diff --git a/CHANGELOG.md b/CHANGELOG.md
index 710b7ad..989cdc5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
+## [v3.818.0] - 2026-08-10
+
+### Changed
+- Updated `openapi`
+- Updated `v3-one-time-aml-entry`
+- Updated `v3-token`
+
+
## [v3.801.0] - 2026-08-04
### Changed
diff --git a/README.md b/README.md
index 1293a34..e2372ff 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@ OpenAPI 3.0 specifications for the Smile Identity v3 API.
| [Document Verification](specs/v3/v3-document-verification-entry.yaml) | `POST /v3/document_verification` | Submit Document Verification |
| [Enhanced Document Verification](specs/v3/v3-enhanced-document-verification-entry.yaml) | `POST /v3/enhanced_document_verification` | Submit Enhanced Document Verification |
| [Enhanced KYC](specs/v3/v3-enhanced-kyc-entry.yaml) | `POST /v3/enhanced_kyc` | Submit Enhanced KYC verification |
+| [One Time Aml](specs/v3/v3-one-time-aml-entry.yaml) | `POST /v3/aml` | Submit One-Time AML screening |
| [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 |
| [Services](specs/v3/v3-services.yaml) | `GET /v3/services/bank_codes` | List bank codes |
diff --git a/docs/index.html b/docs/index.html
index 2349d67..026f251 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -237,6 +237,7 @@
APIs
{ file: "v3-document-verification-entry", label: "Document Verification" },
{ 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-replay-callback", label: "Replay Callback" },
{ file: "v3-report-user-fraud", label: "Report User Fraud" },
{ file: "v3-services", label: "Services" },
diff --git a/specs/v3/openapi.yaml b/specs/v3/openapi.yaml
index e6a1fc6..63c7d42 100644
--- a/specs/v3/openapi.yaml
+++ b/specs/v3/openapi.yaml
@@ -21,6 +21,7 @@ tags:
- name: Document Verification
- name: Enhanced Document Verification
- name: Enhanced KYC
+ - name: One-Time AML
- name: Services
- name: Smart Selfie Compare
- name: Users
@@ -1181,6 +1182,420 @@ paths:
example:
status: Internal Server Error
message: An unexpected error occurred. Please try again or contact support.
+ /v3/aml:
+ post:
+ operationId: submitOneTimeAml
+ tags:
+ - One-Time AML
+ security:
+ - SmileIDToken: []
+ summary: Submit One-Time AML screening
+ description: >-
+ Screens the supplied full name (and optional aliases/birth year) against sanctions, PEP, and
+ adverse-media lists for the given countries. Results are delivered asynchronously via
+ callback URL. No human review is performed — the callback carries a terminal outcome.
+ parameters:
+ - 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
+ x-smile-sdk-exclude: true
+ 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
+ x-smile-sdk-exclude: true
+ 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. Must agree with body `user_id` and any token-bound
+ user id — disagreement is a 403. If omitted everywhere, a TypeID is generated
+ automatically.
+ schema:
+ type: string
+ requestBody:
+ required: true
+ description: >-
+ Sent as multipart/form-data. Scalar fields (full_name, birth_year, strict_match,
+ search_existing_user, user_id, source_sdk, source_sdk_version) are plain form fields.
+ Non-scalar fields must be sent as JSON-encoded strings in their form part: the array
+ fields countries and aliases (e.g. countries='["NG","KE"]') and the object fields consent,
+ user_details, metadata, and partner_params. Multipart has no native array encoding, so a
+ bare or repeated countries field is rejected — it must be a JSON array string.
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/OneTimeAmlRequest'
+ responses:
+ '202':
+ description: Accepted — screening submitted for async processing.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OneTimeAmlAcceptedResponse'
+ example:
+ status: accepted
+ message: Job submitted successfully
+ job_id: job_01h8x9y2z3a4b5c6d7e8f9g0h1
+ user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1
+ '400':
+ description: Bad Request — validation error in request body or headers.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ examples:
+ missingCountries:
+ summary: Missing or invalid countries
+ value:
+ status: Bad Request
+ message: Required field 'countries' is missing or invalid.
+ missingFullName:
+ summary: Missing or invalid full_name
+ value:
+ status: Bad Request
+ message: Required field 'full_name' is missing or invalid.
+ invalidBirthYear:
+ summary: Invalid birth_year
+ value:
+ status: Bad Request
+ message: Field 'birth_year' is invalid.
+ invalidStrictMatch:
+ summary: Invalid strict_match
+ value:
+ status: Bad Request
+ message: Field 'strict_match' is invalid.
+ tooManyAliases:
+ summary: Too many aliases
+ value:
+ status: Bad Request
+ message: Field 'aliases' must contain at most 20 entries.
+ aliasTooLong:
+ summary: Alias entry too long
+ value:
+ status: Bad Request
+ message: Field 'aliases' entries must be at most 256 characters.
+ missingUserIdForSearch:
+ summary: user_id required when search_existing_user is true
+ value:
+ status: Bad Request
+ message: >-
+ Required field 'user_id' is missing or invalid when search_existing_user is
+ true.
+ missingConsent:
+ summary: Consent not granted
+ value:
+ status: Bad Request
+ message: Required field 'consent.granted' is missing or invalid.
+ futureConsent:
+ summary: consent.granted_at in the future
+ value:
+ status: Bad Request
+ message: Required field 'consent.granted_at' cannot be set in the future.
+ missingUserDetails:
+ summary: Missing user_details.given_names
+ value:
+ status: Bad Request
+ message: Required field 'user_details.given_names' is missing or invalid.
+ missingContact:
+ summary: Missing email and phone
+ value:
+ status: Bad Request
+ message: Either user_details.email or user_details.phone_number is required.
+ missingCallbackUrl:
+ summary: Missing callback_url and no default set
+ value:
+ status: Bad Request
+ message: Required field 'callback_url' is missing or invalid.
+ '401':
+ description: Unauthorized — invalid or missing authentication credentials.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ example:
+ status: Unauthorized
+ message: Invalid authentication credentials.
+ '402':
+ description: Payment Required — insufficient wallet balance.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ example:
+ status: Payment Required
+ message: Insufficient wallet balance.
+ '403':
+ description: Forbidden — partner not authorized for this product or IP, or user_id conflict.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ examples:
+ userIdConflict:
+ summary: Body/header/token user_id disagree
+ value:
+ status: Forbidden
+ message: Token is not authorized for this user ID.
+ 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.
+ '404':
+ description: >-
+ Not Found — `search_existing_user` was true but no matching enrollee or usable prior
+ record was found.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ examples:
+ noEnrollee:
+ summary: No enrolled user found for this partner
+ value:
+ status: Not Found
+ message: No enrolled user found for this partner.
+ noUsablePriorRecord:
+ summary: No usable prior KYC record
+ value:
+ status: Not Found
+ message: No prior KYC record with a usable name and country was found for this user.
+ '413':
+ description: Content Too Large — the request payload exceeds the size limit.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ example:
+ status: Content Too Large
+ message: Request payload is too large.
+ '415':
+ description: Unsupported Media Type — request must be multipart/form-data.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ 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/ApiErrorResponse'
+ 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/ApiErrorResponse'
+ example:
+ status: Internal Server Error
+ message: An unexpected error occurred. Please try again or contact support.
+ callbacks:
+ oneTimeAmlResult:
+ '{$request.body#/callback_url}':
+ post:
+ summary: One-Time AML result callback
+ description: >-
+ Sent once the screening reaches a terminal state (clear, block, attention, or
+ error). The same body is returned by `GET /v3/status/{jobId}`-driven polling flows
+ that reconstruct the result, and by `POST /v3/replay/{job_id}`.
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OneTimeAmlCallback'
+ examples:
+ clear:
+ summary: 1031 — no matches found
+ value:
+ status: clear
+ message: 'Screening completed: no matches found.'
+ reason: null
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: null
+ strict_match: true
+ no_of_persons_found: 0
+ people: []
+ user_provided_info:
+ given_names: Nkechi
+ last_name: Okafor
+ email: nkechi.okafor@example.com
+ phone_number: null
+ consent: {}
+ antifraud: null
+ device_signals: null
+ block_match_found:
+ summary: 1030/1023 — potential match(es) identified
+ value:
+ status: block
+ message: 'Screening completed: potential matches identified.'
+ reason: aml_match_found
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: https://receipts.smileidentity.com/...
+ strict_match: true
+ no_of_persons_found: 1
+ people:
+ - name: Gbenga Afolabi
+ addresses: []
+ adverse_media: []
+ aliases: []
+ associations: []
+ dates_of_birth: []
+ enforcement_actions: []
+ nationalities: []
+ sanctions:
+ - list: OFAC SDN
+ pep:
+ pep_level: 1
+ political_positions:
+ - Member of Parliament
+ sources: []
+ user_provided_info:
+ given_names: Gbenga
+ last_name: Afolabi
+ email: null
+ phone_number: '+2348012345678'
+ consent: {}
+ antifraud: null
+ device_signals: null
+ attention_adverse_media:
+ summary: 1017 — adverse media only
+ value:
+ status: attention
+ message: 'Screening completed: adverse media identified only.'
+ reason: adverse_media_match
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: https://receipts.smileidentity.com/...
+ strict_match: true
+ no_of_persons_found: 1
+ people:
+ - name: Bukola Oni
+ addresses: []
+ adverse_media:
+ - title: Local business dispute reported in the press
+ aliases: []
+ associations: []
+ dates_of_birth: []
+ enforcement_actions: []
+ nationalities: []
+ sanctions: []
+ pep:
+ pep_level: null
+ political_positions: []
+ sources: []
+ user_provided_info:
+ given_names: Bukola
+ last_name: Oni
+ email: bukola.oni@example.com
+ phone_number: null
+ consent: {}
+ antifraud: null
+ device_signals: null
+ error_service_unavailable:
+ summary: 1015 — provider unavailable
+ value:
+ status: error
+ message: 'Error: external service unavailable.'
+ reason: service_unavailable
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: null
+ strict_match: true
+ no_of_persons_found: 0
+ people: []
+ user_provided_info:
+ given_names: Ngozi
+ last_name: Ifeoma
+ email: ngozi.ifeoma@example.com
+ phone_number: null
+ consent: {}
+ antifraud: null
+ device_signals: null
+ block_high_risk:
+ summary: High antifraud risk — overrides any provider result
+ value:
+ status: block
+ message: Verification failed.
+ reason: high_risk
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: https://receipts.smileidentity.com/...
+ strict_match: true
+ no_of_persons_found: 0
+ people: []
+ user_provided_info:
+ given_names: Rashid
+ last_name: Omar
+ email: rashid.omar@example.com
+ phone_number: null
+ consent: {}
+ antifraud:
+ fraud_risk_level: high
+ fraud_risk_score: 92
+ fraud_risk_indicator_groups:
+ - device_risk
+ device_signals: null
+ responses:
+ '200':
+ description: Callback received and acknowledged by the partner endpoint.
/v3/replay/{job_id}:
post:
operationId: replayCallback
@@ -3000,6 +3415,365 @@ components:
value:
type: string
maxLength: 1000
+ OneTimeAmlRequest:
+ type: object
+ required:
+ - countries
+ - full_name
+ - consent
+ - user_details
+ properties:
+ user_id:
+ type: string
+ minLength: 1
+ nullable: true
+ description: >-
+ Partner-provided user identifier. Optional in general; required when
+ `search_existing_user` is `true`. Reconciled with the `User-ID` header and any
+ token-bound user id after authentication — disagreement is a 403. Generated
+ automatically as a TypeID when omitted everywhere.
+ example: user-1234
+ countries:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ minLength: 2
+ maxLength: 2
+ description: >-
+ ISO 3166-1 alpha-2 country codes (uppercase) to screen against. Remains authoritative
+ for the screening even when `search_existing_user` is `true`. Sent as a JSON-encoded
+ array string in the multipart part (e.g. `["NG","KE"]`).
+ example:
+ - NG
+ - KE
+ full_name:
+ type: string
+ minLength: 1
+ description: >-
+ Full name to screen. Remains authoritative for the screening — never replaced or
+ compared with prior enrollee information, even when `search_existing_user` is `true`.
+ example: John Doe
+ birth_year:
+ type: string
+ pattern: ^\d{4}$
+ nullable: true
+ description: >-
+ Optional four-digit birth year, minimum 1000 and maximum the current UTC year. A bare
+ integer is also accepted. Full dates, decimals, non-four-digit values, and future years
+ are rejected.
+ example: '1990'
+ strict_match:
+ type: boolean
+ default: true
+ description: >-
+ Optional. When `true` (default), uses the stricter match filter set; when `false`, uses
+ a looser filter set. Accepts standard multipart boolean string representations
+ (`"true"`/`"false"`). Always echoed back on the callback.
+ aliases:
+ type: array
+ maxItems: 20
+ items:
+ type: string
+ minLength: 1
+ maxLength: 256
+ description: >-
+ Optional list of alternate names to screen, at most 20 entries, each at most 256
+ characters. Sent as a JSON-encoded array string in the multipart part (e.g. `["Johnny
+ Doe"]`).
+ example:
+ - Johnny Doe
+ search_existing_user:
+ type: boolean
+ default: false
+ description: >-
+ Optional. A gate, not a data source: when `true`, requires the resolved `user_id` to
+ belong to a partner-scoped, non-deleted enrollee with at least one non-expired prior KYC
+ record carrying a usable name and country. It never overwrites `full_name`, `countries`,
+ or `birth_year` — those stay authoritative. Accepts standard multipart boolean string
+ representations.
+ 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 screened 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: ^\+[1-9]\d{6,14}$
+ 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
+ pattern: ^https://
+ 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.
+ items:
+ type: object
+ required:
+ - name
+ - value
+ properties:
+ name:
+ type: string
+ maxLength: 100
+ value:
+ type: string
+ maxLength: 1000
+ source_sdk:
+ type: string
+ description: Source SDK identifier. Can also be provided via the `SmileID-Source-SDK` header.
+ example: android
+ source_sdk_version:
+ type: string
+ description: Source SDK version. Can also be provided via the `SmileID-Source-SDK-Version` header.
+ example: 10.4.2
+ OneTimeAmlAcceptedResponse:
+ type: object
+ required:
+ - status
+ - message
+ - job_id
+ - user_id
+ properties:
+ status:
+ type: string
+ enum:
+ - accepted
+ description: Acceptance status for the queued screening request.
+ message:
+ type: string
+ enum:
+ - Job submitted successfully
+ description: Human-readable acceptance message.
+ job_id:
+ type: string
+ description: TypeID format verification identifier for tracking.
+ example: job_01h8x9y2z3a4b5c6d7e8f9g0h1
+ user_id:
+ type: string
+ description: TypeID format user identifier, or the reconciled partner-provided user identifier.
+ example: user_01h8x9y2z3a4b5c6d7e8f9g0h1
+ AmlPersonMatch:
+ type: object
+ description: >-
+ A single sanctions/PEP/adverse-media hit. Public snake_case fields only — internal provider
+ references (e.g. sigma_ref) are always stripped before the callback is sent.
+ additionalProperties: true
+ properties:
+ name:
+ type: string
+ addresses:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ adverse_media:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ aliases:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ associations:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ dates_of_birth:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ enforcement_actions:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ nationalities:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ sanctions:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ pep:
+ type: object
+ properties:
+ pep_level:
+ type: integer
+ nullable: true
+ political_positions:
+ type: array
+ items:
+ type: string
+ sources:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ OneTimeAmlCallback:
+ type: object
+ required:
+ - status
+ - message
+ - reason
+ - created_at
+ - product
+ - partner_params
+ - kyc_receipt
+ - strict_match
+ - no_of_persons_found
+ - people
+ - user_provided_info
+ - consent
+ - antifraud
+ - device_signals
+ properties:
+ status:
+ type: string
+ enum:
+ - clear
+ - block
+ - attention
+ - error
+ description: Terminal outcome of the screening.
+ message:
+ type: string
+ description: Canonical human-readable outcome message.
+ example: 'Screening completed: no matches found.'
+ reason:
+ type: string
+ nullable: true
+ description: Canonical machine-readable reason. `null` for a clear outcome.
+ enum:
+ - null
+ - aml_match_found
+ - adverse_media_match
+ - service_unavailable
+ - high_risk
+ created_at:
+ type: string
+ format: date-time
+ description: ISO 8601 timestamp the screening job started processing.
+ completed_at:
+ type: string
+ format: date-time
+ description: >-
+ ISO 8601 timestamp the terminal outcome was reached. Omitted only if the terminal state
+ could not be read.
+ product:
+ type: string
+ enum:
+ - one_time_aml
+ partner_params:
+ type: object
+ nullable: true
+ additionalProperties:
+ type: string
+ description: >-
+ Partner-supplied key-value metadata, with internal transport keys (`_sandbox_v3`,
+ `job_id`, `job_type`, `user_id`) stripped. `null` when empty.
+ kyc_receipt:
+ type: string
+ nullable: true
+ description: >-
+ Signed receipt URL. `null` on submission; populated for `clear`, `block`, and
+ `attention` outcomes. Remains `null` for `error`.
+ strict_match:
+ type: boolean
+ description: The resolved `strict_match` value used for the screening.
+ no_of_persons_found:
+ type: integer
+ description: Count of sanctions/PEP/adverse-media matches found.
+ people:
+ type: array
+ items:
+ $ref: '#/components/schemas/AmlPersonMatch'
+ user_provided_info:
+ type: object
+ required:
+ - given_names
+ - last_name
+ - email
+ - phone_number
+ properties:
+ given_names:
+ type: string
+ nullable: true
+ last_name:
+ type: string
+ nullable: true
+ email:
+ type: string
+ nullable: true
+ phone_number:
+ type: string
+ nullable: true
+ consent:
+ type: object
+ additionalProperties: true
+ description: ISO 27560 consent record for the granted consent.
+ antifraud:
+ type: object
+ nullable: true
+ additionalProperties: true
+ description: Antifraud risk assessment. `null` when no scored fraud result exists for the job.
+ device_signals:
+ type: object
+ nullable: true
+ 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.
ReplayCallbackRequest:
type: object
properties:
diff --git a/specs/v3/v3-one-time-aml-entry.yaml b/specs/v3/v3-one-time-aml-entry.yaml
new file mode 100644
index 0000000..eec9b66
--- /dev/null
+++ b/specs/v3/v3-one-time-aml-entry.yaml
@@ -0,0 +1,844 @@
+openapi: 3.0.3
+servers:
+ - url: https://testapi.smileidentity.com
+ description: Sandbox
+ - url: https://api.smileidentity.com
+ description: Production
+info:
+ title: V3 One-Time AML API
+ version: '1.0.0'
+ description: >-
+ Async One-Time AML endpoint. Screens a full name against sanctions, PEP,
+ and adverse-media lists (job type 15). Accepts a request, validates at
+ entry, and processes the screening asynchronously. Returns HTTP 202 with a
+ job_id and user_id to track the result via callback.
+
+ Authentication: standard V3 token (SmileID-Token header from /v3/token) or
+ V3 HMAC request signature (SmileID-Timestamp + SmileID-Request-Signature
+ headers). There is no token-only restriction.
+
+ This is distinct from ongoing AML monitoring (job type 10,
+ `SmileProduct.AML`), which now lives at `POST /v3/aml/monitoring` — see
+ the V3 AML Monitoring API spec.
+
+ A submitted screening can also be tracked with the generic V3 endpoints:
+ `GET /v3/status/{jobId}` (see the V3 Verification Status API) and
+ `POST /v3/replay/{job_id}` (see the V3 Replay Callback API) both work with
+ One-Time AML jobs the same way as any other V3 product.
+paths:
+ /v3/aml:
+ post:
+ operationId: submitOneTimeAml
+ tags:
+ - One-Time AML
+ security:
+ - SmileIDToken: []
+ summary: Submit One-Time AML screening
+ description: >-
+ Screens the supplied full name (and optional aliases/birth year)
+ against sanctions, PEP, and adverse-media lists for the given
+ countries. Results are delivered asynchronously via callback URL. No
+ human review is performed — the callback carries a terminal outcome.
+ parameters:
+ - 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
+ x-smile-sdk-exclude: true
+ 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
+ x-smile-sdk-exclude: true
+ 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. Must agree with body `user_id` and any
+ token-bound user id — disagreement is a 403. If omitted everywhere, a TypeID
+ is generated automatically.
+ schema:
+ type: string
+ requestBody:
+ required: true
+ description: >-
+ Sent as multipart/form-data. Scalar fields (full_name, birth_year,
+ strict_match, search_existing_user, user_id, source_sdk,
+ source_sdk_version) are plain form fields. Non-scalar fields must be
+ sent as JSON-encoded strings in their form part: the array fields
+ countries and aliases (e.g. countries='["NG","KE"]') and the object
+ fields consent, user_details, metadata, and partner_params. Multipart
+ has no native array encoding, so a bare or repeated countries field is
+ rejected — it must be a JSON array string.
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/OneTimeAmlRequest'
+ responses:
+ '202':
+ description: Accepted — screening submitted for async processing.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OneTimeAmlAcceptedResponse'
+ example:
+ status: accepted
+ message: Job submitted successfully
+ job_id: job_01h8x9y2z3a4b5c6d7e8f9g0h1
+ user_id: user_01h8x9y2z3a4b5c6d7e8f9g0h1
+ '400':
+ description: Bad Request — validation error in request body or headers.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ examples:
+ missingCountries:
+ summary: Missing or invalid countries
+ value:
+ status: Bad Request
+ message: "Required field 'countries' is missing or invalid."
+ missingFullName:
+ summary: Missing or invalid full_name
+ value:
+ status: Bad Request
+ message: "Required field 'full_name' is missing or invalid."
+ invalidBirthYear:
+ summary: Invalid birth_year
+ value:
+ status: Bad Request
+ message: "Field 'birth_year' is invalid."
+ invalidStrictMatch:
+ summary: Invalid strict_match
+ value:
+ status: Bad Request
+ message: "Field 'strict_match' is invalid."
+ tooManyAliases:
+ summary: Too many aliases
+ value:
+ status: Bad Request
+ message: "Field 'aliases' must contain at most 20 entries."
+ aliasTooLong:
+ summary: Alias entry too long
+ value:
+ status: Bad Request
+ message: "Field 'aliases' entries must be at most 256 characters."
+ missingUserIdForSearch:
+ summary: user_id required when search_existing_user is true
+ value:
+ status: Bad Request
+ message: "Required field 'user_id' is missing or invalid when search_existing_user is true."
+ missingConsent:
+ summary: Consent not granted
+ value:
+ status: Bad Request
+ message: "Required field 'consent.granted' is missing or invalid."
+ futureConsent:
+ summary: consent.granted_at in the future
+ value:
+ status: Bad Request
+ message: "Required field 'consent.granted_at' cannot be set in the future."
+ missingUserDetails:
+ summary: Missing user_details.given_names
+ value:
+ status: Bad Request
+ message: "Required field 'user_details.given_names' is missing or invalid."
+ missingContact:
+ summary: Missing email and phone
+ value:
+ status: Bad Request
+ message: Either user_details.email or user_details.phone_number is required.
+ missingCallbackUrl:
+ summary: Missing callback_url and no default set
+ value:
+ status: Bad Request
+ message: "Required field 'callback_url' is missing or invalid."
+ '401':
+ description: Unauthorized — invalid or missing authentication credentials.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ example:
+ status: Unauthorized
+ message: Invalid authentication credentials.
+ '402':
+ description: Payment Required — insufficient wallet balance.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ example:
+ status: Payment Required
+ message: Insufficient wallet balance.
+ '403':
+ description: Forbidden — partner not authorized for this product or IP, or user_id conflict.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ examples:
+ userIdConflict:
+ summary: Body/header/token user_id disagree
+ value:
+ status: Forbidden
+ message: Token is not authorized for this user ID.
+ 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.
+ '404':
+ description: >-
+ Not Found — `search_existing_user` was true but no matching enrollee or usable
+ prior record was found.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ examples:
+ noEnrollee:
+ summary: No enrolled user found for this partner
+ value:
+ status: Not Found
+ message: No enrolled user found for this partner.
+ noUsablePriorRecord:
+ summary: No usable prior KYC record
+ value:
+ status: Not Found
+ message: No prior KYC record with a usable name and country was found for this user.
+ '413':
+ description: Content Too Large — the request payload exceeds the size limit.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ example:
+ status: Content Too Large
+ message: Request payload is too large.
+ '415':
+ description: Unsupported Media Type — request must be multipart/form-data.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+ 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/ApiErrorResponse'
+ 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/ApiErrorResponse'
+ example:
+ status: Internal Server Error
+ message: An unexpected error occurred. Please try again or contact support.
+ callbacks:
+ oneTimeAmlResult:
+ '{$request.body#/callback_url}':
+ post:
+ summary: One-Time AML result callback
+ description: >-
+ Sent once the screening reaches a terminal state (clear, block, attention, or
+ error). The same body is returned by `GET /v3/status/{jobId}`-driven polling
+ flows that reconstruct the result, and by `POST /v3/replay/{job_id}`.
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OneTimeAmlCallback'
+ examples:
+ clear:
+ summary: '1031 — no matches found'
+ value:
+ status: clear
+ message: 'Screening completed: no matches found.'
+ reason: null
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: null
+ strict_match: true
+ no_of_persons_found: 0
+ people: []
+ user_provided_info:
+ given_names: Nkechi
+ last_name: Okafor
+ email: nkechi.okafor@example.com
+ phone_number: null
+ consent: {}
+ antifraud: null
+ device_signals: null
+ block_match_found:
+ summary: '1030/1023 — potential match(es) identified'
+ value:
+ status: block
+ message: 'Screening completed: potential matches identified.'
+ reason: aml_match_found
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: 'https://receipts.smileidentity.com/...'
+ strict_match: true
+ no_of_persons_found: 1
+ people:
+ - name: Gbenga Afolabi
+ addresses: []
+ adverse_media: []
+ aliases: []
+ associations: []
+ dates_of_birth: []
+ enforcement_actions: []
+ nationalities: []
+ sanctions:
+ - list: OFAC SDN
+ pep:
+ pep_level: 1
+ political_positions:
+ - Member of Parliament
+ sources: []
+ user_provided_info:
+ given_names: Gbenga
+ last_name: Afolabi
+ email: null
+ phone_number: '+2348012345678'
+ consent: {}
+ antifraud: null
+ device_signals: null
+ attention_adverse_media:
+ summary: '1017 — adverse media only'
+ value:
+ status: attention
+ message: 'Screening completed: adverse media identified only.'
+ reason: adverse_media_match
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: 'https://receipts.smileidentity.com/...'
+ strict_match: true
+ no_of_persons_found: 1
+ people:
+ - name: Bukola Oni
+ addresses: []
+ adverse_media:
+ - title: Local business dispute reported in the press
+ aliases: []
+ associations: []
+ dates_of_birth: []
+ enforcement_actions: []
+ nationalities: []
+ sanctions: []
+ pep:
+ pep_level: null
+ political_positions: []
+ sources: []
+ user_provided_info:
+ given_names: Bukola
+ last_name: Oni
+ email: bukola.oni@example.com
+ phone_number: null
+ consent: {}
+ antifraud: null
+ device_signals: null
+ error_service_unavailable:
+ summary: '1015 — provider unavailable'
+ value:
+ status: error
+ message: 'Error: external service unavailable.'
+ reason: service_unavailable
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: null
+ strict_match: true
+ no_of_persons_found: 0
+ people: []
+ user_provided_info:
+ given_names: Ngozi
+ last_name: Ifeoma
+ email: ngozi.ifeoma@example.com
+ phone_number: null
+ consent: {}
+ antifraud: null
+ device_signals: null
+ block_high_risk:
+ summary: 'High antifraud risk — overrides any provider result'
+ value:
+ status: block
+ message: 'Verification failed.'
+ reason: high_risk
+ created_at: '2026-07-20T12:00:00.000Z'
+ completed_at: '2026-07-20T12:00:01.000Z'
+ product: one_time_aml
+ partner_params: null
+ kyc_receipt: 'https://receipts.smileidentity.com/...'
+ strict_match: true
+ no_of_persons_found: 0
+ people: []
+ user_provided_info:
+ given_names: Rashid
+ last_name: Omar
+ email: rashid.omar@example.com
+ phone_number: null
+ consent: {}
+ antifraud:
+ fraud_risk_level: high
+ fraud_risk_score: 92
+ fraud_risk_indicator_groups:
+ - device_risk
+ device_signals: null
+ responses:
+ '200':
+ description: Callback received and acknowledged by the partner endpoint.
+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:
+ OneTimeAmlRequest:
+ type: object
+ required:
+ - countries
+ - full_name
+ - consent
+ - user_details
+ properties:
+ user_id:
+ type: string
+ minLength: 1
+ nullable: true
+ description: >-
+ Partner-provided user identifier. Optional in general; required when
+ `search_existing_user` is `true`. Reconciled with the `User-ID` header and any
+ token-bound user id after authentication — disagreement is a 403. Generated
+ automatically as a TypeID when omitted everywhere.
+ example: 'user-1234'
+ countries:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ minLength: 2
+ maxLength: 2
+ description: >-
+ ISO 3166-1 alpha-2 country codes (uppercase) to screen against. Remains
+ authoritative for the screening even when `search_existing_user` is `true`.
+ Sent as a JSON-encoded array string in the multipart part (e.g. `["NG","KE"]`).
+ example: ['NG', 'KE']
+ full_name:
+ type: string
+ minLength: 1
+ description: >-
+ Full name to screen. Remains authoritative for the screening — never replaced
+ or compared with prior enrollee information, even when `search_existing_user`
+ is `true`.
+ example: 'John Doe'
+ birth_year:
+ type: string
+ pattern: '^\d{4}$'
+ nullable: true
+ description: >-
+ Optional four-digit birth year, minimum 1000 and maximum the current UTC year.
+ A bare integer is also accepted. Full dates, decimals, non-four-digit values,
+ and future years are rejected.
+ example: '1990'
+ strict_match:
+ type: boolean
+ default: true
+ description: >-
+ Optional. When `true` (default), uses the stricter match filter set; when
+ `false`, uses a looser filter set. Accepts standard multipart boolean string
+ representations (`"true"`/`"false"`). Always echoed back on the callback.
+ aliases:
+ type: array
+ maxItems: 20
+ items:
+ type: string
+ minLength: 1
+ maxLength: 256
+ description: >-
+ Optional list of alternate names to screen, at most 20 entries, each at most
+ 256 characters. Sent as a JSON-encoded array string in the multipart part
+ (e.g. `["Johnny Doe"]`).
+ example: ['Johnny Doe']
+ search_existing_user:
+ type: boolean
+ default: false
+ description: >-
+ Optional. A gate, not a data source: when `true`, requires the resolved
+ `user_id` to belong to a partner-scoped, non-deleted enrollee with at least one
+ non-expired prior KYC record carrying a usable name and country. It never
+ overwrites `full_name`, `countries`, or `birth_year` — those stay authoritative.
+ Accepts standard multipart boolean string representations.
+ 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 screened 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: '^\+[1-9]\d{6,14}$'
+ 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
+ pattern: '^https://'
+ 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.
+ items:
+ type: object
+ required:
+ - name
+ - value
+ properties:
+ name:
+ type: string
+ maxLength: 100
+ value:
+ type: string
+ maxLength: 1000
+ source_sdk:
+ type: string
+ description: Source SDK identifier. Can also be provided via the `SmileID-Source-SDK` header.
+ example: android
+ source_sdk_version:
+ type: string
+ description: Source SDK version. Can also be provided via the `SmileID-Source-SDK-Version` header.
+ example: '10.4.2'
+ 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
+
+ OneTimeAmlAcceptedResponse:
+ type: object
+ required:
+ - status
+ - message
+ - job_id
+ - user_id
+ properties:
+ status:
+ type: string
+ enum: [accepted]
+ description: Acceptance status for the queued screening request.
+ message:
+ type: string
+ enum: ['Job submitted successfully']
+ description: Human-readable acceptance message.
+ job_id:
+ type: string
+ description: TypeID format verification identifier for tracking.
+ example: job_01h8x9y2z3a4b5c6d7e8f9g0h1
+ user_id:
+ type: string
+ description: TypeID format user identifier, or the reconciled partner-provided user identifier.
+ example: user_01h8x9y2z3a4b5c6d7e8f9g0h1
+
+ AmlPersonMatch:
+ type: object
+ description: >-
+ A single sanctions/PEP/adverse-media hit. Public snake_case fields only — internal
+ provider references (e.g. sigma_ref) are always stripped before the callback is sent.
+ additionalProperties: true
+ properties:
+ name:
+ type: string
+ addresses:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ adverse_media:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ aliases:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ associations:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ dates_of_birth:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ enforcement_actions:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ nationalities:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ sanctions:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ pep:
+ type: object
+ properties:
+ pep_level:
+ type: integer
+ nullable: true
+ political_positions:
+ type: array
+ items:
+ type: string
+ sources:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+
+ OneTimeAmlCallback:
+ type: object
+ required:
+ - status
+ - message
+ - reason
+ - created_at
+ - product
+ - partner_params
+ - kyc_receipt
+ - strict_match
+ - no_of_persons_found
+ - people
+ - user_provided_info
+ - consent
+ - antifraud
+ - device_signals
+ properties:
+ status:
+ type: string
+ enum: [clear, block, attention, error]
+ description: Terminal outcome of the screening.
+ message:
+ type: string
+ description: Canonical human-readable outcome message.
+ example: 'Screening completed: no matches found.'
+ reason:
+ type: string
+ nullable: true
+ description: >-
+ Canonical machine-readable reason. `null` for a clear outcome.
+ enum: [null, aml_match_found, adverse_media_match, service_unavailable, high_risk]
+ created_at:
+ type: string
+ format: date-time
+ description: ISO 8601 timestamp the screening job started processing.
+ completed_at:
+ type: string
+ format: date-time
+ description: >-
+ ISO 8601 timestamp the terminal outcome was reached. Omitted only if the terminal
+ state could not be read.
+ product:
+ type: string
+ enum: [one_time_aml]
+ partner_params:
+ type: object
+ nullable: true
+ additionalProperties:
+ type: string
+ description: >-
+ Partner-supplied key-value metadata, with internal transport keys
+ (`_sandbox_v3`, `job_id`, `job_type`, `user_id`) stripped. `null` when empty.
+ kyc_receipt:
+ type: string
+ nullable: true
+ description: >-
+ Signed receipt URL. `null` on submission; populated for `clear`, `block`, and
+ `attention` outcomes. Remains `null` for `error`.
+ strict_match:
+ type: boolean
+ description: The resolved `strict_match` value used for the screening.
+ no_of_persons_found:
+ type: integer
+ description: Count of sanctions/PEP/adverse-media matches found.
+ people:
+ type: array
+ items:
+ $ref: '#/components/schemas/AmlPersonMatch'
+ user_provided_info:
+ type: object
+ required:
+ - given_names
+ - last_name
+ - email
+ - phone_number
+ properties:
+ given_names:
+ type: string
+ nullable: true
+ last_name:
+ type: string
+ nullable: true
+ email:
+ type: string
+ nullable: true
+ phone_number:
+ type: string
+ nullable: true
+ consent:
+ type: object
+ additionalProperties: true
+ description: ISO 27560 consent record for the granted consent.
+ antifraud:
+ type: object
+ nullable: true
+ additionalProperties: true
+ description: Antifraud risk assessment. `null` when no scored fraud result exists for the job.
+ device_signals:
+ type: object
+ nullable: true
+ 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.
+
+ 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-token.yaml b/specs/v3/v3-token.yaml
index 160fab8..62fb141 100644
--- a/specs/v3/v3-token.yaml
+++ b/specs/v3/v3-token.yaml
@@ -14,6 +14,7 @@ info:
description: >-
API for generating v3 authentication tokens.
The issued JWT payload includes `policy` as a number (bitmask) representing partner security policies.
+ It also includes `api_url`, the base URL for subsequent v3 API requests.
tags:
- name: Authentication
paths: