Troubleshooting: "Everything Returns 200 When I Test with curl"
If every request you send with a bare curl command returns 200 OK - even
ones you'd expect to fail validation, or ones sent with an obviously wrong Secret Key - the bot filter
is almost certainly intercepting the request before it reaches authentication or validation at all.
Why This Happens
The ingestion API runs a bot-detection pipeline (botFilterMiddleware) as the
first middleware in the chain, ahead of CORS, authentication, and request validation.
When a request is classified as a bot, the API responds with:
200 OK
{"status": "ok"}
...and the request is dropped immediately. It never reaches your workspace's authentication check, its
field validators, or your Errors tab - so from the outside, a bot-dropped request and a genuinely
successful request look identical: both return 200 with a small JSON body.
This is intentional. Returning an error status (or a distinguishable body) to a detected bot would
let scripted traffic learn it had been detected and adapt its User-Agent or headers to evade the
filter next time. A uniform 200 OK gives no signal back to the caller.
Why curl Gets Flagged
curl's default User-Agent header is curl/<version> (e.g. curl/8.7.1).
That pattern is matched by the bot filter's crawler/User-Agent detector - the same list that catches
generic HTTP clients, scripts, and scrapers - so an un-customized curl request is classified as a bot
on the User-Agent check alone, regardless of how correct the rest of the request is.
How to Tell the Difference
X-Axitrace-Dropped: bot
A response that carries the X-Axitrace-Dropped: bot header was intercepted by the bot
filter and never processed - regardless of the 200 status code. If that header is
absent, the request reached authentication/validation and a 200 means what it normally
means.
# Include response headers (-i) to check for the bot-drop marker
curl -i -X POST https://stat.axitrace.com/v1/page/view \
-u "sk_live_YOUR_SECRET_KEY:" \
-H "Content-Type: application/json" \
-H "User-Agent: curl/8.7.1" \
-d '{"label": "test", "client": {"customId": "test-user"}, "params": {"url": "https://example.com/"}}'
# Response includes: X-Axitrace-Dropped: bot
# -> the request was NEVER validated or processed, despite the 200
Testing Correctly
Override curl's default User-Agent with something that looks like a real browser or a clearly
identified application - both work, as long as it isn't a bare curl/…,
python-requests/…, Go-http-client/…, etc.
# A realistic browser User-Agent passes the bot filter for manual testing
curl -i -X POST https://stat.axitrace.com/v1/page/view \
-u "sk_live_YOUR_SECRET_KEY:" \
-H "Content-Type: application/json" \
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" \
-d '{"label": "test", "client": {"customId": "test-user"}, "params": {"url": "https://example.com/"}}'
# No X-Axitrace-Dropped header -> the request was actually authenticated and validated.
For real server-side integrations (not manual testing), always send a descriptive application
User-Agent such as MyApp/1.0 - see
HTTP API for the full endpoint reference.
Once you've confirmed the request isn't being bot-dropped, work through the rest of the checklist in Troubleshooting: Event Sent, Nothing Visible - the Errors tab, the ~10s conversion delay, and domain verification.