Ingestion API
These endpoints live outside /api/v1 and are authenticated by the DSN public key,
not by a user token. They are what SDKs, crontabs and browsers talk to.
Authentication
Any of these carries the key:
X-Sentry-Auth: Sentry sentry_version=7, sentry_key=<public_key>
?sentry_key=<public_key> # browser SDKs and non-SDK clients
{"dsn": "https://<key>@<host>/<id>"} # the dsn field of an envelope header (tunnelled)
The key is resolved together with the project id in the path, so a valid key aimed at the
wrong project is rejected the same way a bad key is: 401 Invalid DSN key. Too many requests
in a minute → 429.
Events
POST /api/<project_id>/store/ # a single error event (legacy, still supported)
POST /api/<project_id>/envelope/ # everything (modern default)
Both accept gzip-compressed bodies (Content-Encoding: gzip) and answer 202 Accepted
as soon as the payload is accepted; grouping and storage follow right after. Oversized
payloads are rejected with 413.
Envelope format
Newline-delimited JSON — a header, then per item an item-header line and a payload line:
{"event_id":"9a1f…","sent_at":"2026-01-01T00:00:00Z","dsn":"https://<key>@<host>/<id>"}
{"type":"event","content_type":"application/json"}
{"level":"error","exception":{"values":[{"type":"ValueError","value":"boom"}]}}
Item types Errora consumes:
| Item type | Product |
|---|---|
event | Errors |
transaction | Performance (and AI monitoring for gen_ai.*/mcp.* spans) |
log | Structured logs |
replay_event, replay_recording | Session replay |
check_in | Cron monitoring |
feedback, user_report | User feedback |
profile, profile_chunk | Profiling |
trace_metric, statsd | Metrics |
Cron check-ins
For jobs with no SDK. The key sits in the path, so a crontab line can use it directly.
POST /api/<project_id>/cron/<monitor_slug>/<public_key>/?status=in_progress|ok|error
PUT /api/<project_id>/cron/<monitor_slug>/<public_key>/<check_in_id>/?status=ok|error
Optional query parameters: environment, duration (milliseconds). A POST with
status=in_progress returns the check-in id you close later with the PUT.
Security policy reports
POST /api/<project_id>/security/?sentry_key=<public_key>
Accepts CSP, Expect-CT, Expect-Staple, HPKP and batched Reporting API bodies. Use it as your
report-uri / report-to endpoint — see
Security policy reports.
Crash-report modal
GET /api/embed/error-page/?dsn=<dsn>&eventId=<event_id> → the dialog's JavaScript
POST /api/embed/error-page/?dsn=<dsn>&eventId=<event_id> → stores name/email/comments
A public, unauthenticated-by-session write by design — it runs on your users' pages — so it carries its own per-IP rate limit (10 submissions per minute). Every label is overridable with a query parameter of the same name. See User feedback.
Status codes
| Code | Meaning |
|---|---|
202 | Queued. This is success. |
400 | Malformed payload or envelope |
401 | Bad, missing or deactivated DSN key — or a key that doesn't belong to that project id |
413 | Payload over the size limit |
429 | Rate limited, or ingestion paused because the wallet is past its credit line — the detail field says which |
Debugging a client
# Does the key work at all?
curl -i -X POST "$ERRORA/api/$PROJECT_ID/store/" \
-H "Content-Type: application/json" \
-H "X-Sentry-Auth: Sentry sentry_version=7, sentry_key=$KEY" \
-d '{"event_id":"9a1f4c2e7b8d4a1fa0c3e5d6b7a8c9d0","platform":"other","level":"error",
"exception":{"values":[{"type":"SmokeTest","value":"hello"}]}}'
202 means Errora took the event. If it still doesn't appear in Issues, check the
project's sample rate and the organization's wallet balance.