diff --git a/CHANGELOG.md b/CHANGELOG.md
index e64768a..d245046 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
+## [v3.1094.0] - 2026-10-29
+
+### Changed
+- Updated `openapi`
+- Updated `v3-address-entry`
+- Updated `v3-phone-verification-entry`
+- Updated `v3-replay-callback`
+- Updated `v3-token`
+
+
## [v3.1090.0] - 2026-10-28
### Changed
diff --git a/README.md b/README.md
index 570b501..42c9e2f 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ OpenAPI 3.0 specifications for the Smile Identity v3 API.
| [Enhanced KYC](specs/v3/v3-enhanced-kyc-entry.yaml) | `POST /v3/enhanced_kyc/sync` | Submit Enhanced KYC verification synchronously |
| [One Time Aml](specs/v3/v3-one-time-aml-entry.yaml) | `POST /v3/aml` | Submit One-Time AML screening |
| [One Time Aml](specs/v3/v3-one-time-aml-entry.yaml) | `POST /v3/aml/sync` | Submit One-Time AML screening and receive the result inline |
+| [Phone Verification](specs/v3/v3-phone-verification-entry.yaml) | `POST /v3/phone` | Submit a phone number verification |
| [Replay Callback](specs/v3/v3-replay-callback.yaml) | `POST /v3/replay/{job_id}` | Replay a callback for a completed verification |
| [Report User Fraud](specs/v3/v3-report-user-fraud.yaml) | `POST /v3/users/{user_id}/report_fraud` | Flag or clear fraud status for a user |
| [Residency Document Verification](specs/v3/v3-residency-document-verification-entry.yaml) | `POST /v3/residency_document_verification` | Submit Residency Document Verification |
diff --git a/docs/index.html b/docs/index.html
index 1942ab5..0a588e4 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -241,6 +241,7 @@
APIs
{ file: "v3-enhanced-document-verification-entry", label: "Enhanced Document Verification" },
{ file: "v3-enhanced-kyc-entry", label: "Enhanced KYC" },
{ file: "v3-one-time-aml-entry", label: "One Time Aml" },
+ { file: "v3-phone-verification-entry", label: "Phone Verification" },
{ file: "v3-replay-callback", label: "Replay Callback" },
{ file: "v3-report-user-fraud", label: "Report User Fraud" },
{ file: "v3-residency-document-verification-entry", label: "Residency Document Verification" },
diff --git a/specs/v3/openapi.yaml b/specs/v3/openapi.yaml
index 11fdc24..a072189 100644
--- a/specs/v3/openapi.yaml
+++ b/specs/v3/openapi.yaml
@@ -25,6 +25,7 @@ tags:
- name: Enhanced Document Verification
- name: Enhanced KYC
- name: One-Time AML
+ - name: Phone Number Verification
- name: Residency Document Verification
- name: Services
- name: Smart Selfie Compare
@@ -58,42 +59,7 @@ paths:
* `block` (`identifier_not_found`) — the provider has no record for the ID or utility number.
* `error` (`service_unavailable`) — the provider could not be reached.
- parameters:
- - name: SmileID-Source-SDK
- in: header
- required: false
- description: Source SDK identifier.
- schema:
- type: string
- example: rest_api
- - name: SmileID-Source-SDK-Version
- in: header
- required: false
- description: Source SDK version.
- schema:
- type: string
- example: 1.0.0
- - name: SmileID-Timestamp
- in: header
- required: false
- x-smile-sdk-exclude: true
- 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
- x-smile-sdk-exclude: true
- 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
+ parameters: []
requestBody:
required: true
content:
@@ -2394,6 +2360,114 @@ paths:
example:
status: Internal Server Error
message: An unexpected error occurred. Please try again or contact support.
+ /v3/phone:
+ post:
+ summary: Submit a phone number verification
+ operationId: v3PhoneVerification
+ tags:
+ - Phone Number Verification
+ security:
+ - SmileIDToken: []
+ description: >-
+ Looks up `phone_number` with the mobile network or registry for its country and compares the registration against `user_details.given_names`, `user_details.last_name` and, when you send one, `id_number`. Kenya requires `id_number`.
+
+ The result is one of: an exact match on every field you supplied (clear), a match on some of them (attention), no match (block), or no registration for that number (block).
+
+ Ghana requires `operator`, because the number ranges and the lookup differ per network.
+ parameters: []
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PhoneVerificationRequest'
+ responses:
+ '202':
+ description: Accepted — job queued for async processing.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AcceptedResponse'
+ example:
+ status: accepted
+ message: Job submitted successfully
+ 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/ApiErrorResponse'
+ examples:
+ missingPhoneNumber:
+ summary: Missing or malformed phone number
+ value:
+ status: Bad Request
+ message: Required field 'phone_number' is missing or invalid.
+ wrongCountry:
+ summary: Number cannot belong to the country given
+ value:
+ status: Bad Request
+ message: Field 'phone_number' is not a valid phone number for KE.
+ missingIdNumber:
+ summary: Kenya request with no id_number
+ value:
+ status: Bad Request
+ message: Required field 'id_number' is missing or invalid.
+ missingOperator:
+ summary: Ghana request with no operator
+ value:
+ status: Bad Request
+ message: Required field 'operator' is missing or invalid.
+ unsupportedCountry:
+ summary: No phone number provider for the country
+ value:
+ status: Bad Request
+ message: Required field 'country' is missing or invalid.
+ missingCallbackUrl:
+ summary: Missing callback_url and no default set
+ value:
+ status: Bad Request
+ message: >-
+ A valid callback_url is required in the request or a default callback URL must be configured in the portal.
+ '401':
+ description: Unauthorized — invalid or missing authentication credentials.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '402':
+ description: Payment Required — insufficient wallet balance.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '403':
+ description: Forbidden — partner not authorized for this product, country or IP.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '415':
+ description: Unsupported Media Type — request must be multipart/form-data.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '429':
+ description: Too Many Requests — rate limit exceeded.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '500':
+ description: Internal Server Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
/v3/replay/{job_id}:
post:
operationId: replayCallback
@@ -4071,7 +4145,8 @@ paths:
example: john@example.com
phone_number:
type: string
- description: Phone number in E.164 format.
+ description: >-
+ Contact phone number of the individual, in E.164 format. It binds `user_details.phone_number`, so for phone number verification it is the contact number, never the number checked.
example: '+2348012345678'
callback_url:
type: string
@@ -5847,6 +5922,116 @@ components:
additionalProperties: true
description: >-
Device/network signals captured at submission time. Always `null` for an `error` outcome, and best-effort `null` when no metadata was captured.
+ PhoneVerificationRequest:
+ type: object
+ required:
+ - country
+ - consent
+ - phone_number
+ - user_details
+ anyOf:
+ - properties:
+ country:
+ not:
+ enum:
+ - KE
+ - required:
+ - id_number
+ properties:
+ country:
+ type: string
+ minLength: 2
+ maxLength: 2
+ pattern: ^[A-Z]{2}$
+ description: >-
+ ISO 3166-1 alpha-2 code of the country the number belongs to. Only countries with a phone number provider are accepted. Call GET /v3/services/config for the list available to you.
+ example: NG
+ phone_number:
+ type: string
+ pattern: ^\+[1-9]\d{6,14}$
+ description: >-
+ The number to verify, in E.164 format. It must be a number for `country` (and, in Ghana, for `operator`).
+ example: '+2348012345678'
+ operator:
+ type: string
+ enum:
+ - MTN
+ - VODAFONE
+ - AIRTELTIGO
+ description: Mobile network operator. Required for Ghana, ignored elsewhere.
+ example: MTN
+ id_number:
+ type: string
+ minLength: 1
+ maxLength: 256
+ description: >-
+ National ID number to match against the number's registration, reported separately in `matched_fields`. Required for Kenya, optional elsewhere.
+ example: '12345678901'
+ consent:
+ $ref: '#/components/schemas/Consent'
+ user_details:
+ type: object
+ required:
+ - given_names
+ - last_name
+ anyOf:
+ - required:
+ - email
+ - required:
+ - phone_number
+ description: >-
+ Consumer-stated PII fields for the person the number should be registered to. The given names and last name are compared against the registration. Either email or phone_number must be provided.
+ properties:
+ given_names:
+ type: string
+ minLength: 1
+ example: Blessing Okoro
+ last_name:
+ type: string
+ minLength: 1
+ example: Matchwell
+ email:
+ type: string
+ format: email
+ nullable: true
+ description: At least one of email or phone_number is required.
+ example: blessing@example.com
+ phone_number:
+ type: string
+ pattern: ^\+[1-9]\d{6,14}$
+ nullable: true
+ description: >-
+ The consumer's contact number in E.164 format, not the number checked. At least one of email or phone_number is required.
+ example: '+2348098765432'
+ user_id:
+ type: string
+ description: >-
+ Optional partner-provided user identifier. Must match the token user identifier when both are supplied. If no user identifier is supplied, a TypeID is generated automatically.
+ example: user_01h8x9y2z3a4b5c6d7e8f9g0h1
+ callback_url:
+ type: string
+ format: uri
+ pattern: ^https://
+ description: URL to receive the async result callback.
+ example: https://example.com/callback
+ 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
ReplayCallbackRequest:
type: object
properties:
diff --git a/specs/v3/v3-address-entry.yaml b/specs/v3/v3-address-entry.yaml
index 5c0d0a8..f5fd4c7 100644
--- a/specs/v3/v3-address-entry.yaml
+++ b/specs/v3/v3-address-entry.yaml
@@ -48,45 +48,7 @@ paths:
* `block` (`identifier_not_found`) — the provider has no record for the ID or utility number.
* `error` (`service_unavailable`) — the provider could not be reached.
- parameters:
- - name: SmileID-Source-SDK
- in: header
- required: false
- description: Source SDK identifier.
- schema:
- type: string
- example: 'rest_api'
- - name: SmileID-Source-SDK-Version
- in: header
- required: false
- description: Source SDK version.
- schema:
- type: string
- example: '1.0.0'
- - name: SmileID-Timestamp
- in: header
- required: false
- x-smile-sdk-exclude: true
- 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
- x-smile-sdk-exclude: true
- 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
+ parameters: []
requestBody:
required: true
content:
diff --git a/specs/v3/v3-phone-verification-entry.yaml b/specs/v3/v3-phone-verification-entry.yaml
new file mode 100644
index 0000000..6f3d40b
--- /dev/null
+++ b/specs/v3/v3-phone-verification-entry.yaml
@@ -0,0 +1,311 @@
+openapi: 3.0.3
+servers:
+ - url: https://testapi.smileidentity.com
+ description: Sandbox
+ - url: https://api.smileidentity.com
+ description: Production
+info:
+ contact:
+ name: Smile ID Support
+ url: https://docs.usesmileid.com
+ email: support@usesmileid.com
+ title: V3 Phone Number Verification API
+ version: '1.0.0'
+ description: >-
+ Async phone number verification endpoint. Checks who a mobile number is registered to and reports how well that registration matches the names, and the ID number, you supplied. The ID number is optional, except in Kenya where it is required. Returns HTTP 202 with a job_id and user_id; the result arrives on your callback URL.
+
+ Authentication: token-based (SmileID-Token header from POST /v3/token).
+
+ The number checked is the top-level `phone_number`, in E.164 format. `user_details` holds the consumer's own details, as in every v3 product: their names, and an email or contact phone number. The contact number is never the number checked, even when it is the same number.
+tags:
+ - name: Phone Number Verification
+paths:
+ /v3/phone:
+ post:
+ summary: Submit a phone number verification
+ operationId: v3PhoneVerification
+ tags:
+ - Phone Number Verification
+ security:
+ - SmileIDToken: []
+ description: >-
+ Looks up `phone_number` with the mobile network or registry for its country and compares the registration against `user_details.given_names`, `user_details.last_name` and, when you send one, `id_number`. Kenya requires `id_number`.
+
+ The result is one of: an exact match on every field you supplied (clear), a match on some of them (attention), no match (block), or no registration for that number (block).
+
+ Ghana requires `operator`, because the number ranges and the lookup differ per network.
+ parameters: []
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PhoneVerificationRequest'
+ responses:
+ '202':
+ description: Accepted — job queued for async processing.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AcceptedResponse'
+ example:
+ status: accepted
+ message: Job submitted successfully
+ 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/ApiErrorResponse'
+ examples:
+ missingPhoneNumber:
+ summary: Missing or malformed phone number
+ value:
+ status: Bad Request
+ message: "Required field 'phone_number' is missing or invalid."
+ wrongCountry:
+ summary: Number cannot belong to the country given
+ value:
+ status: Bad Request
+ message: "Field 'phone_number' is not a valid phone number for KE."
+ missingIdNumber:
+ summary: Kenya request with no id_number
+ value:
+ status: Bad Request
+ message: "Required field 'id_number' is missing or invalid."
+ missingOperator:
+ summary: Ghana request with no operator
+ value:
+ status: Bad Request
+ message: "Required field 'operator' is missing or invalid."
+ unsupportedCountry:
+ summary: No phone number provider for the country
+ value:
+ status: Bad Request
+ message: "Required field 'country' is missing or invalid."
+ missingCallbackUrl:
+ summary: Missing callback_url and no default set
+ value:
+ status: Bad Request
+ message: A valid callback_url is required in the request or a default callback URL must be configured in the portal.
+ '401':
+ description: Unauthorized — invalid or missing authentication credentials.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '402':
+ description: Payment Required — insufficient wallet balance.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '403':
+ description: Forbidden — partner not authorized for this product, country or IP.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '415':
+ description: Unsupported Media Type — request must be multipart/form-data.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '429':
+ description: Too Many Requests — rate limit exceeded.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ '500':
+ description: Internal Server Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+components:
+ securitySchemes:
+ SmileIDToken:
+ type: apiKey
+ in: header
+ name: SmileID-Token
+ description: JWT token obtained from `POST /v3/token`.
+ x-gitbook-token-placeholder: YOUR_GENERATED_TOKEN
+ schemas:
+ PhoneVerificationRequest:
+ type: object
+ required:
+ - country
+ - consent
+ - phone_number
+ - user_details
+ # OpenAPI 3.0 has no if/then: "country is KE" implies "id_number is present".
+ anyOf:
+ - properties:
+ country:
+ not:
+ enum: [KE]
+ - required: [id_number]
+ properties:
+ country:
+ type: string
+ minLength: 2
+ maxLength: 2
+ pattern: '^[A-Z]{2}$'
+ description: >-
+ ISO 3166-1 alpha-2 code of the country the number belongs to. Only countries with a phone number provider are accepted. Call GET /v3/services/config for the list available to you.
+ example: NG
+ phone_number:
+ type: string
+ pattern: '^\+[1-9]\d{6,14}$'
+ description: >-
+ The number to verify, in E.164 format. It must be a number for `country` (and, in Ghana, for `operator`).
+ example: '+2348012345678'
+ operator:
+ type: string
+ enum: [MTN, VODAFONE, AIRTELTIGO]
+ description: >-
+ Mobile network operator. Required for Ghana, ignored elsewhere.
+ example: MTN
+ id_number:
+ type: string
+ minLength: 1
+ maxLength: 256
+ description: >-
+ National ID number to match against the number's registration, reported separately in `matched_fields`. Required for Kenya, optional elsewhere.
+ example: '12345678901'
+ consent:
+ $ref: '#/components/schemas/Consent'
+ user_details:
+ type: object
+ required:
+ - given_names
+ - last_name
+ anyOf:
+ - required: [email]
+ - required: [phone_number]
+ description: >-
+ Consumer-stated PII fields for the person the number should be registered to. The given names and last name are compared against the registration. Either email or phone_number must be provided.
+ properties:
+ given_names:
+ type: string
+ minLength: 1
+ example: Blessing Okoro
+ last_name:
+ type: string
+ minLength: 1
+ example: Matchwell
+ email:
+ type: string
+ format: email
+ nullable: true
+ description: At least one of email or phone_number is required.
+ example: blessing@example.com
+ phone_number:
+ type: string
+ pattern: '^\+[1-9]\d{6,14}$'
+ nullable: true
+ description: >-
+ The consumer's contact number in E.164 format, not the number checked. At least one of email or phone_number is required.
+ example: '+2348098765432'
+ user_id:
+ type: string
+ description: >-
+ Optional partner-provided user identifier. Must match the token user identifier when both are supplied. If no user identifier is supplied, a TypeID is generated automatically.
+ example: user_01h8x9y2z3a4b5c6d7e8f9g0h1
+ callback_url:
+ type: string
+ format: uri
+ pattern: '^https://'
+ description: URL to receive the async result callback.
+ example: https://example.com/callback
+ 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]
+ 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
+ pattern: '^https://'
+ description: HTTPS URL of the privacy policy notice shown to the user.
+ example: https://example.com/privacy
+ AcceptedResponse:
+ type: object
+ required:
+ - status
+ - message
+ - job_id
+ - user_id
+ - created_at
+ properties:
+ status:
+ type: string
+ enum: [accepted]
+ description: Acceptance status for queued verification requests.
+ message:
+ type: string
+ description: Human-readable acceptance message.
+ example: Request accepted and queued for processing.
+ job_id:
+ type: string
+ description: TypeID format verification identifier for tracking.
+ example: job_01h8x9y2z3a4b5c6d7e8f9g0h1
+ user_id:
+ type: string
+ description: TypeID format user identifier, or partner-provided user identifier.
+ example: user_01h8x9y2z3a4b5c6d7e8f9g0h1
+ created_at:
+ type: string
+ format: date-time
+ description: ISO 8601 timestamp of when the verification was created.
+ example: '2026-03-10T12:00:00.000Z'
+ ApiErrorResponse:
+ 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: Invalid request.
diff --git a/specs/v3/v3-replay-callback.yaml b/specs/v3/v3-replay-callback.yaml
index 594d03a..87e3248 100644
--- a/specs/v3/v3-replay-callback.yaml
+++ b/specs/v3/v3-replay-callback.yaml
@@ -30,6 +30,8 @@ info:
+
+
1. `callback_url` from request body (validated against partner's allowed domains)
2. `callback_url` stored with the original verification
3. Partner's default callback URL
diff --git a/specs/v3/v3-token.yaml b/specs/v3/v3-token.yaml
index b4d8f1d..616a92d 100644
--- a/specs/v3/v3-token.yaml
+++ b/specs/v3/v3-token.yaml
@@ -114,7 +114,8 @@ paths:
example: john@example.com
phone_number:
type: string
- description: Phone number in E.164 format.
+ description: >-
+ Contact phone number of the individual, in E.164 format. It binds `user_details.phone_number`, so for phone number verification it is the contact number, never the number checked.
example: '+2348012345678'
callback_url:
type: string