From 7c2fd00ec0a3da2073fd69bdfff00ad83da2cf90 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 May 2026 10:25:21 +0000 Subject: [PATCH] chore: sync v3 specs from lambda v3.549.0 --- CHANGELOG.md | 18 + .../v3/v3-biometric-authentication-entry.yaml | 280 ++++++++++++ specs/v3/v3-biometric-enrollment-entry.yaml | 82 ++-- specs/v3/v3-biometric-kyc-entry.yaml | 76 ++-- specs/v3/v3-block-user.yaml | 261 +++++++++++ specs/v3/v3-document-verification-entry.yaml | 414 +++++++++++++++++ ...-enhanced-document-verification-entry.yaml | 424 ++++++++++++++++++ specs/v3/v3-enhanced-kyc-entry.yaml | 85 ++-- specs/v3/v3-enhanced-kyc-job-status.yaml | 152 +++++++ specs/v3/v3-id-status.yaml | 140 ++++++ specs/v3/v3-replay-callback.yaml | 47 +- specs/v3/v3-services.yaml | 205 +++++++++ specs/v3/v3-smart-selfie-compare-entry.yaml | 300 +++++++++++++ specs/v3/v3-supported-documents.yaml | 187 ++++++++ specs/v3/v3-token.yaml | 9 +- 15 files changed, 2536 insertions(+), 144 deletions(-) create mode 100644 specs/v3/v3-biometric-authentication-entry.yaml create mode 100644 specs/v3/v3-block-user.yaml create mode 100644 specs/v3/v3-document-verification-entry.yaml create mode 100644 specs/v3/v3-enhanced-document-verification-entry.yaml create mode 100644 specs/v3/v3-enhanced-kyc-job-status.yaml create mode 100644 specs/v3/v3-id-status.yaml create mode 100644 specs/v3/v3-services.yaml create mode 100644 specs/v3/v3-smart-selfie-compare-entry.yaml create mode 100644 specs/v3/v3-supported-documents.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index b44ede5..a603b63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to the Smile Identity API specifications will be documented The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +## [v3.549.0] - 2026-05-08 + +### Changed +- Updated `v3-biometric-authentication-entry` +- Updated `v3-biometric-enrollment-entry` +- Updated `v3-biometric-kyc-entry` +- Updated `v3-block-user` +- Updated `v3-document-verification-entry` +- Updated `v3-enhanced-document-verification-entry` +- Updated `v3-enhanced-kyc-entry` +- Updated `v3-enhanced-kyc-job-status` +- Updated `v3-id-status` +- Updated `v3-replay-callback` +- Updated `v3-services` +- Updated `v3-smart-selfie-compare-entry` +- Updated `v3-supported-documents` +- Updated `v3-token` + ### Added diff --git a/specs/v3/v3-biometric-authentication-entry.yaml b/specs/v3/v3-biometric-authentication-entry.yaml new file mode 100644 index 0000000..109a2e1 --- /dev/null +++ b/specs/v3/v3-biometric-authentication-entry.yaml @@ -0,0 +1,280 @@ +openapi: 3.0.0 +info: + title: V3 Biometric Authentication API + version: '1.0.0' + description: >- + Async biometric authentication endpoint (Smart Selfie™ Authentication). + Accepts a selfie image and liveness images, validates at entry, and queues the job + for async processing. The selfie is compared against the user's previously enrolled image. + Returns HTTP 202 with a job_id and user_id to track the result via callback. + + Authentication: token-based (token header from /v3/token). + + At least one of `email` or `phone_number` is required. The `user_id` field is required + and must match an existing enrolled user. +paths: + /v3/authenticate: + post: + summary: Submit biometric authentication + operationId: v3BiometricAuthentication + description: >- + Authenticates a user by comparing a submitted selfie against their enrolled image. + The selfie and liveness images are uploaded, validated at entry, then queued for + async ML processing (passive liveness, active liveness, face matching). + Results are delivered via callback URL. + + Supports `use_enrolled_image: true` to skip selfie/liveness upload and re-use the + enrolled image for the comparison (useful for server-side re-verification). + parameters: + - name: SmileID-Token + in: header + required: true + description: JWT token from /v3/token. + schema: + type: string + - name: SmileID-Source-SDK + in: header + required: false + description: Source SDK identifier. + schema: + type: string + example: 'android' + - name: SmileID-Source-SDK-Version + in: header + required: false + description: Source SDK version. + schema: + type: string + example: '10.4.2' + - name: SmileID-Timestamp + in: header + required: false + description: >- + ISO 8601 timestamp used as the salt when computing SmileID-Request-Signature. + schema: + type: string + format: date-time + - name: SmileID-Request-Signature + in: header + required: false + description: >- + HMAC signature of the raw HTTP request body. + schema: + type: string + - name: User-ID + in: header + required: false + description: >- + Partner-provided user identifier override. + schema: + type: string + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/BiometricAuthenticationRequest' + encoding: + selfie_image: + contentType: image/jpeg + liveness_images: + contentType: image/jpeg + responses: + '202': + description: Accepted — job queued for async processing. + content: + application/json: + schema: + $ref: '#/components/schemas/AcceptedResponse' + example: + status: Accepted + message: Request accepted and queued for processing. + job_id: job_01h8x9y2z3a4b5c6d7e8f9g0h1 + user_id: user_auth_001 + created_at: '2026-03-10T12:00:00.000Z' + '400': + description: Bad Request — validation error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + missingUserId: + summary: Missing user_id + value: + status: Bad Request + message: "Required field 'user_id' is missing or invalid." + missingContact: + summary: Missing email and phone + value: + status: Bad Request + message: Either email or phone_number is required. + '401': + description: Unauthorized — invalid or missing authentication credentials. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '402': + description: Payment Required — insufficient wallet balance. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden — partner not authorized for this product or IP. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '415': + description: Unsupported Media Type — request must be multipart/form-data. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '429': + description: Too Many Requests — rate limit exceeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + BiometricAuthenticationRequest: + type: object + required: + - user_id + - consent + - user_details + properties: + user_id: + type: string + description: >- + The enrolled user's identifier. Must match an existing enrollee. + example: user_auth_001 + selfie_image: + type: string + format: binary + description: >- + JPEG selfie image for authentication. Required unless use_enrolled_image is true. + liveness_images: + type: array + minItems: 6 + maxItems: 8 + items: + type: string + format: binary + description: >- + Array of 6–8 JPEG liveness images. Required unless use_enrolled_image is true. + consent: + $ref: '#/components/schemas/Consent' + user_details: + type: object + required: + - given_names + - last_name + description: >- + Consumer-stated PII fields for the user. + Either email or phone_number must be provided. + properties: + given_names: + type: string + minLength: 1 + example: Jane + last_name: + type: string + minLength: 1 + example: Smith + email: + type: string + format: email + nullable: true + description: At least one of email or phone_number is required. + example: jane@example.com + phone_number: + type: string + pattern: '^\+' + nullable: true + description: Phone number in E.164 format. At least one of email or phone_number is required. + example: '+2348012345678' + use_enrolled_image: + type: boolean + default: false + description: >- + If true, skips selfie and liveness image upload and uses the enrolled image + for re-verification. Useful for server-side re-authentication. + callback_url: + type: string + format: uri + description: URL to receive the async result callback. + example: https://example.com/callback + sandbox_result: + type: number + description: Force a specific result code in sandbox mode. + partner_params: + type: object + additionalProperties: + type: string + metadata: + type: array + items: + type: object + required: [name, value] + properties: + name: + type: string + maxLength: 100 + value: + type: string + maxLength: 1000 + + Consent: + type: object + required: [granted, granted_at, notice_language, notice_privacy_policy_url] + properties: + granted: + type: boolean + enum: [true] + granted_at: + type: string + format: date-time + notice_language: + type: string + minLength: 2 + maxLength: 2 + pattern: '^[A-Z]{2}$' + notice_privacy_policy_url: + type: string + format: uri + + AcceptedResponse: + type: object + properties: + status: + type: string + enum: [Accepted] + message: + type: string + job_id: + type: string + user_id: + type: string + created_at: + type: string + format: date-time + + ErrorResponse: + type: object + properties: + status: + type: string + message: + type: string diff --git a/specs/v3/v3-biometric-enrollment-entry.yaml b/specs/v3/v3-biometric-enrollment-entry.yaml index 023c971..7798f16 100644 --- a/specs/v3/v3-biometric-enrollment-entry.yaml +++ b/specs/v3/v3-biometric-enrollment-entry.yaml @@ -4,7 +4,7 @@ info: version: '1.0.0' description: >- Async biometric enrollment endpoint (Smart Selfie™ Enrollment). - Accepts a selfie image and liveness images, validates at entry, and processes the job + Accepts a selfie image and liveness images, validates at entry, and processes the verification asynchronously (passive liveness, active liveness). Returns HTTP 202 with a job_id and user_id to track the result via callback. @@ -12,7 +12,7 @@ info: At least one of `email` or `phone_number` is required. paths: - /v3/enroll: + /v3/registration: post: summary: Submit biometric enrollment operationId: v3BiometricEnrollment @@ -22,14 +22,6 @@ paths: asynchronously (passive liveness, active liveness). Results are delivered via callback URL. parameters: - - name: SmileID-Partner-ID - in: header - required: true - description: Partner identifier (numeric, 3+ digits). - schema: - type: string - pattern: '^\d{3,}$' - example: '1234' - name: SmileID-Token in: header required: true @@ -91,7 +83,7 @@ paths: contentType: image/jpeg responses: '202': - description: Accepted — job submitted for async processing. + description: Accepted — verification submitted for async processing. content: application/json: schema: @@ -214,8 +206,7 @@ components: - selfie_image - liveness_images - consent - - given_names - - last_name + - user_details properties: selfie_image: type: string @@ -235,18 +226,41 @@ components: These images are used for passive and active liveness verification. consent: $ref: '#/components/schemas/Consent' - given_names: - type: string - minLength: 1 - description: >- - Given name(s) / first name of the individual being enrolled. - example: John - last_name: - type: string - minLength: 1 + user_details: + type: object + required: + - given_names + - last_name description: >- - Last name / surname of the individual being enrolled. - example: Doe + Consumer-stated PII fields for the user. + Either email or phone_number must be provided. + properties: + given_names: + type: string + minLength: 1 + description: Given name(s) / first name of the individual being enrolled. + example: John + last_name: + type: string + minLength: 1 + description: Last name / surname of the individual being enrolled. + example: Doe + email: + type: string + format: email + nullable: true + description: >- + Email address of the individual being enrolled. + At least one of email or phone_number is required. + example: john@example.com + phone_number: + type: string + pattern: '^\+' + nullable: true + description: >- + Phone number in E.164 format (must start with +). + At least one of email or phone_number is required. + example: '+2348012345678' allow_new_enroll: type: boolean default: false @@ -261,22 +275,6 @@ components: URL to receive the async result callback. Falls back to partner default if omitted. Must be on the partner's allowed callback domains list. example: https://example.com/callback - email: - type: string - format: email - nullable: true - description: >- - Email address of the individual being enrolled. - At least one of email or phone_number is required. - example: john@example.com - phone_number: - type: string - pattern: '^\+' - nullable: true - description: >- - Phone number in E.164 format (must start with +). - At least one of email or phone_number is required. - example: '+2348012345678' sandbox_result: type: number description: >- @@ -347,7 +345,7 @@ components: example: Request accepted and queued for processing. job_id: type: string - description: TypeID format job identifier for tracking. + description: TypeID format verification identifier for tracking. example: job_01h8x9y2z3a4b5c6d7e8f9g0h1 user_id: type: string @@ -356,7 +354,7 @@ components: created_at: type: string format: date-time - description: ISO 8601 timestamp of when the job was created. + description: ISO 8601 timestamp of when the verification was created. example: '2026-03-10T12:00:00.000Z' ErrorResponse: diff --git a/specs/v3/v3-biometric-kyc-entry.yaml b/specs/v3/v3-biometric-kyc-entry.yaml index 01bad71..4fa4ecc 100644 --- a/specs/v3/v3-biometric-kyc-entry.yaml +++ b/specs/v3/v3-biometric-kyc-entry.yaml @@ -5,7 +5,7 @@ info: description: >- Async Biometric KYC endpoint combining biometric verification with KYC identity checks. Accepts a selfie image, liveness images, and ID details, validates at entry, and processes - the job asynchronously (passive liveness, active liveness, and ID authority verification). + the verification asynchronously (passive liveness, active liveness, and ID authority verification). Returns HTTP 202 with a job_id and user_id to track the result via callback. Authentication: token-based (token header from /v3/token). @@ -92,13 +92,13 @@ paths: contentType: image/jpeg responses: '202': - description: Accepted — job submitted for async processing. + description: Accepted — verification submitted for async processing. content: application/json: schema: $ref: '#/components/schemas/AcceptedResponse' example: - status: Accepted + status: accepted message: Request accepted and queued for processing. job_id: job_01h8x9y2z3a4b5c6d7e8f9g0h1 user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1 @@ -233,8 +233,7 @@ components: - country - id_type - id_number - - given_names - - last_name + - user_details properties: selfie_image: type: string @@ -268,18 +267,41 @@ components: type: string description: ID document number. Must match the regex format for the country/id_type. example: '12345678901' - given_names: - type: string - minLength: 1 - description: >- - Given name(s) / first name of the individual. - example: John - last_name: - type: string - minLength: 1 + user_details: + type: object + required: + - given_names + - last_name description: >- - Last name / surname of the individual. - example: Doe + Consumer-stated PII fields for the user. + Either email or phone_number must be provided. + properties: + given_names: + type: string + minLength: 1 + description: Given name(s) / first name of the individual. + example: John + last_name: + type: string + minLength: 1 + description: Last name / surname of the individual. + example: Doe + email: + type: string + format: email + nullable: true + description: >- + Email address of the individual. + At least one of email or phone_number is required. + example: john@example.com + phone_number: + type: string + pattern: '^\+' + nullable: true + description: >- + Phone number in E.164 format (must start with +). + At least one of email or phone_number is required. + example: '+2348012345678' callback_url: type: string format: uri @@ -287,22 +309,6 @@ components: URL to receive the async result callback. Falls back to partner default if omitted. Must be on the partner's allowed callback domains list. example: https://example.com/callback - email: - type: string - format: email - nullable: true - description: >- - Email address of the individual. - At least one of email or phone_number is required. - example: john@example.com - phone_number: - type: string - pattern: '^\+' - nullable: true - description: >- - Phone number in E.164 format (must start with +). - At least one of email or phone_number is required. - example: '+2348012345678' sandbox_result: type: number description: >- @@ -367,13 +373,13 @@ components: properties: status: type: string - enum: [Accepted] + enum: [accepted] message: type: string example: Request accepted and queued for processing. job_id: type: string - description: TypeID format job identifier for tracking. + description: TypeID format verification identifier for tracking. example: job_01h8x9y2z3a4b5c6d7e8f9g0h1 user_id: type: string @@ -382,7 +388,7 @@ components: created_at: type: string format: date-time - description: ISO 8601 timestamp of when the job was created. + description: ISO 8601 timestamp of when the verification was created. example: '2026-03-10T12:00:00.000Z' ErrorResponse: diff --git a/specs/v3/v3-block-user.yaml b/specs/v3/v3-block-user.yaml new file mode 100644 index 0000000..69c90c0 --- /dev/null +++ b/specs/v3/v3-block-user.yaml @@ -0,0 +1,261 @@ +openapi: 3.0.3 +info: + title: V3 Block User API + version: 1.0.0 + description: | + Block or unblock an enrolled user. Updates the user's fraud status, + active/deleted/allow_new_enroll state, and optionally marks associated verifications as + confirmed fraud. + + The `user_id` is specified in the URL path. The partner is identified from the + JWT token provided via the `SmileID-Token` header (obtained from + `POST /v3/token`). + + **Authentication**: Only JWT token auth is supported. Signature-based auth + (`smileid-request-signature` / `smileid-timestamp`) is not accepted. + +servers: + - url: https://api.smileidentity.com + description: Production + - url: https://testapi.smileidentity.com + description: Sandbox + - url: https://devapi.smileidentity.com + description: Development + +components: + securitySchemes: + SmileIDToken: + type: apiKey + in: header + name: SmileID-Token + description: JWT token obtained from `POST /v3/token`. + + schemas: + BlockUserRequest: + type: object + description: | + At least one of `is_fraudulent`, `active`, `allow_new_enroll`, or `deleted` + must be provided. Additional properties are not allowed. + properties: + is_fraudulent: + type: boolean + description: | + Set to `true` to mark the user as fraudulent (block), or `false` to + remove the fraud flag (unblock). + example: true + update_jobs: + type: boolean + description: | + When `true` **and** `is_fraudulent` is also provided, updates the + confirmed-fraud status on all verifications associated with this user. If + unblocking (`is_fraudulent: false`), also re-allows any previously-blocked + biometric matches linked to those verifications. + example: true + active: + type: boolean + description: | + Set to `true` to mark the enrollee as active, or `false` to mark + inactive. Internally stored as `inactive = !active`. + example: true + allow_new_enroll: + type: boolean + description: | + Set to `true` to allow the user to re-enroll, or `false` to prevent + re-enrollment. + example: true + deleted: + type: boolean + description: Soft-delete (`true`) or restore (`false`) the enrollee record. + example: false + additionalProperties: false + + BlockUserSuccessResponse: + type: object + required: + - message + - status + properties: + message: + type: string + description: Human-readable result message. + example: Enrollee user updated + status: + type: string + description: Operation status. + example: OK + + ErrorResponse: + type: object + required: + - message + - status + properties: + message: + type: string + description: Human-readable error message. + example: Enrollee not found + status: + type: string + description: HTTP status text. + example: Not Found + +security: + - SmileIDToken: [] + +paths: + /v3/users/{user_id}: + post: + operationId: blockUser + summary: Block or unblock an enrolled user + description: | + Updates an enrolled user's fraud status and/or enrollee state fields. + The partner is identified from the JWT token; `user_id` is taken from the + URL path. + + **Blocking a user** (`is_fraudulent: true`): + - Creates a new fraud record for the enrollee. + - Optionally (`update_jobs: true`) creates confirmed-fraud entries for all + associated verifications. + + **Unblocking a user** (`is_fraudulent: false`): + - Creates a new fraud record clearing the fraud flag. + - Optionally (`update_jobs: true`) soft-deletes confirmed-fraud entries and + re-allows previously-blocked biometric matches for associated verifications. + + **Updating enrollee state** (`active`, `allow_new_enroll`, `deleted`): + - Updates the corresponding fields on the enrollee record. + - Only fields present in the request body are modified; omitted fields are + left unchanged. + + A single indexing message is emitted after all database updates to ensure + the search index reflects the final state. + security: + - SmileIDToken: [] + parameters: + - name: user_id + in: path + required: true + description: | + The partner-scoped user identifier of the enrolled user to update. + This is the `user_id` value originally provided during enrollment. + schema: + type: string + example: user-123 + requestBody: + required: true + description: | + At least one actionable field (`is_fraudulent`, `active`, + `allow_new_enroll`, or `deleted`) must be provided. `update_jobs` alone + is not sufficient. + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/BlockUserRequest' + examples: + block: + summary: Block a user and update verifications + value: + is_fraudulent: true + update_jobs: true + unblock: + summary: Unblock a user and restore verifications + value: + is_fraudulent: false + update_jobs: true + updateState: + summary: Update enrollee state only + value: + active: true + allow_new_enroll: true + deleted: false + fullUpdate: + summary: Block user and update all fields + value: + active: false + allow_new_enroll: false + deleted: false + is_fraudulent: true + update_jobs: true + responses: + '200': + description: Enrollee updated successfully. + content: + application/json: + schema: + $ref: '#/components/schemas/BlockUserSuccessResponse' + example: + message: Enrollee user updated + status: OK + '400': + description: | + Validation error. Possible causes: + - `user_id` path parameter is missing. + - Request body is empty or missing all actionable fields. + - Unknown fields in request body. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: '"value" must contain at least one of [active, allow_new_enroll, deleted, is_fraudulent]' + status: Bad Request + '401': + description: Authentication failed (invalid or missing token). + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: Invalid token + status: Unauthorized + '402': + description: Insufficient wallet balance. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: You are out of credits. Add funds to your wallet to run more verifications. + status: Payment Required + '403': + description: | + Access denied. Possible causes: + - Production mode not enabled for partner. + - IP address is blocked. + - IP not in partner's allowlist. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: You are not authorized to do that. + status: Forbidden + '404': + description: No enrollee found for the given `user_id` and partner. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: Enrollee not found + status: Not Found + '415': + description: | + Wrong or missing `Content-Type` header. The request body must be sent + as `multipart/form-data`. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: Unsupported Media Type. Required Content-Type is multipart/form-data + status: Unsupported Media Type + '500': + description: Unexpected server error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: System Error + status: Internal Server Error diff --git a/specs/v3/v3-document-verification-entry.yaml b/specs/v3/v3-document-verification-entry.yaml new file mode 100644 index 0000000..b35aae2 --- /dev/null +++ b/specs/v3/v3-document-verification-entry.yaml @@ -0,0 +1,414 @@ +openapi: 3.0.0 +info: + title: V3 Document Verification API + version: '1.0.0' + description: >- + Async Document Verification endpoint. + Accepts a selfie image, liveness images, and a document image (front, and optionally back), + then verifies the document and the user's identity. + The id_type field is optional — the document type can be auto-classified if not provided. + Returns HTTP 202 with a job_id and user_id to track the result via callback. + + Authentication: token-based (token header from /v3/token). + + At least one of `email` or `phone_number` is required. +paths: + /v3/document-verification: + post: + summary: Submit Document Verification + operationId: v3DocumentVerificationEntry + description: >- + Verifies a user's identity by comparing a selfie against a document image. + The selfie and liveness images are uploaded alongside a document photo (front, and + optionally back). The id_type is optional — the document type is auto-classified if + not provided. + Results are delivered asynchronously via callback URL. + parameters: + - name: SmileID-Partner-ID + in: header + required: true + description: Partner identifier (numeric, 3+ digits). + schema: + type: string + pattern: '^\d{3,}$' + example: '1234' + - name: SmileID-Token + in: header + required: true + description: JWT token from /v3/token. + schema: + type: string + - name: SmileID-Source-SDK + in: header + required: false + description: Source SDK identifier. + schema: + type: string + example: 'android' + - name: SmileID-Source-SDK-Version + in: header + required: false + description: Source SDK version. + schema: + type: string + example: '10.4.2' + - name: SmileID-Timestamp + in: header + required: false + description: >- + ISO 8601 timestamp used as the salt when computing SmileID-Request-Signature. + Required when your Smile ID account is configured to use SDK/partner secret HMAC + authentication. + schema: + type: string + format: date-time + example: '2026-03-10T12:00:00.000Z' + - name: SmileID-Request-Signature + in: header + required: false + description: >- + HMAC signature of the raw HTTP request body, computed with your SDK/partner secret + and the value of SmileID-Timestamp as salt. Required when your Smile ID + account is configured to use SDK/partner secret HMAC authentication. + schema: + type: string + example: '4f2d9c6b8a7e3f1c0d5e4b3a2c1f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2' + - name: User-ID + in: header + required: false + description: >- + Partner-provided user identifier. If omitted, a TypeID is generated automatically. + schema: + type: string + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/DocumentVerificationRequest' + encoding: + selfie_image: + contentType: image/jpeg + liveness_images: + contentType: image/jpeg + document: + contentType: image/jpeg, image/png + document_back: + contentType: image/jpeg, image/png + responses: + '202': + description: Accepted — job submitted for processing. + content: + application/json: + schema: + $ref: '#/components/schemas/AcceptedResponse' + example: + status: accepted + message: Request accepted and queued for processing. + job_id: job_01h8x9y2z3a4b5c6d7e8f9g0h1 + user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + created_at: '2026-03-10T12:00:00.000Z' + '400': + description: Bad Request — validation error in request body or headers. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + missingDocument: + summary: Missing document image + value: + status: Bad Request + message: "Required field 'document' is missing or invalid." + missingSelfie: + summary: Missing selfie image + value: + status: Bad Request + message: "Required field 'selfie_image' is missing or invalid." + insufficientLiveness: + summary: Too few liveness images + value: + status: Bad Request + message: liveness_images must contain at least 6 images. + missingCountry: + summary: Missing required field + value: + status: Bad Request + message: "Required field 'country' is missing or invalid." + missingContact: + summary: Missing email and phone + value: + status: Bad Request + message: Either email or phone_number is required. + invalidConsent: + summary: Consent not granted + value: + status: Bad Request + message: "Required field 'consent.granted' is missing or invalid." + invalidDocumentMime: + summary: Invalid document image format + value: + status: Bad Request + message: Document image must be JPEG or PNG. + '401': + description: Unauthorized — invalid or missing authentication credentials. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Unauthorized + message: Invalid authentication credentials. + '402': + description: Payment Required — insufficient wallet balance. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Payment Required + message: Insufficient wallet balance. + '403': + description: Forbidden — partner not authorized for this product or IP. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + productAccess: + summary: Product not enabled + value: + status: Forbidden + message: Product not enabled for this partner. + productionAccess: + summary: Production access denied + value: + status: Forbidden + message: Production access is not enabled. + sdkVersion: + summary: SDK version blocked + value: + status: Forbidden + message: SDK version not allowed. + '413': + description: Content Too Large — an uploaded file exceeds the size limit. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Content Too Large + message: selfie_image is too large. + '415': + description: Unsupported Media Type — request must be multipart/form-data. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Unsupported Media Type + message: Unsupported Media Type. Required Content-Type is multipart/form-data + '429': + description: Too Many Requests — rate limit exceeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Too Many Requests + message: Rate limit exceeded. Please try again later. + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Internal Server Error + message: An unexpected error occurred. Please try again or contact support. + +components: + schemas: + DocumentVerificationRequest: + type: object + required: + - selfie_image + - liveness_images + - consent + - country + - document + - user_details + properties: + selfie_image: + type: string + format: binary + description: >- + JPEG selfie image used for biometric verification. + Must be a clear, well-lit, front-facing photo. + liveness_images: + type: array + minItems: 6 + maxItems: 8 + items: + type: string + format: binary + description: >- + Array of 6–8 JPEG liveness sequence images captured during the liveness check. + These images are used for liveness verification. + document: + type: string + format: binary + description: >- + Front of the identity document (JPEG or PNG). + Used for document verification. + document_back: + type: string + format: binary + description: >- + Back of the identity document (JPEG or PNG). Optional. + Provide when the document has relevant information on the back (e.g., barcodes, + MRZ on some document types). + consent: + $ref: '#/components/schemas/Consent' + country: + type: string + minLength: 2 + maxLength: 2 + description: ISO 3166-1 alpha-2 country code (uppercase). + example: NG + id_type: + type: string + description: >- + ID document type (e.g., DRIVERS_LICENSE, NATIONAL_ID). + Optional for standard Document Verification — the document type is + auto-classified if not provided. + example: DRIVERS_LICENSE + user_details: + type: object + required: + - given_names + - last_name + description: >- + Consumer-stated PII fields for the user. + Either email or phone_number must be provided. + properties: + given_names: + type: string + minLength: 1 + description: Given name(s) / first name of the individual. + example: John + last_name: + type: string + minLength: 1 + description: Last name / surname of the individual. + example: Doe + email: + type: string + format: email + nullable: true + description: >- + Email address of the individual. + At least one of email or phone_number is required. + example: john@example.com + phone_number: + type: string + pattern: '^\+' + nullable: true + description: >- + Phone number in E.164 format (must start with +). + At least one of email or phone_number is required. + example: '+2348012345678' + callback_url: + type: string + format: uri + description: >- + URL to receive the async result callback. Falls back to partner default if omitted. + Must be on the partner's allowed callback domains list. + example: https://example.com/callback + partner_params: + type: object + additionalProperties: + type: string + description: Arbitrary key-value metadata for partner reference. + example: + order_id: 'ORD-12345' + metadata: + type: array + description: Additional metadata entries (e.g., SDK telemetry, device info). + items: + type: object + required: + - name + - value + properties: + name: + type: string + maxLength: 100 + value: + type: string + maxLength: 1000 + + Consent: + type: object + required: + - granted + - granted_at + - notice_language + - notice_privacy_policy_url + properties: + granted: + type: boolean + enum: [true] + description: Must be true — user has granted consent. + granted_at: + type: string + format: date-time + description: ISO 8601 timestamp of when consent was granted. + example: '2026-03-06T12:00:00.000Z' + notice_language: + type: string + minLength: 2 + maxLength: 2 + pattern: '^[A-Z]{2}$' + description: ISO 639-1 language code of the privacy notice shown (uppercase). + example: EN + notice_privacy_policy_url: + type: string + format: uri + description: URL of the privacy policy notice shown to the user. + example: https://example.com/privacy + + AcceptedResponse: + type: object + properties: + status: + type: string + enum: [accepted] + message: + type: string + example: Request accepted and queued for processing. + job_id: + type: string + description: TypeID format job identifier for tracking. + example: job_01h8x9y2z3a4b5c6d7e8f9g0h1 + user_id: + type: string + description: TypeID format user identifier (or partner-provided User-ID). + example: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + created_at: + type: string + format: date-time + description: ISO 8601 timestamp of when the job was created. + example: '2026-03-10T12:00:00.000Z' + + ErrorResponse: + type: object + properties: + status: + type: string + description: HTTP status text. + example: Bad Request + message: + type: string + description: Human-readable error description. + example: "Required field 'country' is missing or invalid." diff --git a/specs/v3/v3-enhanced-document-verification-entry.yaml b/specs/v3/v3-enhanced-document-verification-entry.yaml new file mode 100644 index 0000000..f7031e8 --- /dev/null +++ b/specs/v3/v3-enhanced-document-verification-entry.yaml @@ -0,0 +1,424 @@ +openapi: 3.0.0 +info: + title: V3 Enhanced Document Verification API + version: '1.0.0' + description: >- + Async Enhanced Document Verification endpoint. + Combines document verification with identity data cross-referencing. + Accepts a selfie image, liveness images, and a document image (front, and optionally back), + along with a required id_type. + Returns HTTP 202 with a job_id and user_id to track the result via callback. + + Authentication: token-based (token header from /v3/token). + + At least one of `email` or `phone_number` is required. +paths: + /v3/enhanced-document-verification: + post: + summary: Submit Enhanced Document Verification + operationId: v3EnhancedDocumentVerificationEntry + description: >- + Verifies a user's identity by comparing a selfie against a document image and + cross-referencing extracted data for additional verification. + The selfie and liveness images are uploaded alongside a document photo (front, and + optionally back). The id_type is required for this endpoint. + Results are delivered asynchronously via callback URL. + parameters: + - name: SmileID-Partner-ID + in: header + required: true + description: Partner identifier (numeric, 3+ digits). + schema: + type: string + pattern: '^\d{3,}$' + example: '1234' + - name: SmileID-Token + in: header + required: true + description: JWT token from /v3/token. + schema: + type: string + - name: SmileID-Source-SDK + in: header + required: false + description: Source SDK identifier. + schema: + type: string + example: 'android' + - name: SmileID-Source-SDK-Version + in: header + required: false + description: Source SDK version. + schema: + type: string + example: '10.4.2' + - name: SmileID-Timestamp + in: header + required: false + description: >- + ISO 8601 timestamp used as the salt when computing SmileID-Request-Signature. + Required when your Smile ID account is configured to use SDK/partner secret HMAC + authentication. + schema: + type: string + format: date-time + example: '2026-03-10T12:00:00.000Z' + - name: SmileID-Request-Signature + in: header + required: false + description: >- + HMAC signature of the raw HTTP request body, computed with your SDK/partner secret + and the value of SmileID-Timestamp as salt. Required when your Smile ID + account is configured to use SDK/partner secret HMAC authentication. + schema: + type: string + example: '4f2d9c6b8a7e3f1c0d5e4b3a2c1f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2' + - name: User-ID + in: header + required: false + description: >- + Partner-provided user identifier. If omitted, a TypeID is generated automatically. + schema: + type: string + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/EnhancedDocumentVerificationRequest' + encoding: + selfie_image: + contentType: image/jpeg + liveness_images: + contentType: image/jpeg + document: + contentType: image/jpeg, image/png + document_back: + contentType: image/jpeg, image/png + responses: + '202': + description: Accepted — job submitted for processing. + content: + application/json: + schema: + $ref: '#/components/schemas/AcceptedResponse' + example: + status: accepted + message: Request accepted and queued for processing. + job_id: job_01h8x9y2z3a4b5c6d7e8f9g0h1 + user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + created_at: '2026-03-10T12:00:00.000Z' + '400': + description: Bad Request — validation error in request body or headers. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + missingDocument: + summary: Missing document image + value: + status: Bad Request + message: "Required field 'document' is missing or invalid." + missingIdType: + summary: Missing id_type (required for Enhanced DocV) + value: + status: Bad Request + message: "Required field 'id_type' is missing or invalid." + missingSelfie: + summary: Missing selfie image + value: + status: Bad Request + message: "Required field 'selfie_image' is missing or invalid." + insufficientLiveness: + summary: Too few liveness images + value: + status: Bad Request + message: liveness_images must contain at least 6 images. + missingCountry: + summary: Missing required field + value: + status: Bad Request + message: "Required field 'country' is missing or invalid." + missingContact: + summary: Missing email and phone + value: + status: Bad Request + message: Either email or phone_number is required. + invalidConsent: + summary: Consent not granted + value: + status: Bad Request + message: "Required field 'consent.granted' is missing or invalid." + invalidDocumentMime: + summary: Invalid document image format + value: + status: Bad Request + message: Document image must be JPEG or PNG. + '401': + description: Unauthorized — invalid or missing authentication credentials. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Unauthorized + message: Invalid authentication credentials. + '402': + description: Payment Required — insufficient wallet balance. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Payment Required + message: Insufficient wallet balance. + '403': + description: Forbidden — partner not authorized for this product, ID type, or IP. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + productAccess: + summary: Product not enabled + value: + status: Forbidden + message: Product not enabled for this partner. + idTypeDisabled: + summary: ID type not enabled + value: + status: Forbidden + message: ID type not enabled for this partner. + productionAccess: + summary: Production access denied + value: + status: Forbidden + message: Production access is not enabled. + sdkVersion: + summary: SDK version blocked + value: + status: Forbidden + message: SDK version not allowed. + '413': + description: Content Too Large — an uploaded file exceeds the size limit. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Content Too Large + message: selfie_image is too large. + '415': + description: Unsupported Media Type — request must be multipart/form-data. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Unsupported Media Type + message: Unsupported Media Type. Required Content-Type is multipart/form-data + '429': + description: Too Many Requests — rate limit exceeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Too Many Requests + message: Rate limit exceeded. Please try again later. + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Internal Server Error + message: An unexpected error occurred. Please try again or contact support. + +components: + schemas: + EnhancedDocumentVerificationRequest: + type: object + required: + - selfie_image + - liveness_images + - consent + - country + - document + - id_type + - user_details + properties: + selfie_image: + type: string + format: binary + description: >- + JPEG selfie image used for biometric verification. + Must be a clear, well-lit, front-facing photo. + liveness_images: + type: array + minItems: 6 + maxItems: 8 + items: + type: string + format: binary + description: >- + Array of 6–8 JPEG liveness sequence images captured during the liveness check. + These images are used for liveness verification. + document: + type: string + format: binary + description: >- + Front of the identity document (JPEG or PNG). + Used for document verification and data extraction. + document_back: + type: string + format: binary + description: >- + Back of the identity document (JPEG or PNG). Optional. + Provide when the document has relevant information on the back (e.g., barcodes, + MRZ on some document types). + consent: + $ref: '#/components/schemas/Consent' + country: + type: string + minLength: 2 + maxLength: 2 + description: ISO 3166-1 alpha-2 country code (uppercase). + example: NG + id_type: + type: string + description: >- + ID document type (e.g., DRIVERS_LICENSE, NATIONAL_ID). + Required for Enhanced Document Verification. + example: DRIVERS_LICENSE + user_details: + type: object + required: + - given_names + - last_name + description: >- + Consumer-stated PII fields for the user. + Either email or phone_number must be provided. + properties: + given_names: + type: string + minLength: 1 + description: Given name(s) / first name of the individual. + example: John + last_name: + type: string + minLength: 1 + description: Last name / surname of the individual. + example: Doe + email: + type: string + format: email + nullable: true + description: >- + Email address of the individual. + At least one of email or phone_number is required. + example: john@example.com + phone_number: + type: string + pattern: '^\+' + nullable: true + description: >- + Phone number in E.164 format (must start with +). + At least one of email or phone_number is required. + example: '+2348012345678' + callback_url: + type: string + format: uri + description: >- + URL to receive the async result callback. Falls back to partner default if omitted. + Must be on the partner's allowed callback domains list. + example: https://example.com/callback + partner_params: + type: object + additionalProperties: + type: string + description: Arbitrary key-value metadata for partner reference. + example: + order_id: 'ORD-12345' + metadata: + type: array + description: Additional metadata entries (e.g., SDK telemetry, device info). + items: + type: object + required: + - name + - value + properties: + name: + type: string + maxLength: 100 + value: + type: string + maxLength: 1000 + + Consent: + type: object + required: + - granted + - granted_at + - notice_language + - notice_privacy_policy_url + properties: + granted: + type: boolean + enum: [true] + description: Must be true — user has granted consent. + granted_at: + type: string + format: date-time + description: ISO 8601 timestamp of when consent was granted. + example: '2026-03-06T12:00:00.000Z' + notice_language: + type: string + minLength: 2 + maxLength: 2 + pattern: '^[A-Z]{2}$' + description: ISO 639-1 language code of the privacy notice shown (uppercase). + example: EN + notice_privacy_policy_url: + type: string + format: uri + description: URL of the privacy policy notice shown to the user. + example: https://example.com/privacy + + AcceptedResponse: + type: object + properties: + status: + type: string + enum: [accepted] + message: + type: string + example: Request accepted and queued for processing. + job_id: + type: string + description: TypeID format job identifier for tracking. + example: job_01h8x9y2z3a4b5c6d7e8f9g0h1 + user_id: + type: string + description: TypeID format user identifier (or partner-provided User-ID). + example: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + created_at: + type: string + format: date-time + description: ISO 8601 timestamp of when the job was created. + example: '2026-03-10T12:00:00.000Z' + + ErrorResponse: + type: object + properties: + status: + type: string + description: HTTP status text. + example: Bad Request + message: + type: string + description: Human-readable error description. + example: "Required field 'country' is missing or invalid." diff --git a/specs/v3/v3-enhanced-kyc-entry.yaml b/specs/v3/v3-enhanced-kyc-entry.yaml index 8796652..e3e4c1d 100644 --- a/specs/v3/v3-enhanced-kyc-entry.yaml +++ b/specs/v3/v3-enhanced-kyc-entry.yaml @@ -4,7 +4,7 @@ info: version: '1.0.0' description: >- Async Enhanced KYC endpoint for identity verification against ID authority databases. - Accepts a request, validates at entry, and processes the job asynchronously. + Accepts a request, validates at entry, and processes the verification asynchronously. Returns HTTP 202 with a job_id and user_id to track the result via callback. Authentication: token-based (token header from /v3/token). @@ -13,19 +13,12 @@ info: paths: /v3/enhanced_kyc: post: + operationId: submitEnhancedKyc summary: Submit Enhanced KYC verification description: >- - Allows submission of Enhanced KYC verification requests and processes the job asynchronously against the relevant ID authority. + Allows submission of Enhanced KYC verification requests and processes the verification asynchronously against the relevant ID authority. Results are delivered via callback URL. parameters: - - name: SmileID-Partner-ID - in: header - required: true - description: Partner identifier (numeric, 3+ digits). - schema: - type: string - pattern: '^\d{3,}$' - example: '1234' - name: SmileID-Token in: header required: true @@ -82,7 +75,7 @@ paths: $ref: '#/components/schemas/EnhancedKycRequest' responses: '202': - description: Accepted — job submitted for async processing. + description: Accepted — verification submitted for async processing. content: application/json: schema: @@ -109,6 +102,16 @@ paths: value: status: Bad Request message: Either email or phone_number is required. + invalidEmail: + summary: Invalid email format + value: + status: Bad Request + message: "Field 'email' is invalid." + invalidPhone: + summary: Invalid phone number format + value: + status: Bad Request + message: "Field 'phone_number' is invalid." invalidIdFormat: summary: Invalid ID number format value: @@ -204,8 +207,7 @@ components: - country - id_type - id_number - - given_names - - last_name + - user_details - consent properties: country: @@ -222,16 +224,37 @@ components: type: string description: ID document number. Must match the regex format for the country/id_type. example: '12345678901' - given_names: - type: string - minLength: 1 - description: Given names of the individual. - example: John - last_name: - type: string - minLength: 1 - description: Last name / surname of the individual. - example: Doe + user_details: + type: object + required: + - given_names + - last_name + description: >- + Consumer-stated PII fields for the user. + Either email or phone_number must be provided. + properties: + given_names: + type: string + minLength: 1 + description: Given names of the individual. + example: John + last_name: + type: string + minLength: 1 + description: Last name / surname of the individual. + example: Doe + email: + type: string + format: email + nullable: true + description: Email address. At least one of email or phone_number is required. + example: john@example.com + phone_number: + type: string + pattern: '^\+' + nullable: true + description: Phone number in E.164 format (must start with +). At least one of email or phone_number is required. + example: '+2348012345678' consent: $ref: '#/components/schemas/Consent' callback_url: @@ -241,18 +264,6 @@ components: URL to receive the async result callback. Falls back to partner default if omitted. Must be on the partner's allowed callback domains list. example: https://example.com/callback - email: - type: string - format: email - nullable: true - description: Email address. At least one of email or phone_number is required. - example: john@example.com - phone_number: - type: string - pattern: '^\+' - nullable: true - description: Phone number in E.164 format (must start with +). At least one of email or phone_number is required. - example: '+2348012345678' bank_code: type: string description: Bank code (required for certain ID types like BANK_ACCOUNT). @@ -323,7 +334,7 @@ components: example: Request accepted and queued for processing. job_id: type: string - description: TypeID format job identifier for tracking. + description: TypeID format verification identifier for tracking. example: job_01h8x9y2z3a4b5c6d7e8f9g0h1 user_id: type: string @@ -332,7 +343,7 @@ components: created_at: type: string format: date-time - description: ISO 8601 timestamp of when the job was created. + description: ISO 8601 timestamp of when the verification was created. example: '2026-03-10T12:00:00.000Z' ErrorResponse: diff --git a/specs/v3/v3-enhanced-kyc-job-status.yaml b/specs/v3/v3-enhanced-kyc-job-status.yaml new file mode 100644 index 0000000..4d4f309 --- /dev/null +++ b/specs/v3/v3-enhanced-kyc-job-status.yaml @@ -0,0 +1,152 @@ +openapi: 3.0.0 +info: + title: V3 Verification Status API + version: '1.0.0' + description: >- + Retrieves the current status of a verification by its TypeID. + + Authentication: token-based (SmileID-Token header with JWT from /v3/token). + + The response includes the verification's current state, + mapped to one of: processing, complete, or not_found. + +paths: + /v3/status/{jobId}: + get: + operationId: getEnhancedKycJobStatus + summary: Get verification status + description: >- + Retrieves the current status of a previously submitted verification. + Returns the latest state from the verification lifecycle (processing, clear, block, attention, error). + parameters: + - name: jobId + in: path + required: true + description: TypeID format verification identifier with 'job_' prefix. + schema: + type: string + pattern: '^job_[0-9a-hjkmnp-tv-z]{26}$' + example: 'job_01h2xcejqtf2nbrexx3vqjhp41' + - name: SmileID-Token + in: header + required: true + description: JWT token from /v3/token. + schema: + type: string + responses: + '200': + description: Verification has reached a terminal state (clear, block, attention, or error). + content: + application/json: + schema: + $ref: '#/components/schemas/JobStatusResponse' + example: + status: complete + job_id: job_01h2xcejqtf2nbrexx3vqjhp41 + user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + message: 'Verification completed with state: clear' + '202': + description: Verification is still processing. + content: + application/json: + schema: + $ref: '#/components/schemas/JobStatusResponse' + example: + status: processing + job_id: job_01h2xcejqtf2nbrexx3vqjhp41 + user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + message: Verification is still processing + '400': + description: Bad Request — invalid jobId format. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Bad Request + message: '"jobId" must be a valid TypeID with prefix ''job_''' + '401': + description: Unauthorized — invalid or missing authentication credentials. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Unauthorized + message: Invalid authentication credentials. + '403': + description: Forbidden — IP not in allowlist. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Forbidden + message: You are not authorized to do that. + '404': + description: Not Found — verification does not exist or does not belong to this partner. + content: + application/json: + schema: + $ref: '#/components/schemas/JobStatusResponse' + example: + status: not_found + job_id: job_01h2xcejqtf2nbrexx3vqjhp41 + user_id: unknown + message: Verification not found + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + status: Internal Server Error + message: An unexpected error occurred. Please try again or contact support. + +components: + schemas: + JobStatusResponse: + type: object + required: + - status + - job_id + - user_id + - message + properties: + status: + type: string + description: >- + Verification status. One of: complete (terminal state reached), + processing (still in progress), not_found. + enum: + - complete + - processing + - not_found + example: complete + job_id: + type: string + description: TypeID format verification identifier. + example: job_01h2xcejqtf2nbrexx3vqjhp41 + user_id: + type: string + description: User ID associated with the verification. + example: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + message: + type: string + description: Human-readable status message. + example: 'Verification completed with state: clear' + ErrorResponse: + type: object + required: + - status + - message + properties: + status: + type: string + description: HTTP status text. + example: Bad Request + message: + type: string + description: Human-readable error message. + example: '"jobId" must be a valid TypeID with prefix ''job_''' diff --git a/specs/v3/v3-id-status.yaml b/specs/v3/v3-id-status.yaml new file mode 100644 index 0000000..c34f3af --- /dev/null +++ b/specs/v3/v3-id-status.yaml @@ -0,0 +1,140 @@ +openapi: 3.0.3 +info: + title: Smile ID – ID Status API + description: | + Returns the current availability status of a given ID type for a country. + + **Authentication**: Only JWT token auth is supported. Pass the token + obtained from `POST /v3/token` in the `SmileID-Token` header. + Signature-based auth (`smileid-request-signature` / `smileid-timestamp`) + is not accepted. + version: 3.0.0 + +paths: + /v3/services/id_status: + get: + operationId: getIdStatus + summary: Get ID type availability status + description: | + Returns the current availability and success rate for a specific ID type + in a given country, based on uptime data from the last hour. + + Requires authentication via JWT token. + tags: + - Services + security: + - SmileIDToken: [] + parameters: + - name: country + in: query + required: true + description: ISO 3166-1 alpha-2 country code or full country name (e.g. "NG" or "Nigeria"). + schema: + type: string + example: NG + - name: id_type + in: query + required: true + description: The ID type code to check status for (e.g. "BVN", "NIN", "VOTER_ID"). + schema: + type: string + example: BVN + responses: + '200': + description: ID status retrieved successfully. + content: + application/json: + schema: + type: object + required: + - last_checked + - last_check_status + - last_hour_success_rate + - last_known_status + - last_check_success_rate + properties: + last_checked: + type: string + format: date-time + description: Timestamp of the most recent uptime check. + example: '2026-04-14T12:30:00.000Z' + last_check_status: + type: string + enum: [success, failure] + description: Whether the most recent check succeeded or failed. + example: success + last_hour_success_rate: + type: string + description: Aggregate success rate over the last hour as a percentage. + example: '95%' + last_known_status: + type: string + description: The raw status string from the most recent check (e.g. "online", "offline"). + example: online + last_check_success_rate: + type: string + description: Success rate of the most recent individual check as a percentage. + example: '90%' + example: + last_checked: '2026-04-14T12:30:00.000Z' + last_check_status: success + last_hour_success_rate: '95%' + last_known_status: online + last_check_success_rate: '90%' + '400': + description: Bad request – missing or invalid parameters, or no uptime data found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + missingCountry: + summary: Country parameter missing + value: + message: '"country" is required' + status: Bad Request + invalidCountry: + summary: Invalid country value + value: + message: Invalid country + status: Bad Request + invalidIdType: + summary: ID type not valid for country + value: + message: Invalid id_type for the given country + status: Bad Request + noData: + summary: No uptime data in the last hour + value: + message: 'No data found. Check that NG and BVN are valid inputs' + status: Bad Request + '401': + description: Authentication failed. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + message: Invalid token + status: Unauthorized + +components: + securitySchemes: + SmileIDToken: + type: apiKey + in: header + name: SmileID-Token + description: JWT token obtained from `POST /v3/token`. + schemas: + ErrorResponse: + type: object + required: + - message + - status + properties: + message: + type: string + description: Human-readable error message. + status: + type: string + description: HTTP status text (e.g. "Bad Request", "Unauthorized"). diff --git a/specs/v3/v3-replay-callback.yaml b/specs/v3/v3-replay-callback.yaml index 56919f1..45bda93 100644 --- a/specs/v3/v3-replay-callback.yaml +++ b/specs/v3/v3-replay-callback.yaml @@ -3,25 +3,26 @@ info: title: V3 Replay Callback API version: '1.0.0' description: >- - Re-sends a callback webhook for a completed job so the partner receives it again. + Re-sends a callback webhook for a completed verification so the partner receives it again. This is a generic endpoint that works for any V3 product — the product is - inferred from the original job. + inferred from the original verification. Authentication: token-based (SmileID-Token header with JWT from /v3/token). Callback URL resolution order: 1. `callback_url` from request body (validated against partner's allowed domains) - 2. `callback_url` stored with the original job + 2. `callback_url` stored with the original verification 3. Partner's default callback URL paths: /v3/replay/{job_id}: post: - summary: Replay a callback for a completed job + operationId: replayCallback + summary: Replay a callback for a completed verification description: >- - Looks up a previously completed job by its TypeID, resolves the callback - URL, and re-sends the callback. The job must have reached a + Looks up a previously completed verification by its TypeID, resolves the callback + URL, and re-sends the callback. The verification must have reached a terminal state (clear, block, attention, or error) before its callback can be replayed. @@ -31,19 +32,11 @@ paths: - name: job_id in: path required: true - description: TypeID format job identifier with 'job_' prefix. + description: TypeID format verification identifier with 'job_' prefix. schema: type: string pattern: '^job_[0-9a-z]{26}$' example: 'job_01h2xcejqtf2nbrexx3vqjhp41' - - name: SmileID-Partner-ID - in: header - required: true - description: Partner identifier (numeric, 3+ digits). - schema: - type: string - pattern: '^\d{3,}$' - example: '1234' - name: SmileID-Token in: header required: true @@ -54,7 +47,7 @@ paths: required: false description: >- Optional body to override the callback URL. If omitted, the stored - callback URL (from the original job or partner default) + callback URL (from the original verification or partner default) is used. content: application/json: @@ -97,7 +90,7 @@ paths: summary: Product cannot be inferred value: status: Bad Request - message: Unable to determine product for this job + message: Unable to determine product for this verification '401': description: Unauthorized — invalid or missing authentication credentials. content: @@ -120,7 +113,7 @@ paths: message: You are not authorized to do that. '404': description: >- - Not Found — job does not exist, does not belong to this partner, or + Not Found — verification does not exist, does not belong to this partner, or has no reference entry. content: application/json: @@ -128,18 +121,18 @@ paths: $ref: '#/components/schemas/ErrorResponse' examples: jobNotFound: - summary: Job not found or belongs to another partner + summary: Verification not found or belongs to another partner value: status: Not Found - message: Job not found + message: Verification not found referenceNotFound: - summary: Reference entry missing for the job + summary: Reference entry missing for the verification value: status: Not Found - message: Reference not found for this job + message: Reference not found for this verification '409': description: >- - Conflict — job has not yet reached a terminal state. Wait for + Conflict — verification has not yet reached a terminal state. Wait for processing to complete before replaying the callback. content: application/json: @@ -148,8 +141,8 @@ paths: example: status: Conflict message: >- - Job is still processing. Callbacks can only be replayed for - completed jobs. + Verification is still processing. Callbacks can only be replayed for + completed verifications. '500': description: Internal Server Error content: @@ -188,11 +181,11 @@ components: example: accepted job_id: type: string - description: TypeID format job identifier. + description: TypeID format verification identifier. example: job_01h2xcejqtf2nbrexx3vqjhp41 user_id: type: string - description: User ID associated with the job (from partner_params). + description: User ID associated with the verification (from partner_params). example: test-user message: type: string diff --git a/specs/v3/v3-services.yaml b/specs/v3/v3-services.yaml new file mode 100644 index 0000000..092c506 --- /dev/null +++ b/specs/v3/v3-services.yaml @@ -0,0 +1,205 @@ +openapi: 3.0.3 +info: + title: V3 Services API + version: 1.0.0 + description: | + Read-only reference endpoints that return static configuration data: supported bank + codes and KYC ID types. Both endpoints accept an optional `country` query parameter + to filter results by ISO 3166-1 alpha-2 country code. + + These endpoints do not require authentication. + +servers: + - url: https://api.smileidentity.com + description: Production + - url: https://testapi.smileidentity.com + description: Sandbox + - url: https://devapi.smileidentity.com + description: Development + +components: + parameters: + CountryFilter: + name: country + in: query + required: false + description: | + ISO 3166-1 alpha-2 country code (two uppercase letters). When provided, only + items matching this country are returned. When omitted, all items are returned. + schema: + type: string + pattern: '^[A-Z]{2}$' + example: NG + + schemas: + BankCode: + type: object + required: + - code + - country + - name + properties: + code: + type: string + description: Numeric bank code assigned by the country's central bank. + example: '044' + country: + type: string + description: ISO 3166-1 alpha-2 country code. + example: NG + name: + type: string + description: Human-readable bank name. + example: Access Bank + + BankCodesResponse: + type: object + properties: + bank_codes: + type: array + items: + $ref: '#/components/schemas/BankCode' + + SupportedIdType: + type: object + required: + - country + - type + - label + - regex + properties: + bank_code: + type: string + description: | + Bank code required for this ID type. Only present for ID types that are + bank-specific (e.g. `BANK_ACCOUNT`). + example: '044' + country: + type: string + description: ISO 3166-1 alpha-2 country code. + example: NG + label: + type: string + description: Human-readable label for the ID type. + example: Bank Verification Number + regex: + type: string + description: | + Regular expression pattern (without delimiters) that the ID number must + match for this ID type. + example: '^\d{11}$' + required_fields: + type: array + items: + type: string + description: | + List of field names that must be provided when submitting a verification + request for this ID type (e.g. `first_name`, `last_name`, `dob`). + example: + - first_name + - last_name + - dob + type: + type: string + description: Machine-readable ID type code. + example: BVN + + SupportedIdTypesResponse: + type: object + properties: + id_types: + type: array + items: + $ref: '#/components/schemas/SupportedIdType' + + ErrorResponse: + type: object + properties: + error: + type: string + description: Human-readable error message. + code: + type: string + description: Smile Identity error code. + +paths: + /v3/services/bank_codes: + get: + operationId: getBankCodes + summary: List bank codes + description: | + Returns a list of bank codes supported for bank-account-based identity + verification. Optionally filtered by country. + security: [] + parameters: + - $ref: '#/components/parameters/CountryFilter' + responses: + '200': + description: Successful response containing bank codes. + content: + application/json: + schema: + $ref: '#/components/schemas/BankCodesResponse' + example: + bank_codes: + - code: '044' + country: NG + name: Access Bank + - code: '023' + country: NG + name: Citibank + '403': + description: Request blocked (IP blocked). + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: You are not authorized to do that. + code: '2413' + + /v3/services/supported_id_types: + get: + operationId: getSupportedIdTypes + summary: List supported KYC ID types + description: | + Returns a list of all KYC ID types supported for identity verification, + including their validation regex, required fields, and optional bank code. + Optionally filtered by country. + security: [] + parameters: + - $ref: '#/components/parameters/CountryFilter' + responses: + '200': + description: Successful response containing supported ID types. + content: + application/json: + schema: + $ref: '#/components/schemas/SupportedIdTypesResponse' + example: + id_types: + - country: NG + label: Bank Verification Number + regex: '^\d{11}$' + required_fields: + - first_name + - last_name + - dob + type: BVN + - bank_code: '044' + country: NG + label: Bank Account (Access Bank) + regex: '^\d{10}$' + required_fields: + - first_name + - last_name + type: BANK_ACCOUNT + '403': + description: Request blocked (IP blocked). + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: You are not authorized to do that. + code: '2413' diff --git a/specs/v3/v3-smart-selfie-compare-entry.yaml b/specs/v3/v3-smart-selfie-compare-entry.yaml new file mode 100644 index 0000000..b66e1b1 --- /dev/null +++ b/specs/v3/v3-smart-selfie-compare-entry.yaml @@ -0,0 +1,300 @@ +openapi: 3.0.0 +info: + title: V3 Smart Selfie Compare API + version: '1.0.0' + description: >- + Async smart selfie compare endpoint (Smart Selfie™ Compare). + Accepts a selfie image and a comparison image, validates at entry, and queues the job + for async processing (passive liveness, face matching, optional active liveness). + Returns HTTP 202 with a job_id and user_id to track the result via callback. + + Authentication: token-based (token header from /v3/token). + + At least one of `email` or `phone_number` is required. +paths: + /v3/smart_selfie_compare: + post: + summary: Submit smart selfie compare + operationId: v3SmartSelfieCompare + description: >- + Compares a selfie image against a provided comparison image (document, ID photo, or portrait). + The images are uploaded, validated at entry, then queued for async ML processing + (passive liveness, face matching, optional active liveness with liveness images). + Results are delivered via callback URL. + + If `user_id` is provided and the comparison passes, the user will be enrolled. + parameters: + - name: SmileID-Token + in: header + required: true + description: JWT token from /v3/token. + schema: + type: string + - name: SmileID-Source-SDK + in: header + required: false + description: Source SDK identifier. + schema: + type: string + example: 'ios' + - name: SmileID-Source-SDK-Version + in: header + required: false + description: Source SDK version. + schema: + type: string + example: '10.3.1' + - name: SmileID-Timestamp + in: header + required: false + description: >- + ISO 8601 timestamp used as the salt when computing SmileID-Request-Signature. + schema: + type: string + format: date-time + - name: SmileID-Request-Signature + in: header + required: false + description: >- + HMAC signature of the raw HTTP request body. + schema: + type: string + - name: User-ID + in: header + required: false + description: >- + Partner-provided user identifier. If omitted, a TypeID is generated automatically. + schema: + type: string + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/SmartSelfieCompareRequest' + encoding: + selfie_image: + contentType: image/jpeg + comparison_image: + contentType: image/jpeg + liveness_images: + contentType: image/jpeg + responses: + '202': + description: Accepted — job queued for async processing. + content: + application/json: + schema: + $ref: '#/components/schemas/AcceptedResponse' + example: + status: Accepted + message: Request accepted and queued for processing. + job_id: job_01h8x9y2z3a4b5c6d7e8f9g0h1 + user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1 + created_at: '2026-03-10T12:00:00.000Z' + '400': + description: Bad Request — validation error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + missingSelfie: + summary: Missing selfie image + value: + status: Bad Request + message: "Required field 'selfie_image' is missing or invalid." + missingComparisonImage: + summary: Missing comparison image + value: + status: Bad Request + message: "Required field 'comparison_image' is missing or invalid." + invalidComparisonType: + summary: Invalid comparison image type + value: + status: Bad Request + message: "Field 'comparison_image_type' must be either DOCUMENT, ID_PHOTO, or PORTRAIT." + missingContact: + summary: Missing email and phone + value: + status: Bad Request + message: Either email or phone_number is required. + '401': + description: Unauthorized — invalid or missing authentication credentials. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '402': + description: Payment Required — insufficient wallet balance. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden — partner not authorized for this product or IP. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '415': + description: Unsupported Media Type — request must be multipart/form-data. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '429': + description: Too Many Requests — rate limit exceeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + SmartSelfieCompareRequest: + type: object + required: + - selfie_image + - comparison_image + - comparison_image_type + - consent + - user_details + properties: + selfie_image: + type: string + format: binary + description: JPEG selfie image. + comparison_image: + type: string + format: binary + description: >- + JPEG comparison image (ID card photo, ID photo, or portrait). + comparison_image_type: + type: string + enum: [DOCUMENT, ID_PHOTO, PORTRAIT] + description: >- + Type of comparison image being submitted. + consent: + $ref: '#/components/schemas/Consent' + user_details: + type: object + required: + - given_names + - last_name + description: >- + Consumer-stated PII fields for the user. + Either email or phone_number must be provided. + properties: + given_names: + type: string + minLength: 1 + example: Alice + last_name: + type: string + minLength: 1 + example: Johnson + email: + type: string + format: email + nullable: true + description: At least one of email or phone_number is required. + example: alice@example.com + phone_number: + type: string + pattern: '^\+' + nullable: true + description: Phone number in E.164 format. At least one of email or phone_number is required. + example: '+2348012345678' + liveness_images: + type: array + minItems: 6 + maxItems: 8 + items: + type: string + format: binary + description: >- + Optional array of 6–8 JPEG liveness images. If omitted, active liveness check + is skipped. + allow_new_enroll: + type: boolean + default: false + description: >- + If true, allows re-enrollment for a user who is already enrolled. + user_id: + type: string + description: >- + Optional user identifier. If provided and the job passes, the user will be enrolled. + callback_url: + type: string + format: uri + description: URL to receive the async result callback. + example: https://example.com/callback + sandbox_result: + type: number + description: Force a specific result code in sandbox mode. + partner_params: + type: object + additionalProperties: + type: string + metadata: + type: array + items: + type: object + required: [name, value] + properties: + name: + type: string + maxLength: 100 + value: + type: string + maxLength: 1000 + + Consent: + type: object + required: [granted, granted_at, notice_language, notice_privacy_policy_url] + properties: + granted: + type: boolean + enum: [true] + granted_at: + type: string + format: date-time + notice_language: + type: string + minLength: 2 + maxLength: 2 + pattern: '^[A-Z]{2}$' + notice_privacy_policy_url: + type: string + format: uri + + AcceptedResponse: + type: object + properties: + status: + type: string + enum: [Accepted] + message: + type: string + job_id: + type: string + user_id: + type: string + created_at: + type: string + format: date-time + + ErrorResponse: + type: object + properties: + status: + type: string + message: + type: string diff --git a/specs/v3/v3-supported-documents.yaml b/specs/v3/v3-supported-documents.yaml new file mode 100644 index 0000000..35946c4 --- /dev/null +++ b/specs/v3/v3-supported-documents.yaml @@ -0,0 +1,187 @@ +openapi: 3.0.3 +info: + title: V3 Supported Documents API + version: 1.0.0 + description: | + Retrieves a list of supported document types for identity verification, filterable by + continent, country code, or locale. + + This endpoint does not require authentication. + + This endpoint is an alias of `GET /v1/valid_documents` and `GET /v3/valid-documents`, + providing the same data under a more descriptive path. + +servers: + - url: https://api.smileidentity.com + description: Production + - url: https://testapi.smileidentity.com + description: Sandbox + - url: https://devapi.smileidentity.com + description: Development + +components: + schemas: + Country: + type: object + properties: + code: + type: string + description: ISO 3166-1 alpha-2 country code. + example: NG + name: + type: string + description: Country name. + example: Nigeria + continent: + type: string + description: Continent name. + example: AFRICA + + IDType: + type: object + properties: + code: + type: string + description: Machine-readable ID type code. + example: DRIVERS_LICENSE + name: + type: string + description: Human-readable name of the ID type. + example: Driver's License + example: + type: array + items: + type: string + description: Example ID numbers or usage hints. + has_back: + type: boolean + description: Whether this document type has a back side that should be captured. + example: true + + SupportedDocument: + type: object + properties: + country: + $ref: '#/components/schemas/Country' + id_types: + type: array + items: + $ref: '#/components/schemas/IDType' + + SupportedDocumentsResponse: + type: object + properties: + valid_documents: + type: array + items: + $ref: '#/components/schemas/SupportedDocument' + required: + - valid_documents + + ErrorResponse: + type: object + properties: + error: + type: string + description: Human-readable error message. + code: + type: string + description: Smile Identity error code. + required: + - error + - code + +paths: + /v3/services/supported_documents: + get: + summary: List supported documents for verification + operationId: getSupportedDocuments + description: | + Returns a list of supported document types for identity verification across all + countries served by Smile Identity. + + The response can be filtered by continent or country code. An optional `locale` + parameter controls the language of document names. + tags: + - Services + security: [] + parameters: + - name: continent + in: query + required: false + description: Filter results to a single continent. + schema: + type: string + enum: + - AFRICA + - ASIA + - EUROPE + - 'NORTH AMERICA' + - OCEANIA + - 'SOUTH AMERICA' + example: AFRICA + - name: country_code + in: query + required: false + description: | + Filter results to a single country. Must be an ISO 3166-1 alpha-2 code + (two uppercase letters). + schema: + type: string + pattern: '^[A-Z]{2}$' + example: NG + - name: locale + in: query + required: false + description: | + Locale for document names. Defaults to `en-GB`. + Supported values: `en-GB`, `fr-FR`, `ar-EG`. + schema: + type: string + default: en-GB + enum: + - en-GB + - fr-FR + - ar-EG + responses: + '200': + description: List of supported documents, optionally filtered. + content: + application/json: + schema: + $ref: '#/components/schemas/SupportedDocumentsResponse' + example: + valid_documents: + - country: + code: NG + name: Nigeria + continent: AFRICA + id_types: + - code: DRIVERS_LICENSE + name: Driver's License + example: ['AAA00000AA00'] + has_back: true + - code: NATIONAL_ID + name: National ID (NIN Slip) + example: ['00000000000'] + has_back: false + '400': + description: Invalid query parameters. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: >- + Country Code must be a valid ISO 3166-1 alpha-2 country code + consisting of exactly two uppercase letters. + code: '2413' + '500': + description: Internal server error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: System Error + code: '2401' diff --git a/specs/v3/v3-token.yaml b/specs/v3/v3-token.yaml index a4710dd..1e28f8b 100644 --- a/specs/v3/v3-token.yaml +++ b/specs/v3/v3-token.yaml @@ -8,17 +8,17 @@ info: paths: /v3/token: post: + operationId: getV3Token summary: Generate v3 Auth Token description: Issues a short-lived JWT for authenticating subsequent v3 API requests. parameters: - name: smileid-partner-id in: header required: true - description: >- - Your unique partner identifier. Must be a numeric string with at least 3 digits. + description: Your unique partner identifier. Must be numeric with no leading zeros. schema: type: string - pattern: '^\d{3,}$' + pattern: '^[1-9]\d*$' example: '1234' - name: smileid-api-key in: header @@ -42,6 +42,9 @@ paths: schema: type: object properties: + user_id: + type: string + description: Optional partner-provided user identifier. partner_params: type: object additionalProperties: