Reference
HTTP API
Send logs, metrics, events and heartbeats from any language, and read your logs, metrics and monitors with a personal API key.
Everything the SDKs and the dashboard do goes through one HTTP API at https://api.logdash.io. Use it from a language without an SDK, from a shell script, or to read your data into your own tools. Requests and responses are JSON.
Authentication
Sending data and reading data use different keys, so the key on your servers can never read anything. See Keys and IDs.
| To | Send | Header |
|---|---|---|
| Send logs, metrics and app events | The ingest key of the domain | project-api-key: ldi_… |
| Read your data | A personal API key | Authorization: Bearer ldp_… |
| Ping a heartbeat, read a status page | Nothing. These endpoints are public. | - |
Errors
Errors answer with a status code and a JSON body. message is a string, or a list of strings when the body has more than one problem.
{
"message": "Invalid API key",
"error": "Unauthorized",
"statusCode": 401
} | Status | Means |
|---|---|
400 | The body or a query parameter is not valid, such as a missing field or a field the endpoint does not know. |
401 | The key is missing, wrong, revoked or expired. |
403 | The personal API key lacks the scope, or does not reach the domain. |
404 | The monitor, metric or status page does not exist. |
409 | A plan limit is reached, such as the number of apps or metrics. |
429 | Too many requests. Wait for the window to end and try again. |
Logs
Send a log
curl -X POST https://api.logdash.io/logs \
-H "project-api-key: $LOGDASH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"createdAt": "2026-11-09T10:15:00.000Z",
"level": "error",
"message": "Payment failed for order 1042",
"namespace": "billing",
"app": "api"
}' | Field | Type | Description |
|---|---|---|
createdAt | string, required | When it happened, in ISO 8601. |
level | string, required | One of error, warning, info, http, verbose, debug or silly. See Levels. |
message | string, required | The text of the log. Longer than 4,096 characters is cut. |
namespace | string | A part of your app, such as billing. Up to 255 characters. |
app | string | The app that sent it. Defaults to default. See Apps. |
sequenceNumber | number | Orders logs that share the same createdAt. The SDKs set it for you. |
A sent log answers 201 with {"success": true}. Fields the endpoint does not know answer 400.
Send a batch
Send 1 to 100 logs in one request to POST /logs/batch. Each item takes the same fields as a single log.
{
"logs": [
{ "createdAt": "2026-11-09T10:15:00.000Z", "level": "info", "message": "Job started" },
{ "createdAt": "2026-11-09T10:15:02.000Z", "level": "info", "message": "Job finished" }
]
} Log limits
- Each app can send a fixed number of logs per hour. Past it, logs answer
429with "Rate limit exceeded" until the hour ends. - A log for a new app past the apps limit of your plan answers
409with "You have reached the maximum number of apps for your plan". - Request bodies can be up to 2 MB. The endpoints accept requests from any origin, so a browser can send logs too.
Metrics
curl -X PUT https://api.logdash.io/metrics \
-H "project-api-key: $LOGDASH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "queue_length", "value": 42, "operation": "set", "app": "worker"}' | Field | Type | Description |
|---|---|---|
name | string, required | The name of the metric. Up to 255 characters. |
value | number, required | The value to set, or to add. |
operation | string, required | set replaces the value. change adds to it. See Set or change. |
app | string | The app the metric belongs to. Defaults to default. |
A value answers 200 with {"success": true}. A new metric past the metrics limit of the app answers 409.
App events
Send web analytics events from your backend or a native app to POST /events with the ingest key. The fields and examples are on Events from your apps.
Heartbeats
Ping a heartbeat monitor with POST /ping/<monitor-id>. It needs no key. See Cron and heartbeats.
Read your data
Read endpoints take a personal API key with the matching scope, and most of them a domain ID. To find it, open your domain, go to Settings and press Copy domain ID in the Domain card.
export LOGDASH_PERSONAL_KEY="ldp_…"
export LOGDASH_DOMAIN_ID="6650f1c2a3b4c5d6e7f80a01" Read logs
Needs Logs: Read. Returns the newest logs first.
curl -G "https://api.logdash.io/clusters/$LOGDASH_DOMAIN_ID/logs" \
-H "Authorization: Bearer $LOGDASH_PERSONAL_KEY" \
--data-urlencode "levels=error" \
--data-urlencode "searchString=payment failed" \
--data-urlencode "limit=20" | Parameter | Description |
|---|---|
limit | 1 to 100 logs. Defaults to 50. |
startDate, endDate | ISO 8601 dates. A start before the retention of your plan moves up to it. |
levels | Only these levels. Repeat it for more than one, such as levels=error&levels=warning. |
namespaces | Only these namespaces. Repeat it for more than one. |
apps | Only these apps, by name. Repeat it for more than one. |
searchString | Only logs that contain every word, in any case. |
lastId, direction | Pages from a log. direction=before returns older logs, direction=after newer ones. Send both or neither. |
[
{
"id": "6650f1c2a3b4c5d6e7f80c21",
"createdAt": "2026-11-09T10:15:00.000Z",
"message": "Payment failed for order 1042",
"level": "error",
"sequenceNumber": 0,
"namespace": "billing",
"app": "api"
}
] To read the next page, send the id of the last log you got as lastId, with direction=before. An empty list means there is nothing older.
Follow logs live
Needs Logs: Read. GET /clusters/<domain-id>/logs/sse streams each new log of the domain as a server-sent event, with the fields above. Send lastId to first get up to 100 logs that arrived after it.
curl -N "https://api.logdash.io/clusters/$LOGDASH_DOMAIN_ID/logs/sse" \
-H "Authorization: Bearer $LOGDASH_PERSONAL_KEY" Read metrics
Needs Metrics: Read. GET /clusters/<domain-id>/metrics lists the metrics of the domain with their current value and app.
[
{
"id": "6650f1c2a3b4c5d6e7f80b11",
"name": "queue_length",
"value": 42,
"metricRegisterEntryId": "6650f1c2a3b4c5d6e7f80b10",
"app": "worker",
"projectId": "6650f1c2a3b4c5d6e7f80a02"
}
] For the history of one metric, call GET /clusters/<domain-id>/metrics/<metricRegisterEntryId>. granularity picks minute, hour or day points, and limit returns up to 1,000 of the newest. Each point has its date and value.
curl "https://api.logdash.io/clusters/$LOGDASH_DOMAIN_ID/metrics/<metricRegisterEntryId>?granularity=hour&limit=24" \
-H "Authorization: Bearer $LOGDASH_PERSONAL_KEY" Read monitors
Needs Monitors: Read. GET /clusters/<domain-id>/http_monitors lists the monitors of the domain with their lastStatus: up, down or unknown. GET /clusters/<domain-id>/monitors/<monitor-id>/http_pings returns the newest checks of one monitor, up to 160 with limit, 100 by default.
{
"id": "6650f1c2a3b4c5d6e7f80d31",
"httpMonitorId": "6650f1c2a3b4c5d6e7f80912",
"statusCode": 200,
"responseTimeMs": 184,
"createdAt": "2026-11-09T10:15:00.000Z"
} Read an overview
Needs Domains: Read. GET /overview answers "is anything wrong?" across every domain the key reaches, and GET /clusters/<domain-id>/overview for one domain. It returns the error logs per app, the status of each monitor, the number of monitors that are down, and when each app last sent a log and a metric. since sets the window, such as 30m, 24h or 7d. It defaults to 1h.
curl "https://api.logdash.io/overview?since=24h" \
-H "Authorization: Bearer $LOGDASH_PERSONAL_KEY" Read web analytics
Read web analytics through the MCP server. It takes the same personal API key, with Web analytics: Read.
Status pages
GET /v1/status_pages/<status-page-id> returns a published status page as JSON. It needs no key. See Build your own.