> ## Documentation Index > Fetch the complete documentation index at: https://devdocs.veriff.com/llms.txt > Use this file to discover all available pages before exploring further. # Bulk import faces > ### Import faces in bulk for asynchronous processing Import one or more faces in bulk, either by uploading face **images** or by referencing existing **verification sessions** (`verification_ids`). You can send either, or both in the same request; at least one is required. Each list accepts 1 to 10 items (`images` and `verification_ids` are capped independently). Processing happens asynchronously: the API returns immediately with a 202 status and the faces are processed in the background. #### Importing from verification sessions Instead of (or alongside) uploading image bytes, pass `verification_ids`: an array of up to 10 verification session ids. For each id, the face captured during that verification is imported; no image data is sent. Each id counts toward your quota just like an image. #### Cap on image uploads per request **Maximum 10 images per request** Each request can include a maximum of 10 face images. This is a hard limit enforced by the API. If you attempt to submit more than 10 images in a single request, the request will fail with a validation error. **When you need to import more than 10 images:** - Make multiple requests, each with up to 10 images - Each image submitted counts toward your quota - This quota is fixed according to your service plan - Info about remaining quota is available in the API response in `availableQuota` parameter - Contact your Solutions Engineer or Veriff Customer Support if you need to increase your quota - All images can be of the same person or different persons **Example:** - To import 25 images: Make 3 requests (10 + 10 + 5 images) #### When to use this endpoint - Use this endpoint to import face images in bulk for fraud detection and identity verification - Process multiple images per person in a single request (up to 10 per call) - Leverage asynchronous processing for high-throughput scenarios #### Image name uniqueness Each **image name** can only be submitted **once every 5 minutes**. If you submit an image with the same name multiple times within 5 minutes, only the first submission will be processed. **Recommended naming strategies:** - **Include timestamps**: `profile_2026-02-17_14-30-00.jpg` - **Use UUIDs**: `profile_a7f8d3e1-4c2b-9f8e-b1d2-c3e4f5a6b7c8.jpg` - **Use your internal IDs**: `profile_user_12345_session_67890.jpg` - **Combine multiple identifiers**: `profile_john_doe_20260217_143000.jpg` #### For retries If you need to re-submit an image: - **Option 1**: Wait at least 5 minutes before using the same image name again - **Option 2**: Use a different image name (recommended for immediate retry) #### Implementation notes - This endpoint requires session-level [HMAC signature](https://devdocs.veriff.com/docs/hmac-authentication-and-endpoint-security#public-api-v1) authentication - Processing is asynchronous — results are not returned in the response - Always ensure that you use the correct API URL to send requests. See the [API URL section](https://devdocs.veriff.com/apidocs/veriff-public-api-guides#api-url) for more info. - The order of parameters in the real API response can differ from the order you see in this documentation. This is expected and part of the [Backwards compatible changes](https://devdocs.veriff.com/apidocs/veriff-public-api-guides#backwards-compatible-changes) requirements. ## OpenAPI ````json POST /v1/faces/import { "openapi": "3.0.0", "info": { "title": "Veriff Public API", "version": "1.0.0" }, "servers": [ { "url": "https://example-base-url" } ], "tags": [ { "name": "Session management", "description": "Create and manage verification sessions" }, { "name": "Data submission", "description": "Upload media and submit verification data during the session" }, { "name": "Session results", "description": "Retrieve verification decisions and results" }, { "name": "Media management", "description": "Access and download verification media files and media file-related data" }, { "name": "Database verification", "description": "Validate identity against national registries and databases" }, { "name": "Certificate management", "description": "Retrieve long-term preservation certificates and their source documents for a verification session" } ], "paths": { "/v1/faces/import": { "post": { "tags": [ "Data submission" ], "summary": "Bulk import faces", "description": "### Import faces in bulk for asynchronous processing\n\nImport one or more faces in bulk, either by uploading face **images** or by\nreferencing existing **verification sessions** (`verification_ids`). You can\nsend either, or both in the same request; at least one is required. Each list\naccepts 1 to 10 items (`images` and `verification_ids` are capped independently).\nProcessing happens asynchronously: the API returns immediately with a 202 status\nand the faces are processed in the background.\n\n#### Importing from verification sessions\n\nInstead of (or alongside) uploading image bytes, pass `verification_ids`: an\narray of up to 10 verification session ids. For each id, the face captured\nduring that verification is imported; no image data is sent. Each id counts\ntoward your quota just like an image.\n\n#### Cap on image uploads per request\n\n**Maximum 10 images per request**\n\nEach request can include a maximum of 10 face images. This is a hard limit enforced by the API. \nIf you attempt to submit more than 10 images in a single request, the request will fail with a validation error.\n\n**When you need to import more than 10 images:**\n- Make multiple requests, each with up to 10 images\n- Each image submitted counts toward your quota\n - This quota is fixed according to your service plan\n - Info about remaining quota is available in the API response in `availableQuota` parameter \n - Contact your Solutions Engineer or Veriff Customer Support if you need to increase your quota\n\n- All images can be of the same person or different persons\n\n**Example:**\n- To import 25 images: Make 3 requests (10 + 10 + 5 images)\n\n#### When to use this endpoint\n\n- Use this endpoint to import face images in bulk for fraud detection and identity verification\n- Process multiple images per person in a single request (up to 10 per call)\n- Leverage asynchronous processing for high-throughput scenarios\n\n#### Image name uniqueness\n\nEach **image name** can only be submitted **once every 5 minutes**. If you submit an image with the same name \nmultiple times within 5 minutes, only the first submission will be processed.\n\n**Recommended naming strategies:**\n\n- **Include timestamps**: `profile_2026-02-17_14-30-00.jpg`\n- **Use UUIDs**: `profile_a7f8d3e1-4c2b-9f8e-b1d2-c3e4f5a6b7c8.jpg`\n- **Use your internal IDs**: `profile_user_12345_session_67890.jpg`\n- **Combine multiple identifiers**: `profile_john_doe_20260217_143000.jpg`\n\n#### For retries\n\nIf you need to re-submit an image:\n- **Option 1**: Wait at least 5 minutes before using the same image name again\n- **Option 2**: Use a different image name (recommended for immediate retry)\n\n#### Implementation notes\n\n- This endpoint requires session-level [HMAC signature](https://devdocs.veriff.com/docs/hmac-authentication-and-endpoint-security#public-api-v1) authentication\n- Processing is asynchronous — results are not returned in the response\n- Always ensure that you use the correct API URL to send requests. See the [API URL section](https://devdocs.veriff.com/apidocs/veriff-public-api-guides#api-url) for more info.\n- The order of parameters in the real API response can differ from the order you see in this documentation. This is expected and part of the [Backwards compatible changes](https://devdocs.veriff.com/apidocs/veriff-public-api-guides#backwards-compatible-changes) requirements.\n", "operationId": "importFaces", "parameters": [ { "name": "X-AUTH-CLIENT", "in": "header", "description": "Your integration's API key (occasionally referred to as the \"Token\", \"API public key\" or \"Publishable key\"). \nRequired for all API requests.\n\nYou can find your API key in the Veriff Customer Portal under Settings > API keys.\n", "required": "true", "schema": { "type": "string" }, "example": "your_api_key" }, { "name": "X-HMAC-SIGNATURE", "in": "header", "description": "Request body signed with the shared secret key. Required to authenticate the request sender.\n\n**Signature Formula:**\n```\nsourceString = \"/v1/faces/import\" + \"\\n\" + JSON.stringify(requestBody)\nsignature = HmacSHA256.sign(sourceString, sharedSecret)\n```\n\n`requestBody` is the exact JSON you send (whether it carries `images`,\n`verification_ids`, or both), so the same formula covers every request shape.\nThe request body must be serialized consistently (sorted keys, no extra spaces).\n", "required": "true", "schema": { "type": "string" }, "example": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2" }, { "name": "Content-Type", "in": "header", "description": "Must be set to application/json", "required": "true", "schema": { "type": "string", "enum": [ "application/json" ] }, "example": "application/json" } ], "requestBody": { "required": "true", "description": "Face import request containing face images and/or verification session ids", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FaceImportRequest" }, "examples": { "single_image": { "summary": "Import single face image", "value": { "images": [ { "name": "profile_2026-02-17_14-30-00.jpg", "content": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII=" } ] } }, "multiple_images": { "summary": "Import 3 face images", "value": { "images": [ { "name": "profile_2026-02-17_14-30-00.jpg", "content": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII=" }, { "name": "id_card_front_2026-02-17_14-30-00.jpg", "content": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII=" }, { "name": "id_card_back_2026-02-17_14-30-00.jpg", "content": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII=" } ] } }, "verification_ids": { "summary": "Import faces from verification sessions", "value": { "verification_ids": [ "f04bdb47-d3be-4b28-b028-a652feb060b5", "86c71df5-c163-4022-9c94-1fb6dc903a98" ] } }, "images_and_verification_ids": { "summary": "Import both images and verification sessions in one request", "value": { "images": [ { "name": "profile_2026-02-17_14-30-00.jpg", "content": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII=" } ], "verification_ids": [ "f04bdb47-d3be-4b28-b028-a652feb060b5" ] } } } } } }, "responses": { "202": { "description": "Accepted — Images will be processed asynchronously.\n\nThe request has been accepted for processing. Images are now queued for asynchronous processing.\n", "headers": { "Content-Type": { "description": "Response content type.", "schema": { "type": "string", "example": "application/json" } }, "X-AUTH-CLIENT": { "description": "API key echoed back in response.", "schema": { "type": "string" }, "example": "your_api_key" }, "X-HMAC-SIGNATURE": { "description": "Response body signed with the shared secret key. Required to authenticate the response sender.", "schema": { "type": "string" }, "example": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FaceImportResponse" }, "examples": { "success": { "summary": "Successful import of 3 images", "value": { "message": "3 images queued for asynchronous face import.", "availableQuota": "997", "failedImages": [] } }, "partial_success": { "summary": "Partial success — 2 of 3 images accepted", "value": { "message": "2 of 3 images queued for face import. 1 could not be accepted — see `failedImages` for details and resubmit those.", "availableQuota": "998", "failedImages": [ { "name": "profile_2026-02-17_14-30-02.jpg", "reason": "The image could not be processed. Please retry." } ] } } } } } }, "400": { "description": "Bad Request — the request could not be processed.", "headers": { "Content-Type": { "description": "Response content type.", "schema": { "type": "string", "example": "application/json" } }, "X-AUTH-CLIENT": { "description": "API key echoed back in response.", "schema": { "type": "string", "example": "your_api_key" } }, "X-HMAC-SIGNATURE": { "description": "Response body signed with the shared secret key. Required to authenticate the response sender.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequestErrorResponse" }, "examples": { "malformed_json": { "summary": "Truncated / malformed JSON body", "value": { "status": "fail", "code": "1101", "message": "Invalid JSON in request body." } } } } } }, "401": { "description": "Unauthorized — Authentication failed.", "headers": { "Content-Type": { "description": "Response content type.", "schema": { "type": "string", "example": "application/json" } }, "X-AUTH-CLIENT": { "description": "API key echoed back in response.", "schema": { "type": "string", "example": "your_api_key" } }, "X-HMAC-SIGNATURE": { "description": "Response body signed with the shared secret key. Required to authenticate the response sender.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UnauthorizedErrorResponse" }, "examples": { "missing_api_key": { "summary": "Missing `X-AUTH-CLIENT` header", "value": { "status": "fail", "code": "1801", "message": "Mandatory X-AUTH-CLIENT header containing the API key is missing from the request." } }, "invalid_api_key": { "summary": "API key not recognised", "value": { "status": "fail", "code": "1803", "message": "Integration with the API key \"00000000-0000-0000-0000-000000000000\" was not found." } }, "could_not_authenticate": { "summary": "HMAC signature mismatch or otherwise unverifiable", "value": { "status": "fail", "code": "1815", "message": "Could not authenticate request." } }, "signature_does_not_match": { "summary": "Provided signature does not match the HMAC-SHA256 of body + secret", "value": { "status": "fail", "code": "1819", "message": "Signature \"\" does not match the HMAC-SHA256 of request body and integration API secret." } } } } } }, "402": { "description": "Payment Required — Insufficient quota available.\n\nYour account has reached its faceblock import quota limit.\n", "headers": { "Content-Type": { "description": "Response content type.", "schema": { "type": "string", "example": "application/json" } }, "X-AUTH-CLIENT": { "description": "API key echoed back in response.", "schema": { "type": "string", "example": "your_api_key" } }, "X-HMAC-SIGNATURE": { "description": "Response body signed with the shared secret key. Required to authenticate the response sender.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FaceblockInsufficientQuotaResponse" }, "examples": { "insufficient_quota": { "summary": "Insufficient quota", "value": { "detail": { "error": "insufficient_quota", "message": "Insufficient quota. Available: 1, Required: 3", "available_quota": "1", "required": "3" } } } } } } }, "422": { "description": "Validation Error. The body is valid JSON but fails schema validation:\nwrong types; neither `images` nor `verification_ids` provided (send at\nleast one, either alone or both together); a provided `images` or\n`verification_ids` array that is empty or holds more than 10 items (each\nfield, when present, must have 1 to 10 items); missing required fields;\nor `content` exceeding the raw-size cap.\n\nUse `400` handling for unparseable / truncated JSON bodies; `422`\nonly fires once the JSON has been parsed successfully and schema\nvalidation runs. Per-image validation failures (invalid name\ncharacters, bad base64, unsupported image format, decoded payload\nover 2 MB) are NOT reported here; those return `202` and land in\nthe response's `failedImages` list alongside the successes.\n", "headers": { "Content-Type": { "description": "Response content type.", "schema": { "type": "string", "example": "application/json" } }, "X-AUTH-CLIENT": { "description": "API key echoed back in response.", "schema": { "type": "string", "example": "your_api_key" } }, "X-HMAC-SIGNATURE": { "description": "Response body signed with the shared secret key. Required to authenticate the response sender.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ValidationErrorResponse" }, "examples": { "empty_images_array": { "summary": "Empty images array (minimum 1 required)", "value": { "detail": [ { "type": "too_short", "loc": [ "body", "images" ], "msg": "List should have at least 1 item after validation, not 0", "input": [] } ] } }, "too_many_images": { "summary": "Too many images (maximum 10)", "value": { "detail": [ { "type": "too_long", "loc": [ "body", "images" ], "msg": "List should have at most 10 items after validation, not 11", "input": [] } ] } }, "missing_required_field": { "summary": "Missing required field (`name` or `content`)", "value": { "detail": [ { "type": "missing", "loc": [ "body", "images", "0", "content" ], "msg": "Field required", "input": { "name": "only-name.jpg" } } ] } }, "oversized_content": { "summary": "Content string too large (OOM protection)", "value": { "detail": [ { "type": "string_too_long", "loc": [ "body", "images", "0", "content" ], "msg": "String should have at most 2796268 characters", "input": "<>" } ] } }, "wrong_type": { "summary": "Wrong type (for example `images` sent as a string)", "value": { "detail": [ { "type": "list_type", "loc": [ "body", "images" ], "msg": "Input should be a valid list", "input": "not-an-array" } ] } } } } } }, "500": { "description": "Internal server error. Something went wrong on our side while processing the request; retry after a short delay and contact support if it persists.", "headers": { "Content-Type": { "description": "Response content type.", "schema": { "type": "string", "example": "application/json" } }, "X-AUTH-CLIENT": { "description": "API key echoed back in response.", "schema": { "type": "string", "example": "your_api_key" } }, "X-HMAC-SIGNATURE": { "description": "Response body signed with the shared secret key. Required to authenticate the response sender.", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InternalServerErrorResponse" }, "examples": { "server_error": { "summary": "Internal server error", "value": { "status": "fail", "code": "1101", "message": "Something went wrong" } } } } } } } } } }, "components": { "schemas": { "FaceImportRequest": { "type": "object", "title": "FaceImportRequest", "description": "Request model for importing faces in bulk. Provide face `images` and/or\n`verification_ids` (verification session ids); at least one is required,\nand both may be sent in the same request.\n\n⚠️ **Hard limit: 10 items per field.** `images` accepts 1 to 10 face images and\n`verification_ids` accepts 1 to 10 UUIDs (capped independently). Requests\nexceeding either cap are rejected with a validation error.\n", "additionalProperties": "false", "properties": { "images": { "type": "array", "title": "Images", "description": "Array of image objects containing face data.\n\n**Important:** Exactly 1 to 10 images maximum per request. Each image beyond 10 will cause validation to fail.\n", "minItems": "1", "maxItems": "10", "items": { "$ref": "#/components/schemas/ImageData" } }, "verification_ids": { "type": "array", "title": "Verification IDs", "description": "Array of verification session ids (UUIDs) to import faces from. Faceblock\nimports the face captured during each verification, so no image bytes are\nsent for these.\n\n**Important:** 1 to 10 ids maximum per request.\n", "minItems": "1", "maxItems": "10", "items": { "type": "string", "format": "uuid", "example": "f04bdb47-d3be-4b28-b028-a652feb060b5" } } } }, "FaceImportResponse": { "type": "object", "title": "FaceImportResponse", "description": "Response model for image import operation.", "required": [ "availableQuota", "failedImages" ], "properties": { "message": { "type": "string", "title": "Message", "description": "Confirmation message indicating images are queued for processing.\nOn full success: \"{count} images queued for asynchronous face import.\"\nOn partial success: \"{succeeded} of {total} images queued for face import. {failed} could not be accepted — see `failedImages` for details and resubmit those.\"\n", "default": "Images queued for asynchronous face import.", "example": "3 images queued for asynchronous face import." }, "availableQuota": { "type": "integer", "title": "Available Quota", "description": "Remaining quota after this operation. Only successful images debit quota, so resubmitting a failure does not double-charge.", "example": "997" }, "failedImages": { "type": "array", "title": "Failed Images", "description": "Images that could not be accepted. Empty array on full success.\nInspect this list to identify which specific images to resubmit. When retrying within 5 minutes, use a different `name` — the 5-minute uniqueness rule applies to retries as well.\nQuota exhaustion is NOT reported here — it returns a 402 response before any image is attempted.\n", "items": { "$ref": "#/components/schemas/FailedImage" }, "example": [] } } }, "BadRequestErrorResponse": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "fail" ], "example": "fail" }, "code": { "type": "string", "example": "1101" }, "message": { "type": "string", "example": "Validation failed" } }, "required": [ "status", "code", "message" ] }, "UnauthorizedErrorResponse": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "fail" ], "example": "fail" }, "code": { "type": "string", "example": "1101" }, "message": { "type": "string", "example": "Mandatory X-AUTH-CLIENT header containing the API key is missing from the request." } }, "required": [ "status", "code", "message" ] }, "FaceblockInsufficientQuotaResponse": { "type": "object", "title": "FaceblockInsufficientQuotaResponse", "description": "402 response body returned when a faceblock import request exceeds the integration's remaining quota.", "required": [ "detail" ], "properties": { "detail": { "type": "object", "required": [ "error", "message", "available_quota", "required" ], "properties": { "error": { "type": "string", "enum": [ "insufficient_quota" ], "example": "insufficient_quota" }, "message": { "type": "string", "example": "Insufficient quota. Available: 1, Required: 3" }, "available_quota": { "type": "integer", "description": "Quota remaining at the moment the request was evaluated.", "example": "1" }, "required": { "type": "integer", "description": "Number of images the request was attempting to import.", "example": "3" } } } } }, "ValidationErrorResponse": { "type": "object", "title": "ValidationErrorResponse", "description": "Validation error response model with detailed error locations and messages.", "required": [ "detail" ], "properties": { "detail": { "type": "array", "title": "Detail", "description": "Array of validation error details with field locations and error messages", "items": { "type": "object", "additionalProperties": "true" }, "example": [ { "loc": [ "body", "images" ], "msg": "ensure this value has at most 10 items", "type": "value_error.list.max_items" } ] } } }, "InternalServerErrorResponse": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "fail" ], "example": "fail" }, "code": { "type": "string", "example": "1101" }, "message": { "type": "string", "example": "Something went wrong" } }, "required": [ "status", "code", "message" ] }, "ImageData": { "type": "object", "title": "ImageData", "description": "Model for image data with name and base64 content.", "required": [ "name", "content" ], "additionalProperties": "false", "properties": { "name": { "type": "string", "title": "Name", "description": "Unique name/identifier for this image within the request.\n\nAllowed characters: letters, digits, `.`, `_`, `-`. Max 120 characters. Must not be empty and must not contain `..`.\nNames that break these rules don't 422 the whole batch — they land in the response's `failedImages` with reason `\"Invalid image name.\"` while the rest of the batch proceeds.\n\nCannot be submitted again from the same account within 5 minutes — use timestamps or UUIDs to ensure uniqueness across requests.\n", "example": "profile_2026-02-17_14-30-00.jpg" }, "content": { "type": "string", "title": "Content", "description": "Base64-encoded image data. Supported formats: JPEG, PNG, GIF, BMP, WEBP.\nMax decoded size: 2 MB per image. Can include a data URI prefix (e.g., `data:image/jpeg;base64,`) or be raw base64.\nInvalid / unsupported / oversized content doesn't 422 the whole batch — it lands in the response's `failedImages` with reason `\"Invalid image content.\"` while the rest of the batch proceeds.\n", "example": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII=" } } }, "FailedImage": { "type": "object", "title": "FailedImage", "description": "An image the API could not accept.", "required": [ "name", "reason" ], "properties": { "name": { "type": "string", "title": "Name", "description": "The image name as submitted in the request.", "example": "profile_2026-02-17_14-30-00.jpg" }, "reason": { "type": "string", "title": "Reason", "description": "Why the image was not accepted and what to do next:\n - \"Invalid image name.\" — the `name` contained characters outside the allowed set (only letters, digits, `.`, `_`, `-`), was empty, contained `..`, or exceeded 120 characters. Rename and resubmit.\n - \"Invalid image content.\" — `content` was not valid base64, did not decode to a supported image format (JPEG, PNG, GIF, BMP, WEBP), was larger than 2 MB, or was too small to be a real image. Fix the image and resubmit.\n - \"The image could not be processed. Please retry.\" — transient server-side issue. Retry after a short delay; contact support if it persists.\n", "enum": [ "Invalid image name.", "Invalid image content.", "The image could not be processed. Please retry." ], "example": "The image could not be processed. Please retry." } } } } } } ````