API reference
Two customer-facing endpoints (OTLP ingest + receipt creation), one public auditor-facing endpoint (verify URL), plus the dashboard's REST surface for building integrations against your own data.
Authentication
Customer-facing endpoints use the X-Marturia-Key header.
Mint a key in the dashboard's Keys page. Only the SHA-256
hash is stored; you'll see the plaintext exactly once at creation time.
Dashboard endpoints (under /api/marturia/projects/...) use
JWT bearer tokens issued by the login flow.
Customer endpoints
POST /api/marturia/v1/traces
OTLP/HTTP trace ingest. Standard OTel protocol.
| Header | Value |
|---|---|
X-Marturia-Key | required |
Content-Type | application/x-protobuf or application/json |
Returns 200 OK with empty body on success.
413 if body > 5 MB.
429 if monthly quota exceeded.
POST /api/marturia/v1/receipts
Create a signed cryptographic receipt.
Body
{
"agent_name": "string, 1-80 chars, required",
"payload": "any JSON object, max 64KB canonical, required",
"agent_run_id": "optional string, your stable run identifier"
}
Response 200
{
"id": 98,
"tenant_id": 2,
"project_id": 70,
"receipt_seq": 54,
"signing_kid": "t2-v1",
"receipt_hash": "803e993d40fa...",
"agent_name": "purchase_approver",
"agent_run_id": "run_demo_001",
"verify_url": "https://marturia.dev/v1/verify/2/98"
}
Errors
| Status | Cause |
|---|---|
| 400 | Missing or invalid agent_name / payload; payload > 64 KB. |
| 401 | Missing or invalid X-Marturia-Key. |
| 429 | Rate limit (60/min/project) exceeded. |
Public verifier
GET /v1/verify/{tenant_id}/{receipt_id}
No auth. Returns the full receipt JSON for offline verification. Use this URL when sharing receipts with auditors or customers.
Response 200
{
"tenant_id": 2,
"receipt_seq": 54,
"agent_name": "purchase_approver",
"agent_run_id": "run_demo_001",
"created_at": "2026-05-09T18:42:11.337Z",
"signing_kid": "t2-v1",
"receipt_hash": "803e993d40fa...",
"prev_hash": "a609ed8ce163...",
"signature": "5fd2e0a14a6d...",
"public_key": "9fc982fe3474...",
"payload_canonical_bytes": "<base64>"
}
Dashboard endpoints
JWT auth. The dashboard SPA uses these; you can hit them too if you're building integrations off your own data.
GET /api/marturia/projects
List your tenant's projects.
GET /api/marturia/projects/{id}/spans
List spans for a project. Query params:
| Param | Default | Notes |
|---|---|---|
hours | 24 | Lookback window. Max 720 (30d). |
status | (any) | OK, ERROR, or UNSET. |
service | (any) | Filter to one service.name. |
q | — | Free-text match against name/attributes. |
trace_id | — | Pin to a single trace. |
before | — | Cursor for pagination — pass the previous page's last start_time. |
limit | 200 | Max 1000. |
GET /api/marturia/projects/{id}/traces/{trace_id}
All spans for a single trace, ordered by start time, with parent linkage.
GET /api/marturia/projects/{id}/aggregations
Dashboard tile data — totals, percentiles, timeline, services, models,
slowest spans. Same hours param as /spans.
GET /api/marturia/projects/{id}/receipts
List receipts for the tenant (the chain is tenant-scoped, surfaced on
every project for convenience). Query: limit (default 100,
max 1000).
GET /api/marturia/projects/{id}/receipts/{receipt_id}
Full receipt detail in the same shape as the public verifier.
GET /api/marturia/projects/{id}/receipts/{receipt_id}/export
Download the receipt as a JSON bundle (Content-Disposition: attachment).
Rate limits + quotas
| Endpoint | Limit |
|---|---|
| POST /traces | Project span quota (Free 100K/mo, Pro 1M, Team 10M, Audit 100M) |
| POST /receipts | 60 requests / minute / project |
| GET /v1/verify | 120 requests / minute / IP |
| Dashboard endpoints | 600 requests / minute / user |
Errors
All endpoints return JSON errors in the form:
{ "detail": "human-readable message" }
Status codes follow REST conventions. 500 is reserved for
server bugs and triggers an internal alert; if you see one, please
tell us.