Skip to content
adscapi

Any language

adscapi ships no per-language SDK. For Python, Ruby, Go, PHP, Rust, or anything else: deploy the hosted relay and POST one event, or shell out to the CLI from CI.

Option A — Hosted relay

The Cloudflare Worker in worker/ keeps platform secrets on the Worker. Callers only need a shared bearer token. One HTTP call fans out to every configured destination.

shell
cd worker
npx wrangler secret put RELAY_AUTH_TOKEN
npx wrangler secret put META_CAPI_TOKEN
npx wrangler secret put META_PIXEL_ID
# …every platform secret you need
npx wrangler deploy
shell
curl -X POST https://<your-worker>/track \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "purchase",
    "value": 49,
    "currency": "USD",
    "user": { "email": "a@b.com" },
    "consent": { "adUserData": true, "adPersonalization": true }
  }'

# Log the fan-out without sending:
curl -X POST "https://<your-worker>/track?dryRun=1" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"purchase","consent":{"adUserData":true,"adPersonalization":true}}'

GET / is an unauthenticated health check. Platform secrets never travel in the request body.

Python example

python
import os, requests

resp = requests.post(
    "https://<your-worker>/track",
    headers={
        "Authorization": f"Bearer {os.environ['RELAY_AUTH_TOKEN']}",
        "Content-Type": "application/json",
    },
    json={
        "name": "purchase",
        "value": 49,
        "currency": "USD",
        "user": {"email": "a@b.com"},
        "consent": {"adUserData": True, "adPersonalization": True},
    },
    timeout=15,
)
print(resp.json())  # { "results": [ { "platform": "meta", "ok": true }, … ] }

Durable delivery

POST /track/async enqueues the event and returns 202 immediately. A queue consumer runs the same fan-out; Cloudflare retries failed messages. Requires queue bindings — see the worker README. If the queue binding is missing, /track/async returns 503 (it does not fall back to inline /track).

shell
# Enqueue and return 202 immediately (requires queue bindings — see worker/README.md)
curl -X POST https://<your-worker>/track/async \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"purchase","value":49,"currency":"USD","user":{"email":"a@b.com"},"consent":{"adUserData":true,"adPersonalization":true}}'

Option B — CLI

Shell out from CI, cron, or any backend that can run a subprocess. Secrets come from the process environment.

shell
# From CI, a cron job, or any shell — no JS runtime in your app required
npx adscapi platforms
npx adscapi check
npx adscapi verify
npx adscapi test-event --event purchase --email you@example.com --dry-run
npx adscapi offline --platform bing --file conversions.csv
npx adscapi creatives upload --platform meta --image https://cdn.example.com/hero.jpg

When to use which

  • Relay — live conversion traffic from a non-JS backend; secrets stay off the app servers.
  • CLI — batch jobs, offline CSV uploads, credential checks in CI, one-off test events.
  • SDK — you’re already on Node, Bun, Deno, Next.js, or Workers. See the Node, Next.js, or Workers guides.