SDK # Java SDK `ai.syntermedia:synter-sdk` on Maven Central. A typed Java 17+ client for `POST /api/v1/tools/run`, built on `java.net.http`. Use version 0.1.1 or later. ## Install MavenGradle (Kotlin) ``` ai.syntermedia synter-sdk 0.1.1 ``` If a search says the artifact does not exist search.maven.org and central.sonatype.com can lag behind new releases. The artifact is on Maven Central itself: [repo1.maven.org/maven2/ai/syntermedia/synter-sdk/0.1.1/](https://repo1.maven.org/maven2/ai/syntermedia/synter-sdk/0.1.1/). Maven and Gradle resolve from there, so the search index does not matter. Do not hand-roll an HTTP client because of a search result. From 0.1.1 the POM's project and SCM links point at [github.com/Synter-Media-AI/synter-docs](https://github.com/Synter-Media-AI/synter-docs); 0.1.0 pointed at a repository that no longer exists. ## Authenticate Pass the key to the builder. The SDK sends it as `Authorization: Bearer syn_…` on every request. Read it from the environment; never hardcode it. java ``` import ai.syntermedia.sdk.Synter; Synter synter = Synter.builder() .apiKey(System.getenv("SYNTER_API_KEY")) .build(); ``` | Surface | Accepted | Use | | --- | --- | --- | | REST tools endpoint | Authorization: Bearer syn_…, X-Synter-Key: syn_…, X-API-Key: syn_… | Authorization: Bearer syn_… | | REST resource endpoints | Authorization: Bearer syn_…, X-Synter-Key: syn_… | Authorization: Bearer syn_… | | SDKs (Python, TypeScript, Rust, Java, Go) and the synter CLI | The SDK sets the header for you | Pass 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 block | The package sends Authorization: Bearer syn_… | | Hosted MCP | Browser OAuth (the client sends Authorization: Bearer ), or X-Synter-Key: syn_… for headless clients | OAuth. 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](https://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](https://docs.synterai.com/api/authentication). ## Read: last 7 days of Google Ads performance java ``` import ai.syntermedia.sdk.Synter; import ai.syntermedia.sdk.SynterException; import ai.syntermedia.sdk.requests.GetPerformanceRequest; import ai.syntermedia.sdk.requests.ListCampaignsRequest; import java.util.Map; public class PerformanceReport { public static void main(String[] args) { Synter synter = Synter.builder() .apiKey(System.getenv("SYNTER_API_KEY")) .build(); try { Map campaigns = synter.campaigns().list( ListCampaignsRequest.builder() .platform("google") .status("ENABLED") .build()); Map performance = synter.analytics().getPerformance( GetPerformanceRequest.builder() .platform("google") .dateRange("LAST_7_DAYS") .build()); System.out.println(performance.keySet()); } catch (SynterException error) { System.err.println("Request failed (status " + error.getStatus() + ", code " + error.getCode() + ")"); } } } ``` `getPerformance` sends the REST script `pull_google_ads` with `--days 7`. `pull_google_ads_performance` is the hosted MCP tool name, not a REST script name. ## Write: pause a campaign and change its daily budget Both calls change a live Google Ads campaign. In 0.1.1 the `platform` argument is required but the request always goes to Google Ads. Use the REST endpoints below for other platforms. java ``` import java.util.Map; String campaignId = "1234567890"; // Pause (Google Ads) Map paused = synter.campaigns().pause(campaignId, "google"); // Change the daily budget to 75.00 in the account currency. // 0.1.1's campaigns().updateBudget(...) sends --budget, which the API rejects // with 400 UNRECOGNIZED_ARGS before anything runs. Use execute() until the // next release: Map budget = synter.execute( "update_campaign_budget", Map.of("campaign_id", campaignId, "daily_budget", 75.0), "google"); if ("pending_review".equals(budget.get("status"))) { // Held by the safety gate: nothing ran. See "Writes the safety gate holds". System.out.println("Waiting for approval: " + budget.get("audit_id")); } ``` `execute(scriptName, args, platform)` turns each map key into a flag (`daily_budget` becomes `--daily-budget`). 2xx responses, including 202, come back as a `Map`; anything else throws `SynterException`. 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](https://docs.synterai.com/mcp/approval-model) for who approves what and where. ## Errors | HTTP | Meaning | What to do | | --- | --- | --- | | 400 | Invalid arguments, for example UNRECOGNIZED_ARGS | Fix the arguments. Rejected before submission; nothing is charged. | | 401 | Missing or invalid key | Check SYNTER_API_KEY | | 402 | Not enough credit, or a payment method is needed for a launch | Read the response body; check billing. Do not retry blindly. | | 403 | Missing scope, workspace access, or a safety-policy block | Check the key's scopes and the status field | | 429 | Rate limited | The SDK retries up to three times and honors Retry-After | Was this page helpful? YesNo [Previous Rust SDK](https://docs.synterai.com/sdk/rust) [Next Go SDK](https://docs.synterai.com/sdk/go) --- Source: https://docs.synterai.com/sdk/java Full docs as one file: https://docs.synterai.com/llms-full.txt