Skip to main content
This page documents cross-cutting rules every endpoint follows. Endpoint pages link here instead of repeating the same boilerplate. For status codes, see Errors.

Base URL

All endpoints are versioned under /api/v1/ext/....

Authentication

Every request must send the API key in the X-API-Key header:
Tokens are created and managed from the Developer Zone in the dashboard. See Authentication for the full workflow and token lifecycle.

Identifiers

URL Path Conventions

  • Org-scoped: /api/v1/ext/{org_id}/...
  • Event-scoped: /api/v1/ext/{org_id}/event/{event_id}/...
  • Request-id-scoped: .../{request_id} where request_id is a UUID returned by a previous selfie POST.
  • Pipeline (media-scoped): /api/v1/ext/{org_id}/event/{event_id}/pipeline/{media}/{stage}media is photos today (see Pipeline Status); stage is import, process, go-live, or status.

Response Envelope

Every endpoint — success or error — returns the same three-key envelope:
This applies to every /api/v1/ext/... endpoint, including List Events, Event Details, All Photos, BIB Search, Face Search, Video Clipping Search, Download Original Photos, and Ping. Endpoint-specific fields like request_id, confidence_percentage, status, videos, pagination, etc. always live inside data.

Error envelope

Errors use the same shape with data: null:
The HTTP status code carries the error type; see Errors for the full status code table.

Datetime Format

All datetime fields are ISO 8601 strings:
Date-only fields are not used. When a datetime field is unset, the value is null.

Pagination

Listing and search endpoints return a PaginationInfo object. Defaults and maximums vary per endpoint. See the canonical model and per-endpoint limits on Pagination Model.
Some empty-result responses return currentPage: 0 and totalPages: 0. Treat those values as “no page is available” rather than as a normal page number.

request_id Idempotency

Selfie-driven searches use a POST-once / GET-many pattern. The request_id is the canonical identifier for a single selfie search, not a session token.
A new POST with a fresh request_id (or no request_id) is treated as a brand-new billable search. Avoid issuing fresh POSTs on every page change, refresh, or component remount.
Persist request_id in URL state (for example, /results/:request_id) so refreshes and deep-links survive without re-uploading the selfie.
See Face Search and Video Clipping Search for endpoint-specific behaviour.

Async Endpoints

Video Clipping Search is asynchronous: POST returns immediately with data.status: "processing" and data.request_id. Poll GET /video-clipping/{request_id} until data.status is anything other than processing. Recommended interval: exponential backoff starting at 3s.

Host Validation

Requests are validated against an approved hostname allowlist. Calls from non-approved hosts return 403. The production allowlist includes api.9pic.ai. Talk to support if you need an additional host enabled for testing.

Error Codes

A short error table is included on every endpoint page. The full list of status codes, common causes, and recommended client behaviour lives on the Errors page.