Docs/Help & safety

Troubleshooting

Find your symptom, get the exact fix. Almost every integration problem people hit turns out to be one of these ten things.

First: the 60-second checklist

Before digging deeper, confirm these five things — they cover the vast majority of reported issues:

  1. You're using an official SDK, or you've set an explicit, non-default User-Agent — see User-Agent rules.
  2. You're passing a real, active slot_id — check it in the publisher dashboard, and confirm the Slot's format is banner, interstitial, or native (not rewarded/video).
  3. You haven't hand-rolled URL-encoding for page_url/page_keywords — see WAF-safe encoding.
  4. You're not refreshing more often than every 30 seconds per Slot.
  5. You've checked whether Sandbox mode is on when you didn't mean it to be (or off when you did).
bash
# Sanity-check the raw endpoint outside your app entirely:
curl -v "https://api.adx.theaimart.co/api/v1/serve/ad?api_key=pk_...&slot_id=..." \
  -H "User-Agent: theaimart-adx-node/1.0.0" \
  -H "Accept: application/json"
# Read the actual HTTP status + body before assuming your app code is the problem.

Symptom → cause → fix

Every request returns { fill: false } — 100% no-fill, no errors anywhere

CauseAlmost always the User-Agent. Your HTTP client's default UA (python-requests, okhttp, curl/…, Java/…) is on the backend's bot blocklist, which returns an ordinary no-fill with zero indication anything is wrong.FixUse an official SDK (it sets this for you), or set an explicit User-Agent header yourself that doesn't contain any of the blocked substrings. Full list: User-Agent rules.

Requests that used to work suddenly 403 with "Request blocked due to security policy"

CauseYour page_url/page_keywords contains a substring the WAF treats as SQL-injection-shaped — end, open, select, @, etc. These show up in totally ordinary URLs (/weekend-sale, ?ref=open).FixByte-percent-encode the value instead of using ordinary URL-encoding — every official SDK does this automatically. See WAF-safe encoding if you're building a custom client.

Web SDK: fetch fails with a CORS error in the browser console

CauseThe backend currently only allows cross-origin serving from adx.theaimart.co/theaimart.co. Serving directly from an arbitrary publisher domain isn't supported yet.FixSee the CORS note on the Web SDK page. Native mobile/server SDKs are unaffected — this is web-browser-only.

House ads never fire a viewability beacon / impId is always null for them

CauseThis is expected, not a bug. House ads are un-tracked backfill inventory by design — they carry no imp_id.FixGate your beacon call on ad.isTrackable (equivalent to impId != null) instead of just ad.filled — see Response shapes.

429 Too Many Requests, or ads suddenly stop appearing after working fine

CauseYou're refreshing faster than the 30-second floor, or you have several Slots on one page all polling independently and blowing through the per-IP/per-key rate limit.FixNever set a refresh interval below 30s (SDKs clamp this automatically). Respect any Retry-After header before retrying. See Rate limits & errors.

An OpenRTB/HTML creative renders blank, or throws a script error in the console

CauseThe markup expects to run in a normal page context (reading cookies, calling window APIs) but every SDK deliberately renders it in a sandboxed iframe/WebView with no allow-same-origin and no JS bridge.FixThis is intentional — see the security model. Don't widen the sandbox to work around it; if a specific DSP's creative is broken, report it to your account contact rather than loosening the sandbox for all creatives.

A click_url does nothing when tapped/clicked

CauseIts scheme wasn't http/https (e.g. a stray javascript: or intent: URL from a hostile or malformed creative) and every SDK deliberately refuses to navigate to it.FixThis is a safety feature, not a bug — see Navigation / URL safety in the security model. The image still renders; only the link is dropped.

Server-side integration (Node/Python/Rust): fill rate is far lower than the same traffic gets in a plain browser

CauseYou're forwarding your server's own User-Agent/IP for every user instead of each end user's real UA/IP — every impression looks like one datacenter device, which gets fraud-scored down.FixPass the incoming request's real User-Agent and X-Forwarded-For/client IP through to requestAd/request_ad on every call. See Requesting an ad.

Sandbox mode isn't behaving differently from production

CauseSandbox is a per-account/per-request toggle in the dashboard, not automatic based on environment — it needs to be explicitly turned on for the account or test call you're making.FixEnable it from the Sandbox tab in the publisher dashboard, then re-test. See the Quickstart.

A rewarded or video slot never fills

CauseExpected on the current backend: rewarded has no internal-demand fill yet, and video serves over the VAST path, which this SDK generation intentionally excludes.FixUse banner, interstitial, or native format slots for now. See Getting credentials.

Still stuck?

Re-read Core concepts if any of the terms above are unfamiliar, check the FAQ for conceptual questions this page doesn't cover, or email support@theaimart.co with the raw request and response from the sanity-check curl above — that single pair of status code + body resolves most tickets immediately.