Logs API
Log endpoints require a Bearer token with the appropriate permission. All endpoints are scoped to the tenant identified by the X-Tenant-ID header.
Permission convention: log:read grants access to all log endpoints.
Base path: https://api.ithbat.io/api/v1/
Logs
System logs record activity across all Ithbat IAM services, including authentication events, admin operations, configuration changes, and infrastructure signals. Logs are immutable and retained for 90 days by default.
GET /api/v1/logs
Permission: log:read
Query logs with optional filters. Results are returned in descending chronological order.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
level | string | No | Filter by severity: info, warn, or error |
source | string | No | Filter by service source (e.g., auth, admin, idp, scim) |
search | string | No | Full-text search against the message field |
startDate | string | No | ISO 8601 timestamp — inclusive lower bound (e.g., 2026-03-01T00:00:00Z) |
endDate | string | No | ISO 8601 timestamp — inclusive upper bound (e.g., 2026-03-19T23:59:59Z) |
page | integer | No | Page number, starting at 1 (default: 1) |
limit | integer | No | Results per page, max 500 (default: 50) |
curl "https://api.ithbat.io/api/v1/logs?level=error&source=auth&startDate=2026-03-01T00:00:00Z&page=1&limit=50" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>"
Response 200
{
"success": true,
"data": {
"logs": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"level": "error",
"source": "auth",
"message": "Failed login attempt — invalid credentials",
"metadata": {
"userId": "u9f8e7d6-c5b4-3a2f-1e0d-9c8b7a6f5e4d",
"email": "[email protected]",
"ip": "102.45.67.89",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
},
"createdAt": "2026-03-18T14:32:07Z"
},
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"level": "error",
"source": "auth",
"message": "MFA verification failed — TOTP code expired",
"metadata": {
"userId": "u3c4d5e6-f7a8-9012-cdef-123456789012",
"email": "[email protected]",
"ip": "41.128.200.15"
},
"createdAt": "2026-03-17T09:11:43Z"
}
],
"total": 248,
"page": 1,
"limit": 50
}
}
Log Entry Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique log entry UUID |
tenantId | string | Tenant the entry belongs to |
level | string | Severity level: info, warn, or error |
source | string | Service that produced the log (e.g., auth, admin, idp, scim) |
message | string | Human-readable description of the event |
metadata | object | Arbitrary key/value context — contents vary by source and event type |
createdAt | string | ISO 8601 timestamp of when the event occurred |
GET /api/v1/logs/stream
Permission: log:read
Stream logs in real-time using Server-Sent Events (SSE). The connection stays open and the server pushes new log entries as they are produced. Accepts the same filter parameters as GET /api/v1/logs to narrow the stream.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
level | string | No | Filter stream to a specific severity level |
source | string | No | Filter stream to a specific service source |
curl "https://api.ithbat.io/api/v1/logs/stream?level=error" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>" \
-H "Accept: text/event-stream"
Response 200 — Content-Type: text/event-stream
Each event is a JSON-encoded log entry preceded by data::
data: {"id":"c3d4e5f6-a7b8-9012-cdef-234567890123","tenantId":"3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a","level":"error","source":"idp","message":"OIDC token introspection failed — provider unreachable","metadata":{"provider":"azure-ad","endpoint":"https://login.microsoftonline.com/token"},"createdAt":"2026-03-19T11:05:22Z"}
data: {"id":"d4e5f6a7-b8c9-0123-defa-345678901234","tenantId":"3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a","level":"warn","source":"auth","message":"Session refresh attempted with expired refresh token","metadata":{"userId":"u7a8b9c0-d1e2-f345-6789-012345678901","ip":"197.32.11.44"},"createdAt":"2026-03-19T11:05:38Z"}
The stream closes with a event: end message if the server-side connection limit is reached. Clients should reconnect using the Last-Event-ID header to resume without gaps.
POST /api/v1/logs/export
Permission: log:read
Request an asynchronous export of log entries matching the given filters. The server queues the export job and returns a download URL once the file is ready. Large date ranges may take up to 60 seconds to process.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
format | string | Yes | Output format: csv or json |
level | string | No | Filter by severity: info, warn, or error |
source | string | No | Filter by service source |
search | string | No | Full-text filter against the message field |
startDate | string | No | ISO 8601 inclusive lower bound |
endDate | string | No | ISO 8601 inclusive upper bound |
curl -X POST "https://api.ithbat.io/api/v1/logs/export" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_id>" \
-H "Content-Type: application/json" \
-d '{
"format": "csv",
"level": "error",
"startDate": "2026-03-01T00:00:00Z",
"endDate": "2026-03-19T23:59:59Z"
}'
Response 202
{
"success": true,
"data": {
"exportId": "exp-e5f6a7b8-c9d0-1234-efab-567890123456",
"status": "processing",
"format": "csv",
"estimatedRecords": 248,
"downloadUrl": null,
"expiresAt": null,
"createdAt": "2026-03-19T11:10:00Z"
}
}
Poll GET /api/v1/logs/export/{exportId} to check status. When status is ready, downloadUrl contains a pre-signed URL valid for 1 hour.
Response 200 — Export ready
{
"success": true,
"data": {
"exportId": "exp-e5f6a7b8-c9d0-1234-efab-567890123456",
"status": "ready",
"format": "csv",
"estimatedRecords": 248,
"downloadUrl": "https://exports.ithbat.io/tenants/3e7a9f12/logs/exp-e5f6a7b8.csv?sig=abc123&expires=1742385000",
"expiresAt": "2026-03-19T12:10:00Z",
"createdAt": "2026-03-19T11:10:00Z"
}
}