An app can report errors and crashes on its own with one request, so you hear about a problem before anyone files a report. The web widget, the Swift package and the Godot addon use this endpoint; anything else that can send HTTPS can use it directly.
Request
curl -X POST https://stareglare.com/api/v1/errors \
-H "Authorization: Bearer snag_pk_…" \
-H "Content-Type: application/json" \
-d '{
"message": "Cannot read properties of undefined (reading \"id\")",
"stack": "TypeError: …\n at save (notes.js:42:11)",
"kind": "error",
"version": "1.4.2",
"os": "macOS 15.1",
"context": { "screen": "editor" }
}' | Field | Type | What it is |
|---|---|---|
message | string, required | The error message. Identical errors are grouped by kind, message and place in the code. |
stack | string | The stack trace, as text. |
kind | "error" | "crash" | Defaults to "error". |
version | string | Your app's version, for example "1.4.2". The group shows which versions it appeared in. |
url | string | Where it happened, for web pages. |
os | string | The operating system. |
context | object | Key and value pairs of your own: up to 12 keys, 200 characters each. |
app | string | The app's slug, in place of the Authorization header. Used by web pages; see "Who may send". |
Response
{ "ok": true, "group": "…", "new": true } | Status | Meaning |
|---|---|
202 | Accepted. "ok" is false when the occurrence was dropped by a limit, and "reason" says which (see below); "new" is true for an error not seen before. |
400 | No message, the body is not JSON, or the message is only "Script error.", which names nothing. |
401 | No key or slug, an unknown app, or the app only accepts errors sent with its key. |
403 | The request came from a website that is not on the app's list of error sources. |
413 | The body is larger than 64,000 bytes. |
429 | Too many requests: more than 30 in 10 minutes from one address, or 1,500 an hour for one app. |
When a limit drops the occurrence, the answer is still 202, with a reason:
{ "ok": false, "group": null, "new": false, "reason": "daily" } | Reason | Meaning |
|---|---|
allowance | The workspace has used its month's allowance, or has no plan. Recording starts again next month (UTC). |
daily | The workspace has used the most one day may take: a tenth of the month, at least 100. Recording starts again tomorrow (UTC). |
flood | The app has gained 100 new distinct errors in the last hour. Errors it already has are still counted. |
cap | The app holds 1,000 distinct errors and none is resolved to make room. Resolve or delete some in the dashboard. |
The endpoint answers requests from any origin (CORS), so a web page can call it directly.
What happens to an error
- It joins its group in the app's Errors tab, with a count, a 14-day history and the latest stack.
- You can resolve, ignore or reopen a group. A resolved error that happens again reopens itself. Resolved in a version, it reopens only when it happens in a newer one, so people still on the old version don't undo the fix.
- The workspace is emailed about new errors and ones that came back, as one digest an hour, never one email per error.
- Claude can work through them with the
list_errorsandupdate_errortools.
Limits
- Occurrences a month: 1,000 on the trial, 10,000 on Indie, 100,000 on Studio. Past that they are dropped until the month ends.
- One day may use at most a tenth of the month.
- An app gains at most 100 new distinct errors an hour, and keeps at most 1,000.
The endpoint is public, and these limits keep a flood of junk from costing a workspace its month.
Who may send
By default, anyone who knows an app's slug can send errors for it, as with its public report page. The Error capture panel on the app's Settings tab narrows that: accept only requests that carry the app key, and, for browsers, only the websites you list. Neither is a lock, since a key in a web page can be read by anyone; they stop the cheap case and the limits above bound the rest.
Questions
Is the app key a secret?
No. It starts with snag_pk_ and is publishable: it identifies the app when sending errors and when a native app starts a report. It cannot read anything. You can rotate it from the dashboard.
Are individual occurrences stored?
No. Identical errors (same kind, message and place in the code) form one group. StareGlare keeps the group's counters, the versions it appeared in and its latest sample, and nothing else about the visitor.
What happens when the monthly allowance is used up?
Further occurrences are dropped until the month ends, and the response says so with "ok": false and "reason": "allowance". The workspace is emailed once when it reaches 80% of the month and once when it reaches 100%. The allowance is 1,000 occurrences a month on the trial, 10,000 on Indie and 100,000 on Studio.
Does StareGlare symbolicate stack traces or read source maps?
No. The stack is stored and shown as it was sent. StareGlare groups and counts errors; it is not a crash analytics product.