Errors & limits
Everything on this page applies to every endpoint under /api/tracker/.
Authentication
Send your project API key as the X-API-Key header. If your transport cannot set headers — navigator.sendBeacon is the usual case — send it as apiKey in the JSON body instead. The key identifies the project, so no endpoint takes a project id.
Note: The ingest key is designed to be public: it ships in your client-side bundle and anyone can read it. It only permits writes to your project and can never read your data. Treat it like a Google Analytics measurement id, not a secret — and rotate it from Settings if you ever need to cut off a misbehaving client.
Status codes
| Status | Meaning |
|---|---|
| 200 | Accepted |
| 201 | Created — only /release/, when the version was new |
| 400 | Malformed JSON or a missing required field. The body carries a human-readable error |
| 401 | API key missing, unknown, revoked, or the project is deactivated |
| 404 | The referenced deviceId does not exist in this project |
A 400 or 404 carries the application error envelope:
{ "success": false, "error": "deviceId and userId are required." }
A 401is raised before your request reaches the endpoint, so it uses the framework's shape instead — check the status code rather than the body if you are handling both:
{ "detail": "API key required." }
Batching
Only /track/ accepts a batch — pass an array under events. Events are queued and processed asynchronously, so a 200 means accepted, not stored. The response tells you how many were queued:
{ "success": true, "data": { "ok": true, "queued": 12 } }
An empty events array is accepted and returns queued: 0. Duplicate installs are de-duplicated server-side, so retrying a failed batch will not double-count.
Limits
| Limit | Value |
|---|---|
| Request body size | 2.5 MB — the Django default. A larger body is rejected before it reaches the endpoint |
| Events per batch | No hard cap. Stay under the body limit; a few hundred events per request is a sensible ceiling |
| Rate limit | None currently enforced at the application layer |
Note: There is no application-level rate limit today. Do not read that as licence to flood the endpoint — batch your events, and expect a limit to appear here in future.