Bu sayfanın Türkçesi de var. Türkçe oku →
Read API
The read path is completely separate from the write path: a separate rate limit pool, a separate cache and independent scaling. Ingest traffic never slowing down your dashboard is a direct result of this separation.
Authentication
Read endpoints accept two kinds of credentials:
| Form | Where it is used |
|---|---|
Authorization: Bearer <access-token> |
A user signed in to the dashboard |
X-API-KEY: ebrd_pub_… |
From the browser, from embedded components |
A publishable key is accepted only from origins on its allowed domain list. A
request from anywhere else gets 403; even if the key leaks, it cannot be used on
another site.
Endpoints
| Endpoint | Returns |
|---|---|
GET /api/v1/projects/{id}/summary |
Precomputed summary (event counts, open Issues, monitor status) |
GET /api/v1/projects/{id}/issues |
Issue list (cursor pagination) |
GET /api/v1/projects/{id}/issues/counts |
Counts by status |
GET /api/v1/issues/{id} |
Issue details |
GET /api/v1/issues/{id}/events |
Raw events linked to the Issue |
GET /api/v1/issues/{id}/breakdown |
Breakdown by release/environment/server |
GET /api/v1/projects/{id}/events |
Log search (full text + filters) |
GET /api/v1/projects/{id}/events/histogram |
Time series (time_bucket) |
GET /api/v1/projects/{id}/usage |
Quota usage |
GET /api/v1/projects/{id}/releases |
Events, errors, new errors and regressions per release |
GET /api/v1/projects/{id}/releases/details?release= |
The errors a release introduced and brought back, and the previous release |
GET /api/v1/projects/{id}/dashboards |
Custom dashboards and their chart definitions |
GET /api/v1/projects/{id}/dashboards/{dashboardId}/widgets/{widgetId}/data |
Data of a saved chart |
POST /api/v1/projects/{id}/widget-data |
Data of an unsaved chart |
GET /api/v1/monitors/{id}/uptime |
Uptime percentage and daily breakdown |
GET /api/v1/monitors/{id}/ssl-status |
Certificate status and days left |
GET /api/v1/monitors/{id}/domain-status |
Domain expiry date and registrar |
GET /api/v1/projects/{id}/stream |
Live event stream (SSE) |
GET /status/{slug} |
Public status page (no authentication) |
Cursor pagination
List endpoints have no offset. Pagination uses the base64url-encoded
(timestamp, id) pair of the last row:
curl "https://api.errorbird.com/api/v1/projects/<id>/issues?limit=50" -H "X-API-KEY: ebrd_pub_…"
# { "items": [...], "nextCursor": "MjAyNi0wOC0xOVQyMTowMDowMFo…" }
curl "https://api.errorbird.com/api/v1/projects/<id>/issues?limit=50&cursor=MjAyNi0w…"
When nextCursor is null, the list is complete. The reason there is no offset is
correctness, not performance: if a new event arrives while you are reading page 2,
offset-based pagination skips a record or shows it twice.
Live stream (SSE)
const source = new EventSource(
'https://api.errorbird.com/api/v1/projects/<id>/stream?apiKey=ebrd_pub_…',
)
source.addEventListener('event', (message) => {
console.log(JSON.parse(message.data))
})
Because EventSource cannot send custom headers, the key is taken from the query
string. This path accepts publishable keys only — if a secret key were accepted in
the query string, a key with write access would end up in server logs and browser
history.
Releases
/releases answers "what did this deploy break?". All your events need is the
release field (release in Serilog/CLEF bodies, init({ release }) in the browser
SDK); events without the tag are not listed.
[
{
"release": "[email protected]",
"firstSeen": "2026-10-11T09:02:14Z",
"lastSeen": "2026-10-11T10:27:40Z",
"eventCount": 454,
"errorCount": 194,
"newIssueCount": 2,
"regressionCount": 1
}
]
- Window:
days(default 30, at most 90). The counts andfirstSeenare within the window. The list is sorted by first seen, newest first, with at most 50 releases. - New error: an Issue seen for the first time in this release. Regression: an Issue marked resolved that was reopened by an event from this release. Both count only the Error and Fatal levels; Errorbird groups informational logs too, but "Order received" is not an error a release introduced.
- Breakdown:
/releases/details?release=returns the new errors, the regressions, the errors producing the most events in this release, and a summary of the previous release. The release name goes in the query string, so names with slashes such asweb/1.4.0are valid. If no event came from that release within the window, the response is404 release_not_found. - Latency: counts are read from a continuous aggregate, and the latest events show up immediately. Late events with a past timestamp (e.g. buffered mobile errors) are reflected within 15 minutes at the latest; events with a timestamp older than 3 days do not enter the release counts (they still appear in Issues and log search).
The dashboard's "errors/hour" comparison is calculated from this data: the number of error events divided by the hours between the release's first and last event. The raw count of a release that has been live for a short time cannot be compared with one that has been live for days.
Dashboards
The Dashboards page in the dashboard lets you build your own charts from a project's logs, issues and monitors. Chart data is not stored; it is computed for the selected range (1 hour – 90 days) every time it is opened. The same endpoints can be read with a publishable key, so you can draw the charts in your own panel. Creating and changing dashboards requires a dashboard session (member role); at most 20 dashboards per project and 24 charts per dashboard.
Chart (kind) |
What it shows | Fields |
|---|---|---|
LogVolume |
Log count over time; optional breakdown (top 5 values + "others") | query, minLevel, environment, release, groupBy |
LogCount |
Log count in the range and in the previous range of equal length | query, minLevel, environment, release |
LogTopValues |
The 10 most frequent values of a field | the same filters + required groupBy |
NewIssues |
Issues seen for the first time, over time | minLevel |
MonitorResponseTime |
Average and p95 response time of successful checks | monitorId |
MonitorUptime |
Share of successful checks and the previous range | monitorId |
groupBy: level, environment, release, server, template (message template) or
meta:Field — a property in the log metadata, e.g. meta:TenantId. query uses the
same syntax as log search.
# Data of a saved chart (range: 15m, 6h, 24h, 7d, 90d…; day buckets follow timeZone)
curl "https://api.errorbird.com/api/v1/projects/<project-id>/dashboards/<dashboard-id>/widgets/<widget-id>/data?range=7d&timeZone=Europe/London" \
-H "X-API-KEY: ebrd_pub_…"
# Without saving: send the definition, get its data
curl -X POST https://api.errorbird.com/api/v1/projects/<project-id>/widget-data \
-H "X-API-KEY: ebrd_pub_…" -H "Content-Type: application/json" \
-d '{ "range": "24h", "widget": { "id": "x", "title": "Errors by tenant",
"kind": "LogTopValues", "minLevel": "Error", "groupBy": "meta:TenantId" } }'
{
"kind": "LogVolume", "unit": "count", "bucketSeconds": 10800,
"from": "2026-10-04T12:00:00Z", "to": "2026-10-11T12:00:00Z",
"series": [ { "name": "Error", "points": [ { "time": "2026-10-04T12:00:00Z", "value": 0 }, … ] },
{ "name": "__other__", "points": [ … ] } ],
"rows": [], "value": 1810, "previousValue": null
}
- Buckets: the range is split into at most ~120 buckets (15 minutes for 24 hours,
3 hours for 7 days, 1 day for 90 days). Empty buckets are 0 for counts and
nullfor response times. - Speed: when the bucket is an hour or wider and the only filter is the level, the
chart reads the hourly continuous aggregate; even 90 days do not scan the raw table.
A text, environment or release filter, or a breakdown other than level, goes to the
raw table and can query at most 31 days (including the comparison range of count
charts); more returns
400 range_too_long_for_filters. A single query over 10 seconds returns400 query_timeout. - Series names: the breakdown value;
__other__is the sum of everything outside the top five,""is logs without a value.countfor charts without a breakdown,avgandp95for response time. - Endpoints:
GET/POST /projects/{id}/dashboards,GET/PUT/DELETE /projects/{id}/dashboards/{dashboardId}(PUT writes the whole chart list, in order),GET …/widgets/{widgetId}/data,POST /projects/{id}/widget-data.
Caching and latency
/summary, /uptime and /ssl-status are cached in Redis and backed by TimescaleDB
continuous aggregates. Measured values: p99 18 ms from the cache, p99 189 ms
with an empty cache (a project with 120,503 events).
With an empty cache, concurrent requests for the same key share a single computation (single flight); N requests do not trigger N separate queries.
Rate limits
The read pool allows 600 requests per minute (per key + origin). Beyond that, the
response is 429. This counter is independent of the write pool.
Public endpoints (status page, plan catalog, SSO discovery) are limited to 120 requests per minute per IP.
Multi-tenant isolation
A request for a resource of another organization/workspace returns 404, not
403. A 403 confirms that the resource exists, which is an information leak on its
own.