Docs/Help & safety

Developer FAQ

The questions that actually come up while integrating — most of them one specific gotcha in the wire contract, answered once and for all.

Debugging a specific error?

This page answers conceptual questions. For a symptom → cause → fix table (403s, zero fills, CORS, rate limits…), see Troubleshooting instead.

Is the api_key safe to embed in a shipped client app?

+
Yes. It is a public client identifier — like any ad SDK's publisher key — designed to be shipped inside client binaries. It grants no account access and is not a server secret. See Requesting an ad.

My integration never fills, with no error at all. What's wrong?

+
The single most common cause: a default HTTP-client User-Agent (python-requests, okhttp, Java/…, curl/…) is on the backend's bot/fraud blocklist, which returns an ordinary {"fill": false} with no error to see. Every official SDK sets an explicit, platform-tagged UA for you — see User-Agent rules if you're building a custom client.

A request with a completely ordinary page_url gets a 403. Why?

+
Your query string almost certainly contains one of the WAF's blocked substrings — end, open, cast, select, @, etc. — which occur constantly in real URLs (weekend, /opensource, user@…). Ordinary URL-encoding does not hide these substrings; every SDK byte-percent-encodes the value instead. See WAF-safe encoding.

Which ad formats can I actually serve today?

+
Banner, interstitial and native (image). rewarded has no internal-demand fill yet, and video serves over the VAST path, which this SDK generation intentionally excludes. See Getting credentials for the full caveat.

Do I need to call POST /api/v1/serve/impression myself?

+
No — never, for the SDK flow. Impressions for GET /api/v1/serve/ad are recorded server-side automatically when the ad is served. That endpoint exists only for external/VAST integrations and requires six server-known UUIDs; calling it from an SDK integration would double-count. See Wire contract overview.

How do I test my integration without spending real budget or polluting analytics?

+
Every account includes a sandbox mode (the Sandbox tab in the publisher dashboard) that serves real creative payloads with zero billing or tracking side effects. Verify rendering and beacon wiring there before going live — see the Quickstart.

There's no SDK for my stack. What do I do?

+
Two options. Call the wire contract directly — it's a plain REST API, and this reference documents every byte you need to get right (encoding, User-Agent, response parsing). Or, if you already run a header-bidding stack, connect it to the inbound OpenRTB 2.5 endpoint from the publisher dashboard instead of integrating an SDK at all.

House ads have no imp_id — does that mean they're not worth anything?

+
It means they can't be tracked by this SDK's viewability beacon — house ads are backfill inventory with their own advertiser-side tracking baked into click_url (which is the raw, un-wrapped destination). Skip the viewability beacon for them; everything else renders the same as an internal image ad. See Response shapes.

How does versioning work — what happens if the contract changes?

+
SDKs follow SemVer independently but all track the wire contract's major version (v1 today). A breaking wire change bumps the major version of every SDK at once, so you can pin a major version and integrate with confidence. See Wire contract overview.

Can I point an SDK at a staging environment?

+
Yes — every SDK exposes baseUrl/base_url as a constructor option, defaulting to the production https://api.adx.theaimart.co. Point it at your own staging host to test against a non-production backend.