View as Markdown
SDK

Go SDK

Not published yet

The Go SDK is built but has not been released to the Go module proxy, so go get will not resolve it today. Until it ships, call the REST API from Go with net/http (example below). The SDK code further down shows the planned surface.

Today: REST from Go

go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

func main() {
	body, _ := json.Marshal(map[string]any{"daily_budget": 75.0, "platform": "GOOGLE"})
	req, _ := http.NewRequest(http.MethodPatch,
		"https://api.synterai.com/v1/campaigns/1234567890/budget", bytes.NewReader(body))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("SYNTER_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var out map[string]any
	json.NewDecoder(resp.Body).Decode(&out)
	// 200 = applied. 202 with error "APPROVAL_REQUIRED" = held or refused by
	// the safety gate (see safety_gate_action); nothing ran.
	fmt.Println(resp.StatusCode, out["success"], out["error"])
}

Pause works the same way with POST /v1/campaigns/{id}/pause. See Pause Campaign and Update Budget.

SurfaceAcceptedUse
REST tools endpointAuthorization: Bearer syn_…, X-Synter-Key: syn_…, X-API-Key: syn_…Authorization: Bearer syn_…
REST resource endpointsAuthorization: Bearer syn_…, X-Synter-Key: syn_…Authorization: Bearer syn_…
SDKs (Python, TypeScript, Rust, Java, Go) and the synter CLIThe SDK sets the header for youPass the key to the client. Every SDK sends Authorization: Bearer syn_…
Local stdio MCP (npm @synterai/mcp-server)Set SYNTER_API_KEY in the server's env blockThe package sends Authorization: Bearer syn_…
Hosted MCPBrowser OAuth (the client sends Authorization: Bearer <OAuth access token>), or X-Synter-Key: syn_… for headless clientsOAuth. Headless: X-Synter-Key. Do not put an API key in Authorization on this host.

Keys start with syn_ (sandbox keys with syn_test_). Create one at synterai.com/developer, keep it in SYNTER_API_KEY or a secret store, and send one header per request. On the hosted MCP endpoint, the Authorization header is reserved for the OAuth token the client gets from browser sign-in, so a failed key there shows up as a sign-in prompt rather than a key error. Use X-Synter-Key when you connect a hosted MCP client with a key. Details: Authentication.

Planned SDK surface

Once released, the client sends Authorization: Bearer syn_… to /api/v1/tools/run. Pause and budget calls go to Google Ads regardless of the platform argument.

go
client := synter.NewClient(os.Getenv("SYNTER_API_KEY"))
ctx := context.Background()

// Pause (Google Ads)
paused, err := client.Campaigns.Pause(ctx, "1234567890", "google")

// Change the daily budget. Execute uses map keys as flags verbatim.
result, err := client.Execute(ctx, "update_campaign_budget", map[string]any{
	"--campaign-id":  "1234567890",
	"--daily-budget": 75.0,
}, "google")
if err == nil && result["status"] == "pending_review" {
	fmt.Println("Held for approval, nothing ran:", result["audit_id"])
}

Writes the safety gate holds or refuses

With the default workspace policy, pausing a campaign and changing a budget run straight away and are recorded in the audit log. Enabling or resuming a campaign, deleting or removing anything, sending creative to a platform, and creating new campaigns can be held for approval. A held write returns HTTP 202 with status: "pending_review", an audit_id and the exact reviewed_args. Nothing has run at that point. The SDKs return this body as a normal result, so check status before you report success.

A write the policy refuses (blocked tool, outside operating hours, over a monetary limit) returns HTTP 403 with status: "blocked", and the SDKs raise their error type. Approval cannot override a block.

An API key cannot approve its own pending write. See Approval model and safety controls for who approves what and where.

Was this page helpful?