API Logs
Inspect every request made to the Sendry API for your organization — historical list + a real-time SSE stream.
Sendry persists one row in api_request_logs for every authenticated /v1/* request your organization makes, including method, path, status code, duration, user agent, and a scrubbed copy of the request / response bodies. The endpoints below let you list historical rows and subscribe to a real-time tail.
All endpoints require read_only scope.
Sensitive fields (key, secret, token, password, apiKey, api_key) and bulk content fields (html, text) are redacted in the persisted bodies. Recipient arrays (to, cc, bcc) are reduced to a count string. /v1/analytics/*, tracking endpoints, and the /v1/logs/* endpoints themselves are intentionally not logged.
List API request logs
GET /v1/logs/api-requests
Requires read_only scope.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Results per page (1–100). |
cursor | string | Opaque cursor from a previous response's next_cursor. | |
method | string | Filter by HTTP method (GET, POST, PATCH, DELETE). | |
status_code | number | Filter by exact status code. | |
path | string | Filter by request path (substring match). | |
q | string | Case-insensitive search across path and method. |
Example request
curl -G https://api.sendry.online/v1/logs/api-requests \
-H "Authorization: Bearer $SENDRY_API_KEY" \
--data-urlencode "method=POST" \
--data-urlencode "limit=50"
Response
{
"data": [
{
"id": "log_abc123",
"org_id": "org_xyz789",
"api_key_id": "key_def456",
"method": "POST",
"path": "/v1/emails",
"status_code": 200,
"request_body": {
"from": "noreply@example.com",
"to": "[1 recipient]",
"subject": "Welcome",
"html": "[redacted]"
},
"response_body": { "id": "email_ghi789" },
"duration_ms": 142,
"user_agent": "sendry-sdk/0.4.1",
"created_at": "2026-05-31T14:22:01.412Z"
}
],
"has_more": true,
"next_cursor": "log_abc123",
"total": 12483
}
Stream API request logs (Server-Sent Events)
GET /v1/logs/api-requests/stream
Requires read_only scope.
Opens a long-lived Server-Sent Events stream. On connect the server emits a single connected event, then one data: line per persisted API request for your organization, plus a :heartbeat comment every 15s to keep proxies and load balancers from idling out the connection.
For lightweight delivery the streamed payload omits request_body and response_body. To inspect a body, take the id from the stream and fetch the row via the list endpoint (or store it client-side and GET /v1/logs/api-requests with a cursor that includes it).
The stream is read-only and per-organization. Closing the underlying connection (browser tab close, network drop, HTTP timeout) tears down the Redis subscription server-side.
Example: curl
curl -N https://api.sendry.online/v1/logs/api-requests/stream \
-H "Authorization: Bearer $SENDRY_API_KEY"
event: connected
data: {"ok":true}
data: {"id":"log_abc123","org_id":"org_xyz789","api_key_id":"key_def456","method":"POST","path":"/v1/emails","status_code":200,"duration_ms":142,"user_agent":"sendry-sdk/0.4.1","created_at":"2026-05-31T14:22:01.412Z"}
:heartbeat
data: {"id":"log_abc124","org_id":"org_xyz789","api_key_id":"key_def456","method":"GET","path":"/v1/domains","status_code":200,"duration_ms":11,"user_agent":"sendry-sdk/0.4.1","created_at":"2026-05-31T14:22:04.108Z"}
Example: browser EventSource
const es = new EventSource("/v1/logs/api-requests/stream", {
withCredentials: true,
});
es.addEventListener("connected", () => {
console.log("live");
});
es.onmessage = (e) => {
const log = JSON.parse(e.data);
console.log(log.method, log.path, log.status_code, `${log.duration_ms}ms`);
};
es.onerror = () => {
// EventSource auto-reconnects; surface a UI indicator here if desired.
};
Streamed event shape
| Field | Type | Description |
|---|---|---|
id | string | Log row id (matches the row in the list). |
org_id | string | Your organization id. |
api_key_id | string | null | The key that signed the request (if any). |
method | string | HTTP method. |
path | string | Request path. |
status_code | number | Response status. |
duration_ms | number | null | Server-side request duration. |
user_agent | string | null | Request User-Agent header. |
created_at | string | ISO 8601 timestamp. |
Errors
| Status | Code | When |
|---|---|---|
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | API key lacks read_only scope |
| 422 | validation_error | Invalid query parameter |