Errors · Reference
API
The calls the Laravel SDK makes, for an app in another language or a deploy script of your own: send errors, check in, mark a release live, upload its source maps, erase a person's data.
Basics
| Base URL | https://services.my-beast.com/errors, your MYBEAST_ERRORS_URL. Every path below follows it. |
| Authentication | Authorization: Bearer sk_…: a server secret from Errors' Settings → Keys. It names the project. |
| Format | JSON in UTF-8. Send Accept: application/json, so a refusal comes back as JSON with a message. |
| Ids | A person's or an account's id is 1 to 64 of A-Z a-z 0-9 . _ : -, as your app knows them. Never a name or an e-mail. |
| Rate | 1200 requests a minute per secret on /v1/…, 120 on /api/v1/…. |
| Call | What it does |
|---|---|
POST /v1/errors | Send a batch of errors |
POST /v1/checkins | Say the app can reach Errors |
POST /api/v1/releases | Mark a release live |
PUT /api/v1/releases/{version}/files/{kind}/{name} | Upload a source map |
DELETE /api/v1/subjects/{subject} | Erase a person |
DELETE /api/v1/accounts/{account} | Erase an account |
A server secret is for servers
Send a batch of errors
POST /v1/errors with {"events": [...]}: up to 100 events, and gzip with Content-Encoding: gzip if you like. Scrub personal data before you send it; Errors scrubs again on arrival.
| Field | Type | What it is |
|---|---|---|
event_idrequired | string | A UUID you make. Sending the same one again is harmless: it's stored once. Its last 8 hex digits are the reference a person quotes. |
occurred_atrequired | string | ISO 8601 with milliseconds and an offset: 2026-11-01T09:14:03.120+00:00. |
exception_classrequired | string | The exception's class, up to 255 characters. |
messagerequired | string | Its message, scrubbed of personal data. |
exceptionsrequired | array | The exception and the ones before it, outermost first: each {class, message, frames}, the frames newest first, each {file, line, function, in_app}. Issues are grouped by the top frame with in_app: true. |
environmentrequired | string | 1 to 32 of a-z 0-9 _ -. |
level | string | warning, error or fatal. |
platform | string | php, javascript or other. |
release | string | The build, up to 64 characters. |
transaction | string | The route, job or command that was running. |
request_method | string | GET, POST and so on. |
request_url | string | The path and the query's keys, never its values. |
request_id | string | The request's id as your log lines carry it, so the issue opens those lines in Logs. |
subject | string | The person's id in your app, 1 to 64 of A-Z a-z 0-9 . _ : -. Never a name or an e-mail. |
account | string | Their account's id (a team, a workspace), as subject. |
internal | boolean | true for staff, demo and test accounts: never counted as customers or alerted about. |
fingerprint | array | Your own grouping, instead of Errors': events with the same strings are one issue. |
Optional fields may be left out or null. context takes free-form JSON, shown on the event; its tags (string to string) feed an issue's What differs. A context over 64 KB is cut down to its tags.
curl https://services.my-beast.com/errors/v1/errors \
-H "Authorization: Bearer $MYBEAST_ERRORS_SECRET" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"events": [{
"event_id": "0193f1c2-5b7e-7a41-9d2e-6f3c1a8b9e04",
"occurred_at": "2026-11-01T09:14:03.120+00:00",
"platform": "other",
"level": "error",
"exception_class": "KeyError",
"message": "missing key: plan",
"exceptions": [{
"class": "KeyError",
"message": "missing key: plan",
"frames": [
{ "file": "app/billing.py", "line": 42, "function": "charge", "in_app": true }
]
}],
"environment": "production",
"release": "4f2a9c81d0e3",
"transaction": "POST /checkout",
"subject": "1042"
}]
}'{
"accepted": 1,
"duplicates": 0,
"refused": []
}The answer counts each event: accepted, duplicates (an event_id sent before, stored once) and refused, each with its event_id and reason. A refused event never fits: don't send it again. Past the project's monthly limit the rest are refused with the reason monthly-limit until the 1st (UTC). An event older than the project keeps events is refused; one from the future is placed at now.
Say the app can reach Errors
POST /v1/checkins. Send one an hour, so an environment with no errors can be told from one that can't reach Errors: an environment heard before and silent for 3 hours is reported as gone quiet.
| Field | What it is |
|---|---|
environmentrequired | 1 to 32 of a-z 0-9 _ -. |
sdkrequired | What sends: 1 to 32 of a-z 0-9 _ . -. |
sdk_version, release, runtime | Up to 64 characters each, shown on the project's overview. |
test | true when a person runs it by hand: the overview says so. |
curl https://services.my-beast.com/errors/v1/checkins \
-H "Authorization: Bearer $MYBEAST_ERRORS_SECRET" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"environment": "production", "sdk": "billing-worker", "sdk_version": "1.4.0", "release": "4f2a9c81d0e3"}'{
"heard": true,
"project": "shop",
"environment": "production"
}Mark a release live
POST /api/v1/releases with version (1 to 64 of A-Z a-z 0-9 . _ + -) and environment, once the release serves requests there. The "it's fixed" notices waiting for a newer release go out, and notified says to how many people (Tell the people it hit).
curl https://services.my-beast.com/errors/api/v1/releases \
-H "Authorization: Bearer $MYBEAST_ERRORS_SECRET" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"version": "4f2a9c81d0e3", "environment": "production"}'{
"version": "4f2a9c81d0e3",
"environment": "production",
"notified": 2
}Upload a source map
PUT /api/v1/releases/{version}/files/sourcemap/{name}, the map's raw bytes as the body. name is the bundle's file name with .map, such as app-3fA9xQ1z.js.map. A map must be JSON, up to 20 MB. Upload it before the release's errors arrive: a stack is mapped when the error comes in (Source maps).
curl -X PUT https://services.my-beast.com/errors/api/v1/releases/4f2a9c81d0e3/files/sourcemap/app-3fA9xQ1z.js.map \
-H "Authorization: Bearer $MYBEAST_ERRORS_SECRET" \
-H "Accept: application/json" \
--data-binary @storage/app/private/sourcemaps/app-3fA9xQ1z.js.map{
"name": "app-3fA9xQ1z.js.map",
"size": 482113,
"sha256": "9c1f…"
}Erase a person
DELETE /api/v1/subjects/{subject}: every error event of that person, what your app was asked to tell them, their entries in webhook deliveries, and a mark of them as your own. erased counts the rows that went or were emptied; erasing again answers 0. The project's audit log records the erasure, never the id.
curl -X DELETE https://services.my-beast.com/errors/api/v1/subjects/1042 \
-H "Authorization: Bearer $MYBEAST_ERRORS_SECRET" \
-H "Accept: application/json"{
"erased": 37
}Erase an account
DELETE /api/v1/accounts/{account}: every error event of that account, whoever it happened to, and its people in webhook deliveries. Answered as erasing a person.
Errors
| Status | What it means |
|---|---|
| 400 | The body isn't what the call takes: not JSON, not gzip when it says so, or not {"events": [...]}. The message says which. |
| 401 | No server secret, or one that isn't one of the project's Errors keys: revoked, another product's, or mistyped. |
| 402 | The project's subscription has ended. The answer's link leads to where it is renewed. |
| 404 | A path Errors doesn't have, or an id to erase that no event can have. |
| 413 | Too big: more than 100 events, more than 2 MB as sent or 16 MB unpacked. |
| 422 | A field Errors refuses, such as a release that isn't 1 to 64 of A-Z a-z 0-9 . _ + -. The message says why. |
| 429 | Too many requests in a minute with this secret. Wait and send again. |
A 5xx or a timeout is worth trying again: an event sent twice with the same event_id is stored once. The browser SDK and the Laravel SDK's performance samples use two more paths, /v1/browser-errors and /v1/transactions; they are the SDKs' own.