Appearance
Search & Export
Search log entries with full-text queries and filters, or export results as CSV or JSON files.
Base URL: https://app.krafter.dev/api/v1
Search Logs
Search and filter log entries across a project.
GET /logs/searchRequired scope: logs:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id | string | Yes | The project to search in. |
q | string | No | Substring match against the message and the JSON metadata of an entry. |
level | string | No | Filter by log level: debug, info, warn, error, or fatal. |
stream | string | No | Filter by stream name. |
from | string | No | Start of time range (ISO 8601). Defaults to now - 1 hour when omitted. |
to | string | No | End of time range (ISO 8601). Defaults to now when omitted. |
limit | integer | No | Maximum number of entries to return. Default 100; capped at 1000 — values above 1000 are silently clamped. |
Search window: 31 days
from and to may not span more than 31 days, and from on its own is measured against now — from=2025-01-15T00:00:00Z with no to is a request for everything since that date and is refused with 422:
json
{"error": "from and to may not span more than 31 days"}An unbounded window is a full scan of the project's history. Ask for a window you mean and page through it with cursor; export allows a wider one (92 days).
| cursor | string | No | Continue a previous listing: pass back the next_cursor the last response returned, unchanged, together with the same filters. Omit it for the first page. |
Example Request
bash
curl "https://app.krafter.dev/api/v1/logs/search?project_id=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d&level=error&from=2025-01-15T00:00:00Z&to=2025-01-16T00:00:00Z&limit=50" \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": [
{
"timestamp": "2025-01-15T14:23:01Z",
"level": "error",
"stream": "backend",
"service": "api-server",
"message": "Failed to connect to database",
"trace_id": "tr_abc123",
"span_id": "sp_001",
"metadata": {
"host": "db-primary.internal",
"port": 5432,
"retry_count": 3
}
},
{
"timestamp": "2025-01-15T14:23:05Z",
"level": "error",
"stream": "backend",
"service": "api-server",
"message": "Connection pool exhausted",
"trace_id": "tr_def456",
"span_id": "sp_002",
"metadata": {
"pool_size": 20,
"active_connections": 20
}
}
]
}Paging
A response holding more entries than limit carries a next_cursor. Send it back as cursor, with the same filters, to receive the next page; a response without next_cursor is the last page. Paging is keyset-based on (timestamp, entry_id), so entries that share a millisecond are never skipped or repeated, and a deep page costs the same as the first one.
A cursor is bound to the filters that produced it (project_id, q, level, stream, from, to) and expires after one hour. A cursor sent with different filters, an expired one, or a cursor issued by the MCP logs_search tool is refused with 422 and a message saying why.
bash
# First page
curl "https://app.krafter.dev/api/v1/logs/search?project_id=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d&level=error&limit=500" \
-H "Authorization: Bearer kr_live_abc123def456"
# Next page: same filters, plus the cursor from the previous response
curl "https://app.krafter.dev/api/v1/logs/search?project_id=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d&level=error&limit=500&cursor=SFMyNTY.g2gDaAN..." \
-H "Authorization: Bearer kr_live_abc123def456"json
{
"data": [ "…500 entries…" ],
"next_cursor": "SFMyNTY.g2gDaAN..."
}Combining Filters
You can combine multiple filters. All filters are AND-ed together:
bash
# Errors in the "auth" stream over one day. `from` needs a `to` beside it
# whenever it is more than 31 days back — see the window note above.
curl "https://app.krafter.dev/api/v1/logs/search?project_id=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d&level=error&stream=auth&from=2025-01-15T13:00:00Z&to=2025-01-16T13:00:00Z" \
-H "Authorization: Bearer kr_live_abc123def456"bash
# Full-text search for "timeout" across all levels
curl "https://app.krafter.dev/api/v1/logs/search?project_id=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d&q=timeout" \
-H "Authorization: Bearer kr_live_abc123def456"Export Logs
Export log entries as a downloadable CSV or JSON file. Supports the same filters as the search endpoint. Maximum 10,000 entries per export.
GET /logs/exportRequired scope: logs:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id | string | Yes | The project to export from. |
format | string | Yes | Export format: csv or json. |
q | string | No | Substring match against the message and the JSON metadata of an entry. |
level | string | No | Filter by log level: debug, info, warn, error, or fatal. |
stream | string | No | Filter by stream name. |
from | string | No | Start of time range (ISO 8601). Defaults to now - 1 hour when omitted. |
to | string | No | End of time range (ISO 8601). Defaults to now when omitted. The from--to span may not exceed 92 days; a wider one is refused with 422 and {"error": "from and to may not span more than 92 days"}. |
limit | integer | No | Currently ignored — every export pulls up to 10,000 entries regardless of the value supplied. Use a tighter from/to window to control the result size. |
Example Request -- CSV
bash
curl "https://app.krafter.dev/api/v1/logs/export?project_id=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d&format=csv&level=error&from=2025-01-15T00:00:00Z&to=2025-02-15T00:00:00Z" \
-H "Authorization: Bearer kr_live_abc123def456" \
-o errors.csvExample Request -- JSON
bash
curl "https://app.krafter.dev/api/v1/logs/export?project_id=a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d&format=json&stream=backend&limit=5000" \
-H "Authorization: Bearer kr_live_abc123def456" \
-o backend-logs.jsonTIP
Use the from and to parameters to narrow the time range and keep export sizes manageable. The 10,000 entry limit applies after all filters.