/record/*, with the versioned audit-log read at /v1/record/audit-log. The base URL is https://api.visiqlabs.com.
These endpoints manage the record surface behind the Audit Trail: every governance decision emits a record envelope, envelopes are grouped into records, and records carry events, artifacts, and attestations. For the cryptographic verification of a single envelope, see Decision Receipts.
Authentication
All endpoints require a Bearer credential:Authorization: Bearer <key>. Requests without a valid credential receive 401 Unauthorized.
Two credential audiences exist:
- Harness keys — the operational credential your SDK or harness runs with. On this surface a harness key covers exactly
POST /record/envelopes(the envelope ingestion the record SDK calls); every other endpoint here is management-only and returns403 {"error": "harness_key_not_permitted"}for a harness key. - Management keys — general automation credentials governed by explicit permission grants. They can call every endpoint on this page. Management keys are launching soon: they are visible in the dashboard under Settings → API Keys, but creating one is not yet enabled. Until then, drive the management endpoints from the dashboard, which authenticates with your session.
record:read / record:write scope, and full_access satisfies everything.
Rate limiting
Every API-key request passes a per-key sliding-window rate limit (default 600 requests per 60 seconds). Responses carryX-RateLimit-Limit and X-RateLimit-Remaining headers; exceeding the window returns 429 with a Retry-After header and body {"error": "rate_limited", "detail": "API key rate limit exceeded.", "retryAfter": <seconds>}.
List responses
Every list endpoint on this page returns the same envelope:The record list envelope names the page size field
limit (echoing the request parameter), where the action and retrieval list endpoints name it pageSize. The values are the same; only the key differs.page (default 1) and limit (default 50, max 200) query parameters.
Ingestion
POST /record/envelopes
Ingest a record envelope. The platform upserts the parent record bycorrelationId (creating it on first sight, appending to it thereafter), appends the event with the next sequence number and a SHA-256 content hash, and inserts any attached artifacts and attestations — atomically.
Permission: record_records:create · Scope: record:write
Request body:
Response (201):
201 Created, 400 Bad Request (invalid JSON or body), 401 Unauthorized, 403 Forbidden (harness-key on a management route, or tenantId does not match the authenticated vendor), 500 Internal Server Error
Records
Management endpoints — a harness key receives403 harness_key_not_permitted here. Each read is vendor-scoped; a record that isn’t yours is 404.
GET /record/records
List records, newest first. Permission:record_records:view
Query parameters:
Response:
200 OK, 400 Bad Request (invalid query), 401 Unauthorized, 500 Internal Server Error
GET /record/records/:id
Get a single record by UUID. Permission:record_records:view
Path parameter: :id — the record UUID (must be a valid UUID, else 400)
Response: the record object (as in the list response).
Status codes: 200 OK, 400 Bad Request (invalid record ID), 401 Unauthorized, 404 Not Found, 500 Internal Server Error
PATCH /record/records/:id/finalize
Finalize a record — seal it so no further events are expected. Idempotent: finalizing an already-finalized record returns it unchanged. Permission:record_records:finalize
Path parameter: :id — the record UUID
Response: the record object with status: "finalized" and a populated finalized_at.
Status codes: 200 OK, 400 Bad Request (invalid record ID), 401 Unauthorized, 404 Not Found, 409 Conflict (the record is superseded and cannot be finalized), 500 Internal Server Error
GET /record/records/:id/events
List the events on a record, in sequence order. Permission:record_records:view
Query parameters: page (default 1), limit (default 50, max 200)
Response:
200 OK, 400 Bad Request, 401 Unauthorized, 404 Not Found (unknown or non-owned record), 500 Internal Server Error
GET /record/records/:id/artifacts
List the artifacts attached to a record. Permission:record_records:view
Query parameters: page (default 1), limit (default 50, max 200)
Response: the standard list envelope whose items carry id, artifact_type, mime_type, storage_ref, content_hash, metadata_json, and created_at.
Status codes: 200 OK, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error
GET /record/records/:id/attestations
List the attestations attached to a record. Permission:record_records:view
Query parameters: page (default 1), limit (default 50, max 200)
Response: the standard list envelope whose items carry id, attestation_type, issuer_type, issuer_id, statement_json, hash, signature, and created_at.
Status codes: 200 OK, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error
Verification
GET /record/envelopes/:id/verify
Run a live, independent verification of one envelope’s full attestation chain — integrity, Ed25519 leaf signature, Merkle inclusion, the AWS-KMS root signature (with a live KMS round-trip), and the RFC 3161 timestamp. The response carries a per-check result and evidence; Audit Trail documents the six checks. Permission:record_records:view · Scope: record:read
Path parameter: :id — the envelope UUID (vendor-scoped; an envelope that isn’t yours is 404, indistinguishable from not-found to prevent enumeration)
Status codes: 200 OK, 400 Bad Request (invalid record ID), 401 Unauthorized, 404 Not Found, 500 Internal Server Error
Checkpoints
The public transparency-log checkpoints — the signed, hash-chained Merkle roots. These are tenant-neutral: a checkpoint exposes only roots, signatures, counts, timestamp, and witness status, never any per-tenant data.GET /record/checkpoints/:seq
Fetch one checkpoint by its 1-based batch sequence number. Permission:record_records:view · Scope: record:read
Path parameter: :seq — the checkpoint’s batch_seq (integer ≥ 1)
Query parameters: domain — production (default) or sandbox, selecting the transparency chain
Response: the tenant-free checkpoint view (roots, signatures, counts, timestamp-authority time, and the derived external-witness status).
Status codes: 200 OK, 400 Bad Request (invalid sequence), 401 Unauthorized, 404 Not Found (unknown sequence), 500 Internal Server Error
The sibling
GET /record/checkpoints lists checkpoints newest-first, seq-cursor paginated via before and limit (default 50, max 200), under the same permission and scope — walk it to audit the published roots and detect a split view or rewrite.Audit Log
GET /v1/record/audit-log
Query the record event log for your organization — the events across all your records, filterable by source, correlation id, event type, and date. The join is vendor-scoped server-side, so it never leaks another tenant’s events. Permission:record_audit_log:view · Scope: record:read
Query parameters:
Response:
200 OK, 400 Bad Request (invalid query), 401 Unauthorized, 403 Forbidden (insufficient permission or scope), 500 Internal Server Error
Errors & conventions
Every endpoint on this page follows the platform-wide REST conventions — the validation-error body shape, the/v1/ vs unversioned split, and the API stability policy. See REST API conventions.