Submit a capture-session selfie (liveness poll or upload)
/v1/vision/selfie-submitAuthenticates with client credentials — no bearer token required.
Forwards the request verbatim to identity-kyc's internal `redeem-selfie` endpoint and maps its response back to the widget faithfully — this is a thin passthrough, not a second copy of the business logic. No OAuth bearer token: `capture_session_token` in the body is the entire authorization, verified downstream when this handler calls identity-kyc. A request either polls a pending vendor liveness session (no `selfie_image_base64`) or uploads a frame directly (`selfie_image_base64`, optionally with `liveness_degraded: true` after a prior 503) — see identity-kyc's own `RedeemSelfieCapture.ts` for the full two-path dispatch. `200` reports `provenance: 'controlled'` (a vendor-verified live frame) or `'submitted'` (an uploaded frame, never vendor-verified), or `provenance: null, routed: 'review'` when the liveness retry budget is exhausted without a passing attempt — the case still proceeds, just without a controlled selfie. `409 liveness_retake` (with `attempts_remaining`) means the widget should poll again; it is an ordinary retry signal, not a problem+json body. `503` (`code: liveness_unavailable`) means the vendor check is down — the widget's own fallback is to capture locally and resubmit with `selfie_image_base64` and `liveness_degraded: true`. Served by the vision host, not the primary API host (see the second `servers` entry), same as documentScan — temporary pending the unified API edge (ADR-0043). Rate-limited per-source-IP (RIGID-591 pattern, fixed 60s window); a 429 carries a `Retry-After` header.
Request body
Example
curl -X POST https://vision.dev.rigid.fi/v1/vision/selfie-submit \
-H "Authorization: Bearer $RIGID_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"capture_session_token": "string"
}'Responses
200The selfie was redeemed (`provenance: controlled | submitted`), or the liveness retry budget is exhausted (`provenance: null, routed: 'review'`).
One of
Option 1
Option 2
400Validation error
404Capture session not found or expired
409A pending liveness check has not yet produced a passing verdict — poll again.
410The capture session scan budget is exhausted (`code: scan_budget_exhausted`) — the stored image will still be reviewed, so the widget should land on its done/review terminal rather than treating this like an expired session
429Too many selfie submits from this address — retry shortly
500Internal server error
503The liveness check is temporarily unavailable (`code: liveness_unavailable`) — the widget should fall back to its own capture and resubmit with `selfie_image_base64` and `liveness_degraded: true`