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.