Overview
Face Search is the API surface for 9Pic FaceFind, our AI face recognition photo search. Upload a participant’s selfie and the API returns paginated photos that match the selfie above the event’s confidence threshold. Each search is identified by arequest_id (UUID). You can:
- Omit
request_idand let 9Pic generate one. The generated UUID is returned in the response so you can re-fetch the same results later without re-uploading the selfie. - Pass an existing
request_idto retrieve cached results without re-running face matching.
Selfie/face search must be enabled for the event. Check the
selfie_search flag from Event Details before calling this.Why request_id Matters
A face search is expensive on our side and yours. Each POST /faces triggers an image upload, face matching against the event’s face index, confidence filtering, and a persisted result row. The request_id is what lets you do this work exactly once per user-intent and reuse the result everywhere else.
Treat request_id as the canonical identifier for a single selfie search, not as a session token. The full idempotency model is documented in Conventions.
What problem it solves
How it optimises your system
- Idempotent retries. If
POST /facesfails partway (timeout, 5xx, dropped connection), retrying with the samerequest_idresolves to the cached result on success — no double-charged face-match calls and no duplicate selfie uploads. - Cheap pagination. Hold the
request_idin your UI state. Every page change becomes aGET /faces/{request_id}?page=N&page_size=32instead of a re-search. - Decouple search trigger from result rendering. Your upload screen does the POST and stashes
request_id. Your results screen, share screen, and download screen all read fromGET /faces/{request_id}. None of them need the selfie file. - Stable, shareable references. A
request_idlets your backend log, audit, retry, or reconcile a specific selfie search without storing the user’s selfie image. - Avoid rate limiting. External API calls that perform face matching are subject to stricter limits than read-only calls. Reusing
request_idshifts your traffic fromPOST /faces(rate-limited, billable compute) toGET /faces/{request_id}(cheap reads), keeping integrations comfortably under quota even at peak.
Recommended Integration Sequence — “POST once, GET many”
1
POST once
Call
POST /faces with the user’s selfie. Do not pass request_id; let the server generate one. Read request_id from the response and persist it (URL state, local storage, your DB).2
GET many
Every subsequent action that needs results (pagination, refresh, deep-link, share) calls
GET /faces/{request_id}?page=N&page_size=32.3
Retry safely
On POST failure, retry with the same
request_id you intended for that selfie. The result is cached server-side once any POST succeeds.4
Hand off to download
Pass
request_id as identifier (with method: "selfie") to Download Original Photos. No new search is needed.Endpoints
POST /faces — Upload a Selfie
Uploads a selfie image and returns the matching event photos.Path Parameters
Query Parameters
Results are paginated. See the Pagination Model.
Multipart Form Fields
Example Request
request_id, add -F "request_id=<uuid>" (cURL), include it in data={"request_id": "<uuid>"} (Python), or formData.append("request_id", "<uuid>") (JavaScript).
Example Response
- Matches Found
- No Matches
GET /faces/ — Fetch Cached Search
Returns the cached result for a previous selfie search using itsrequest_id. Useful for paging through results or refreshing a UI without re-uploading the selfie.
Path Parameters
Query Parameters
Results are paginated. See the Pagination Model.
Example Request
Example Response
The response shape is identical toPOST /faces. Use the same model and the same Matches Found / No Matches payloads above.
Response Models
original_url is null in the standard face search response.
Error Responses
See Errors for canonical descriptions and retry guidance.

