Logs
Send log entries without the SDK, one at a time or in batches of up to 100.
Use these when the SDK doesn’t fit, for example from another language or a log shipper. Authentication and errors are described in the API overview.
Send a batch
POST
/api/v1/{projectId}/logs/batchX-API-Key required. What the SDK uses.
curl -X POST "https://apperioserver.onrender.com/api/v1/your-project-id/logs/batch" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d @logs.json{
"logs": [
{
"level": "info",
"message": "Order placed",
"timestamp": "2026-01-15T12:00:00.000Z",
"service": "billing",
"environment": "production",
"release": "2.4.1",
"data": { "orderId": "order-123" }
},
{
"level": "error",
"message": "Payment failed",
"service": "billing",
"environment": "production",
"error": {
"name": "CardError",
"message": "Card declined",
"stack": "CardError: Card declined\n at charge (billing/charge.py:42)"
}
}
]
}Entry fields
| Field | Type | Notes |
|---|---|---|
level | string, required | trace, debug, info, warn, error or fatal |
message | string, required | 1 to 5,000 characters |
timestamp | string | ISO 8601 in UTC ending in Z, such as 2026-01-15T12:00:00.000Z. Offsets like +01:00 are rejected. Defaults to the time Apperio receives it. |
data | object | Anything you want stored with the entry |
error | object | name (up to 200), message (up to 1,000), and optional stack (up to 10,000), url, lineNumber, columnNumber |
service | string | Up to 100 characters |
environment | string | Up to 50 characters |
release | string | Up to 100 characters |
context | object | Shared details, such as a user ID |
metadata | any | |
eventType | string | error, performance, interaction, network, console, pageview, web-vital, breadcrumb, message or system |
sessionId | string | Up to 100 characters. Groups entries into a session. |
traceId, spanId, correlationId | string | Up to 100 characters each |
url, referrer | string | Up to 2,000 characters each |
userAgent | string | Up to 500 characters |
Fields not in this list are dropped.
Limits
- 1 to 100 entries per request.
- The whole request is rejected with 400 if any entry breaks a rule above. Fix the entry and send the batch again.
- Request bodies can be up to 5 MB.
Response
201, with a result for each entry, in order:
{
"status": "success",
"message": "Batch processing complete: 2 succeeded, 0 failed",
"data": {
"success": 2,
"failed": 0,
"results": [
{ "index": 0, "success": true, "logId": "log-id-1" },
{ "index": 1, "success": true, "logId": "log-id-2" }
]
}
}An entry that passes validation but can’t be stored is reported with "success": false and an error message, while the rest are saved.
Send one entry
POST
/api/v1/{projectId}/logsX-API-Key required.
The body is one entry with the fields above. Here only the required fields and the allowed values of level and eventType are checked; the length limits apply to batches. The response is 201 with the stored entry in data.
curl -X POST "https://apperioserver.onrender.com/api/v1/your-project-id/logs" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"level":"warn","message":"Disk 90% full","service":"worker","environment":"production"}'Sampling
The project’s Settings › Sampling applies to this endpoint only. When an entry is sampled out, the response is
202 with "message": "Log sampled out" and nothing is stored. Batches, and so the SDK, aren’t sampled.What happens to a log
- It is stored as you sent it. Nothing is redacted on the server.
- Entries at
errororfatalare grouped into issues and can notify the project owner, exactly like errors from the SDK. Includeerror.name,error.messageanderror.stackfor good grouping. - Every entry is checked against your alert rules.
- Logs are kept for the project’s retention period, 30 days by default.