Evidence API
An Evidence row is one artefact captured during a session — a
snapshot, a whiteboard, a video clip, a recording, or an uploaded document.
Every row carries a sha256 + byte_size + mime
so the integrity-verification chain can prove the bytes weren't tampered with
between capture and audit.
The Evidence object
{
"id": "ev-7f3a...",
"session": "0c8f4d2e-1a3b-4c5d-9e7f-1234567890ab",
"kind": "snapshot",
"status": "ready",
"mime": "image/jpeg",
"byte_size": 184523,
"sha256": "f9cc12fda76c30dcc9bee627baed6c9e8fe11b813313de70b1463f9f73e5e418",
"captured_at": "2026-05-23T10:14:02.481Z",
"created_at": "2026-05-23T10:14:02.917Z",
"completed_at": "2026-05-23T10:14:03.211Z"
} Kinds
| Kind | Captured by | Notes |
|---|---|---|
snapshot | Operator or field-side | Single still frame (JPEG). The most common kind. |
whiteboard | Operator | Excalidraw export — PNG + canonical JSON. See Whiteboards. |
clip | Operator | Short MP4 cut from the live session — used to capture motion the field user demonstrates. |
recording | System | Full session recording. Post-processed to libx264 medium / crf20 after the session ends. |
document | Operator | File attachment from the in-session chat (PDFs, photos, etc.). Foundation for PDF-for-signature. |
Status
| Status | Meaning |
|---|---|
pending | Row created; bytes not yet in object storage. |
uploading | Multipart upload in progress. |
ready | Bytes are persisted; sha256 + byte_size are finalised. Only ready rows are downloadable. |
failed | Capture or upload aborted. completed_at is null. |
List session evidence
GET /api/v1/public/sessions/{session_id}/evidence — scope evidence:read
curl "https://app.nexbasira.com/api/v1/public/sessions/0c8f.../evidence?kind=snapshot&limit=50" \
-H "Authorization: Bearer nb_sec_..." Query params
| Param | Type | Notes |
|---|---|---|
kind | string | Filter — one of snapshot, whiteboard, clip, recording, document. |
limit | int | Max 100. Defaults to 25. |
cursor | opaque | From the previous response's next_cursor. |
Get a signed download URL
GET /api/v1/public/evidence/{evidence_id}/download — scope evidence:read
Returns a short-lived presigned URL the customer fetches the raw bytes from. The URL points directly at the object-storage backend (MinIO / S3 / GCS depending on your deployment) so downloads bypass our app servers — no bandwidth-egress charges from your end of the public API.
curl "https://app.nexbasira.com/api/v1/public/evidence/ev-7f3a.../download" \
-H "Authorization: Bearer nb_sec_..." {
"url": "https://s3.eu-central-1.amazonaws.com/nb-prod-evidence/orgs/.../snapshot.jpg?X-Amz-Algorithm=...",
"expires_in_seconds": 900,
"sha256": "f9cc12fda76c30dcc9bee627baed6c9e8fe11b813313de70b1463f9f73e5e418",
"byte_size": 184523,
"mime": "image/jpeg",
"kind": "snapshot"
}
Re-call when the URL expires — no rate-limit penalty for repeated mints.
After downloading, hash the bytes with SHA-256 and compare to the returned
sha256 to verify the file is intact end-to-end.
# integrity check — Python
import hashlib, requests
r = requests.get(presigned["url"]); r.raise_for_status()
assert hashlib.sha256(r.content).hexdigest() == presigned["sha256"] Common errors
| Status | Code | When |
|---|---|---|
| 403 | permission_denied | Credential lacks evidence:read. |
| 404 | not_found | Evidence row doesn't exist in the credential's org. |
| 409 | evidence_not_ready | Download requested on a row whose status is not ready. |
| 410 | retention_expired | Org's retention policy has passed the row's age cutoff; bytes have been purged from object storage. |
Notes
- No POST/PATCH/DELETE. Evidence is captured client-side (operator + field SPA) during the session. The public API is read-only on this resource.
- Retention. Each org configures a retention window (default 7 years for eIDAS-compliant deployments). After the window, object-storage lifecycle rules purge bytes; the row stays so the audit chain doesn't break, but
/downloadreturns 410. - Anchored in the audit chain. Every
readyrow contributes its sha256 to the per-session hash chain, which is anchored at the TSA on session end. The chain head + TSA receipt are reachable via the SPA-side audit-verify endpoint.