API reference
Base URL, credentials, conventions and an index of every FaceCard v1 route.
Base URL
https://api.facecard.devAll routes are under /v1, except /health, /openapi.json and /.well-known/jwks.json. Requests and responses are JSON. The same contract is served as OpenAPI 3.1 at https://api.facecard.dev/openapi.json.
Credentials
| Credential | Header | Use |
|---|---|---|
Publishable key fc_pk_live_xxx | X-FaceCard-Key: fc_pk_live_xxx plus an allowed Origin | Browser routes: challenges, enroll, match |
Secret key fc_sk_live_xxx | Authorization: Bearer fc_sk_live_xxx | Server routes: users, token verification, usage |
| User token (ES256 JWT) | Authorization: Bearer <jwt> | /v1/me routes for that one user |
The app is always derived from the credential. A request body app_id is ignored. See Apps and keys.
In the curl examples on these pages, fc_pk_live_xxx and fc_sk_live_xxx are placeholders. Use the keys from your own app. Browser routes need an Origin header that matches your allow list, so the examples send one.
Errors
Every error has the same shape and a matching HTTP status:
{ "error": { "code": "no_match", "message": "No matching face was found." } }Some errors carry extra fields, for example limit, used and resets_at on plan_limit_reached. The full list is in Errors.
Routes
| Method and path | Credential | Page |
|---|---|---|
POST /v1/challenges | Publishable key | Challenges |
POST /v1/enroll | Publishable key | Enroll |
POST /v1/match | Publishable key | Match |
GET /v1/me, PATCH /v1/me, DELETE /v1/me | User token | Me |
POST /v1/me/email, POST /v1/me/email/confirm | User token | Me |
POST /v1/me/templates | User token | Me |
GET /v1/users, GET /v1/users/{id}, DELETE /v1/users/{id} | Secret key | Users |
POST /v1/tokens/verify | Secret key | Tokens |
GET /v1/usage | Secret key | Usage |
GET /health, GET /.well-known/jwks.json, GET /openapi.json | None | Health, JWKS and OpenAPI |
The /internal/* routes are used by the developer portal and are not available from the internet. They are not part of the public API.
Rate limits
30 requests a minute per IP on challenge, enroll and match. 600 requests a minute per secret key. Over the limit you get 429 rate_limited with a Retry-After header. See Plans and limits.