Developers · HTTP API

Buy AI ads through an API.

The Admux API buys ads in ChatGPT, Google Search including AI Overviews and AI Mode, and the Gravity network from one prepaid USD balance. Your code or your agent can upload creatives, draft and validate campaigns, get a price, reserve budget, launch and read reports, with a key whose scopes and spending limits you set.

What a key can do

API endpoints by area
AreaEndpoints

Keys can’t top up, refund, manage billing documents, members or other keys: those stay with people in the web app. Reading these docs grants nothing; Admux enforces each key’s scopes and limits on every request.

Quickstart

A ChatGPT ads campaign from upload to submission. The same steps work for Google and Gravity: add them to channels. Admux tests this script against its own API (scripts/examples-api.sh).

Setup
export ADMUX_API_KEY=amx_...   # created in the web app, shown once
API=https://api.admux.ai
AUTH="Authorization: Bearer $ADMUX_API_KEY"
1. What can I buy? Creative rules, minimums and current markup per channel
curl -s "$API/v1/channels" -H "$AUTH" | jq '.channels[] | {id, minBudgetCents}'
2. Upload your own square image (Admux never generates ad content)
IMG=$(curl -s -X POST "$API/v1/assets/images" -H "$AUTH" -H 'content-type: application/json' \
  -d "{\"name\":\"hero.png\",\"contentBase64\":\"$(base64 < hero.png | tr -d '\n')\"}" | jq -r '.version.id')
3. Create an unfunded draft for ChatGPT ads
END=$(date -u -v+7d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d '+7 days' +%Y-%m-%dT%H:%M:%SZ)
DRAFT=$(curl -s -X POST "$API/v1/campaigns" -H "$AUTH" -H 'content-type: application/json' -d "{
  \"name\": \"Spring launch\",
  \"draft\": {
    \"destinationUrl\": \"https://example.com/launch\", \"brandName\": \"Acme Analytics\",
    \"shared\": { \"headline\": \"Find where users drop off\", \"body\": \"Funnels and retention for product teams.\", \"imageVersionId\": \"$IMG\" },
    \"channels\": [\"chatgpt\"], \"budgetCents\": 50000,
    \"targeting\": { \"countries\": [\"US\"], \"languages\": [], \"keywords\": [], \"negativeKeywords\": [], \"contextHints\": [\"product analytics\"], \"platforms\": [] },
    \"schedule\": { \"startMode\": \"asap\", \"startAt\": null, \"endAt\": \"$END\" }
  }
}")
CAMPAIGN=$(echo "$DRAFT" | jq -r '.id'); VERSION=$(echo "$DRAFT" | jq -r '.draftVersion')
4. Validate (no money moves), then get a 15-minute price offer (reserves nothing)
curl -s -X POST "$API/v1/campaigns/$CAMPAIGN/validate" -H "$AUTH" | jq    # {"valid": true, "issues": []}
OFFER=$(curl -s -X POST "$API/v1/campaigns/$CAMPAIGN/offers" -H "$AUTH" | jq -r '.id')
5. Submit: reserves the full budget and sends each leg to review. Retry-safe with the same key.
OP=$(curl -s -X POST "$API/v1/campaigns/$CAMPAIGN/submit" -H "$AUTH" -H 'content-type: application/json' \
  -H "Idempotency-Key: submit-$CAMPAIGN" \
  -d "{\"offerId\":\"$OFFER\",\"expectedDraftVersion\":$VERSION,\"launchMode\":\"review\"}" | jq -r '.operationId')
6. Poll the operation, then read per-leg review and delivery state
curl -s "$API/v1/operations/$OP" -H "$AUTH" | jq '{status}'
curl -s "$API/v1/campaigns/$CAMPAIGN" -H "$AUTH" | jq '.legs[] | {channel, display: .display.label}'
curl -s "$API/v1/balance" -H "$AUTH" | jq

Submitting reserves the full budget and sends each channel leg to review. With launchMode: "review" (the default), approved legs wait for you: call POST /v1/campaigns/{id}/launch with a key that has campaigns:launch, or launch from the web app.

Scopes and presets

Each key gets a preset or a custom set of scopes. An agent sees and can call only what its key allows.

API key scopes
ScopeAllowsIn presets
campaigns:readInspect campaigns, review and delivery states, channel capabilities and customer pricingRead, Draft, Full
campaigns:draftCreate and edit unfunded drafts; no live changes or spending commitmentsDraft, Full
campaigns:validateValidate drafts and request quotes without launchingDraft, Full
campaigns:reserveReserve prepaid funds for review within workspace and key limits (no launch authority)Full
campaigns:launchLaunch reviewed legs or authorize automatic launch of the submitted revisionFull
campaigns:modify_liveApply supported live changes (additional commitments also need reserve)Full
campaigns:pausePause deliveryFull
campaigns:resumeResume paused deliveryFull
campaigns:cancelCancel campaigns or remove authorized legsFull
creatives:readRead supplied assets and copyRead, Draft, Full
creatives:writeUpload supplied assets and create creative versionsDraft, Full
reports:readRead performance reportsRead, Draft, Full
balance:readRead operational available/reserved funds (no billing or payment data)Read, Draft, Full
operations:readRead status of operations on resources you can accessRead, Draft, Full

Spending limits

A key can carry daily, weekly, monthly and lifetime limits in USD. They cap new budget authorizations, such as a submission or a budget increase, per UTC period. They don’t pace delivery, which each channel controls.

A request over the limit fails with KEY_ALLOWANCE_EXCEEDED and reserves nothing. Expired or revoked keys are rejected on every request, pause and cancel included.

Retries and errors

Every request that moves money or changes delivery needs an Idempotency-Key header. Repeating the same key with the same body returns the original result; a different body with that key returns 409.

Errors look like {"error":{"code","message","details"}}, with codes such as OFFER_EXPIRED, VERSION_CONFLICT, INSUFFICIENT_FUNDS, AUTHORITY_DENIED and REVIEW_REQUIRED. Lists use cursor pagination.

Questions developers ask

Is there an API to buy ChatGPT ads?

OpenAI has its own Advertiser API for its ad accounts. The Admux API buys ChatGPT ads together with Google Search (including AI placements) and Gravity, from one prepaid balance and one key, without opening an account with each provider.

Can my agent spend money without me?

Only within its key. Submitting reserves budget and needs campaigns:reserve, launching needs campaigns:launch, and the key’s spending limits cap new budget authorizations. By default approved campaigns wait for an explicit launch.

How do I get an API key?

A workspace owner or campaign manager creates it in the Admux web app, picks a preset (Read, Draft, Full) or custom scopes, and sets optional spending limits. The key is shown once.

Is there an OpenAPI document?

Yes: https://api.admux.ai/openapi.json. The reference at /docs is generated from the same document.