Verifications API
Every call to POST /v1/verify writes a
row scoped to your account. These two endpoints read that history back:
list verifications with filters and cursor pagination, and
retrieve a single verification by ID with a freshly signed image
URL. Both are read-only and account-scoped — you only ever see your own
verifications.
Authentication
Both endpoints authenticate the same way as every VerifyAI request.
| Header | Required | Value |
| ----------- | -------- | ------------------------------------------------------ |
| X-API-Key | Yes | Your vai_… key. See Authentication. |
List verifications
GET /api/v1/verificationsReturns your most recent verifications, newest first, with cursor-based pagination. Use the query parameters to filter by policy, status, compliance, or date range.
Query parameters
| Parameter | Type | Default | Description |
| -------------- | ------- | ------- | ---------------------------------------------------------------------------- |
| limit | number | 20 | Page size. Clamped to a maximum of 100. |
| cursor | string | — | Pagination cursor. Pass the next_cursor from the previous page. |
| policy | string | — | Filter to a single policy ID (e.g. scooter_parking). |
| status | string | — | Filter by success or error. |
| is_compliant | boolean | — | Filter by outcome — true or false. |
| start_date | string | — | ISO 8601 lower bound (inclusive) on created_at. |
| end_date | string | — | ISO 8601 upper bound (inclusive) on created_at. |
Example
curl "https://verify.switchlabs.dev/api/v1/verifications?limit=20&policy=scooter_parking&is_compliant=false" \
-H "X-API-Key: vai_your_api_key"Response
{
"data": [
{
"id": "ver_8x92m4k9",
"created_at": "2026-05-12T14:30:00Z",
"status": "success",
"is_compliant": false,
"confidence": 0.94,
"policy": "scooter_parking",
"violation_reasons": ["blocking_sidewalk", "kickstand_up"],
"feedback": "Please deploy the kickstand and move away from the walkway.",
"metadata": { "trip_id": "trip_456" },
"image_url": "https://...signed-url..."
}
],
"has_more": true,
"next_cursor": "2026-05-12T14:30:00Z"
}Response fields
| Field | Type | Description |
| ------------- | -------- | --------------------------------------------------------------------------------- |
| data | object[] | The page of verification summaries, newest first. |
| has_more | boolean | true when more results exist past this page. |
| next_cursor | string? | Pass as cursor to fetch the next page. null on the last page. |
Each item in data carries id, created_at, status,
is_compliant, confidence, policy, violation_reasons, feedback,
metadata, and a freshly signed image_url (null when storage is
disabled).
The list endpoint returns a compact summary and does not include the
category field. If you need the resolved category for a specific
verification, fetch it from the retrieve endpoint below, or read it
from the original POST /v1/verify response.
Paginating
next_cursor is the created_at of the last item on the page. Pass it
back as cursor and keep going until has_more is false:
let cursor = null;
const all = [];
do {
const params = new URLSearchParams({ limit: "100" });
if (cursor) params.set("cursor", cursor);
const res = await fetch(
"https://verify.switchlabs.dev/api/v1/verifications?" + params,
{ headers: { "X-API-Key": process.env.VERIFY_AI_KEY } },
);
const page = await res.json();
all.push(...page.data);
cursor = page.next_cursor;
} while (cursor);Retrieve a verification
GET /api/v1/verifications/:idReturns a single verification by its ver_ ID. The image URL is signed
fresh on every call — use this endpoint when an image_url from an
earlier response has expired.
Example
curl https://verify.switchlabs.dev/api/v1/verifications/ver_8x92m4k9 \
-H "X-API-Key: vai_your_api_key"Response
{
"id": "ver_8x92m4k9",
"created_at": "2026-05-12T14:30:00Z",
"status": "success",
"is_compliant": false,
"confidence": 0.94,
"policy": "scooter_parking",
"violation_reasons": ["blocking_sidewalk", "kickstand_up"],
"feedback": "Please deploy the kickstand and move away from the walkway.",
"metadata": { "trip_id": "trip_456" },
"image_url": "https://...signed-url...",
"processing_time_ms": 1184,
"error_message": null
}Response fields
| Field | Type | Description |
| -------------------- | -------- | ---------------------------------------------------------------------------- |
| id | string | The verification ID, prefix ver_. |
| created_at | ISO 8601 | When the verification was processed. |
| status | string | success or error. |
| is_compliant | boolean | Top-level pass/fail decision. |
| confidence | number | 0–1 confidence score from the underlying model. |
| policy | string | The policy ID that ran. |
| violation_reasons | string[] | Machine-readable IDs of the failed criteria. |
| feedback | string | Human-readable explanation, safe to surface to end users. |
| metadata | object | The metadata you sent with the original request. |
| image_url | string? | Freshly signed URL to the stored image. null if storage is disabled. |
| processing_time_ms | number? | Server-side processing time for the original verification. |
| error_message | string? | Populated when status is error; otherwise null. |
Errors
| Status | Reason |
| ------ | ------------------------------------------------------------------- |
| 401 | Missing or invalid API key. |
| 403 | API key not valid for VerifyAI, or not linked to a customer. |
| 404 | Verification not found, or it belongs to a different account (retrieve). |
| 429 | Rate limit — check the Retry-After header. |
| 500 | Failed to fetch verifications. |
| 503 | Authentication service unavailable. Retry. |
What's next
- Verify endpoint — create verifications; full request and response schema.
- Concepts: Verifications — the verification object, lifecycle, and retention.
- Policies API — fetch the runtime config a policy uses.