From 8c942aecc0679cf62948b6efafbc2cbc79a1e6cb Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 6 Jun 2026 01:42:47 -0700 Subject: [PATCH 1/6] feat(customers): add contact (email/phone) verification surface Adds a ContactVerification object on the Customer (present only when the customer's payment provider requires email+phone verification, e.g. EU/Striga) and four endpoints to drive it: - POST /customers/{customerId}/verify-email (send/resend) - POST /customers/{customerId}/verify-email/confirm (submit code) - POST /customers/{customerId}/verify-phone (send/resend) - POST /customers/{customerId}/verify-phone/confirm (submit code) Non-EU customers are unaffected: contactVerification is omitted from their responses and the endpoints return 409 for providers with no such requirement. Starting point for AT-4657 (Striga EU). See design: docs/plans/2026-06-06-striga-contact-verification-design.md (webdev). --- mintlify/openapi.yaml | 254 ++++++++++++++++++ openapi.yaml | 254 ++++++++++++++++++ .../customers/ContactVerification.yaml | 21 ++ .../ContactVerificationConfirmRequest.yaml | 11 + .../customers/ContactVerificationStatus.yaml | 9 + .../schemas/customers/Customer.yaml | 7 + openapi/openapi.yaml | 8 + .../customers_{customerId}_verify-email.yaml | 50 ++++ ...ers_{customerId}_verify-email_confirm.yaml | 59 ++++ .../customers_{customerId}_verify-phone.yaml | 50 ++++ ...ers_{customerId}_verify-phone_confirm.yaml | 59 ++++ 11 files changed, 782 insertions(+) create mode 100644 openapi/components/schemas/customers/ContactVerification.yaml create mode 100644 openapi/components/schemas/customers/ContactVerificationConfirmRequest.yaml create mode 100644 openapi/components/schemas/customers/ContactVerificationStatus.yaml create mode 100644 openapi/paths/customers/customers_{customerId}_verify-email.yaml create mode 100644 openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml create mode 100644 openapi/paths/customers/customers_{customerId}_verify-phone.yaml create mode 100644 openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index a73b3fd7..67eeb715 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -849,6 +849,222 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /customers/{customerId}/verify-email: + parameters: + - name: customerId + in: path + description: The Grid customer ID to send an email verification code to. + required: true + schema: + type: string + post: + summary: Send an email verification code to a customer + description: | + Send (or resend) a one-time code to the customer's email address to begin + email verification. + + This endpoint is only meaningful for customers whose payment provider + requires contact verification (e.g. EU customers); the customer's + `contactVerification.email` status reflects progress. For customers whose + provider has no such requirement, this returns `409`. + + Call `POST /customers/{customerId}/verify-email/confirm` with the received + code to complete verification. Re-POST this endpoint to resend the code. + + In sandbox, no email is sent and the code is always `123456`. + operationId: sendCustomerEmailVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + responses: + '204': + description: Verification code sent. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification, or the email is already verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + /customers/{customerId}/verify-email/confirm: + parameters: + - name: customerId + in: path + description: The Grid customer ID whose email is being verified. + required: true + schema: + type: string + post: + summary: Confirm a customer's email verification code + description: | + Submit the one-time code the customer received by email to mark their email + as `VERIFIED`. On success, `contactVerification.email` becomes `VERIFIED`. + + Both email and phone must be `VERIFIED` before the customer can begin KYC. + + In sandbox, the code is always `123456`. + operationId: confirmCustomerEmailVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ContactVerificationConfirmRequest' + responses: + '200': + description: Email verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Customer' + '400': + description: Invalid or expired code + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + /customers/{customerId}/verify-phone: + parameters: + - name: customerId + in: path + description: The Grid customer ID to send a phone verification code to. + required: true + schema: + type: string + post: + summary: Send a phone verification code to a customer + description: | + Send (or resend) a one-time code via SMS to the customer's phone number to + begin phone verification. + + This endpoint is only meaningful for customers whose payment provider + requires contact verification (e.g. EU customers); the customer's + `contactVerification.phone` status reflects progress. For customers whose + provider has no such requirement, this returns `409`. + + Call `POST /customers/{customerId}/verify-phone/confirm` with the received + code to complete verification. Re-POST this endpoint to resend the code. + + In sandbox, no SMS is sent and the code is always `123456`. + operationId: sendCustomerPhoneVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + responses: + '204': + description: Verification code sent. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification, or the phone is already verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + /customers/{customerId}/verify-phone/confirm: + parameters: + - name: customerId + in: path + description: The Grid customer ID whose phone is being verified. + required: true + schema: + type: string + post: + summary: Confirm a customer's phone verification code + description: | + Submit the one-time code the customer received via SMS to mark their phone + as `VERIFIED`. On success, `contactVerification.phone` becomes `VERIFIED`. + + Both email and phone must be `VERIFIED` before the customer can begin KYC. + + In sandbox, the code is always `123456`. + operationId: confirmCustomerPhoneVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ContactVerificationConfirmRequest' + responses: + '200': + description: Phone verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Customer' + '400': + description: Invalid or expired code + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' /customers/internal-accounts: get: summary: List Customer internal accounts @@ -8579,6 +8795,29 @@ components: - BUSINESS description: Whether the customer is an individual or a business entity example: INDIVIDUAL + ContactVerificationStatus: + type: string + description: Status of an individual contact-verification channel (email or phone). `PENDING` means verification is required but not yet completed; `VERIFIED` means the channel has been confirmed. + enum: + - PENDING + - VERIFIED + example: VERIFIED + ContactVerification: + type: object + description: |- + Email and phone verification state for the customer. This object is **only present when the customer's payment provider requires email and phone verification** (e.g. EU customers). For customers whose provider has no such requirement, this object is omitted entirely — no action is needed. + + When present, both channels must reach `VERIFIED` before the customer can begin KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). + properties: + email: + $ref: '#/components/schemas/ContactVerificationStatus' + description: Verification status of the customer's email address. + phone: + $ref: '#/components/schemas/ContactVerificationStatus' + description: Verification status of the customer's phone number. + required: + - email + - phone Customer: type: object required: @@ -8635,6 +8874,11 @@ components: description: Whether the customer is marked as deleted example: false readOnly: true + contactVerification: + allOf: + - $ref: '#/components/schemas/ContactVerification' + readOnly: true + description: Email and phone verification state. **Only present when the customer's payment provider requires it** (e.g. EU customers); omitted otherwise. KycStatus: type: string enum: @@ -9503,6 +9747,16 @@ components: type: string description: Provider-specific token that can be used in place of the hosted URL — for example, to embed the provider's SDK directly in your application. Only returned for providers that support direct SDK integration. Whether to use the hosted URL or the embedded SDK is up to you; both flows result in the same `kycStatus` update on the customer. example: _act-sbx-jwt-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... + ContactVerificationConfirmRequest: + type: object + description: Request body for confirming an email or phone verification challenge. + required: + - code + properties: + code: + type: string + description: The one-time verification code the customer received via email or SMS. In sandbox, the code is always `123456`. + example: '123456' InternalAccountType: title: Internal Account Type type: string diff --git a/openapi.yaml b/openapi.yaml index a73b3fd7..67eeb715 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -849,6 +849,222 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /customers/{customerId}/verify-email: + parameters: + - name: customerId + in: path + description: The Grid customer ID to send an email verification code to. + required: true + schema: + type: string + post: + summary: Send an email verification code to a customer + description: | + Send (or resend) a one-time code to the customer's email address to begin + email verification. + + This endpoint is only meaningful for customers whose payment provider + requires contact verification (e.g. EU customers); the customer's + `contactVerification.email` status reflects progress. For customers whose + provider has no such requirement, this returns `409`. + + Call `POST /customers/{customerId}/verify-email/confirm` with the received + code to complete verification. Re-POST this endpoint to resend the code. + + In sandbox, no email is sent and the code is always `123456`. + operationId: sendCustomerEmailVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + responses: + '204': + description: Verification code sent. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification, or the email is already verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + /customers/{customerId}/verify-email/confirm: + parameters: + - name: customerId + in: path + description: The Grid customer ID whose email is being verified. + required: true + schema: + type: string + post: + summary: Confirm a customer's email verification code + description: | + Submit the one-time code the customer received by email to mark their email + as `VERIFIED`. On success, `contactVerification.email` becomes `VERIFIED`. + + Both email and phone must be `VERIFIED` before the customer can begin KYC. + + In sandbox, the code is always `123456`. + operationId: confirmCustomerEmailVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ContactVerificationConfirmRequest' + responses: + '200': + description: Email verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Customer' + '400': + description: Invalid or expired code + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + /customers/{customerId}/verify-phone: + parameters: + - name: customerId + in: path + description: The Grid customer ID to send a phone verification code to. + required: true + schema: + type: string + post: + summary: Send a phone verification code to a customer + description: | + Send (or resend) a one-time code via SMS to the customer's phone number to + begin phone verification. + + This endpoint is only meaningful for customers whose payment provider + requires contact verification (e.g. EU customers); the customer's + `contactVerification.phone` status reflects progress. For customers whose + provider has no such requirement, this returns `409`. + + Call `POST /customers/{customerId}/verify-phone/confirm` with the received + code to complete verification. Re-POST this endpoint to resend the code. + + In sandbox, no SMS is sent and the code is always `123456`. + operationId: sendCustomerPhoneVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + responses: + '204': + description: Verification code sent. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification, or the phone is already verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + /customers/{customerId}/verify-phone/confirm: + parameters: + - name: customerId + in: path + description: The Grid customer ID whose phone is being verified. + required: true + schema: + type: string + post: + summary: Confirm a customer's phone verification code + description: | + Submit the one-time code the customer received via SMS to mark their phone + as `VERIFIED`. On success, `contactVerification.phone` becomes `VERIFIED`. + + Both email and phone must be `VERIFIED` before the customer can begin KYC. + + In sandbox, the code is always `123456`. + operationId: confirmCustomerPhoneVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ContactVerificationConfirmRequest' + responses: + '200': + description: Phone verified. + content: + application/json: + schema: + $ref: '#/components/schemas/Customer' + '400': + description: Invalid or expired code + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider does not require contact verification. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' /customers/internal-accounts: get: summary: List Customer internal accounts @@ -8579,6 +8795,29 @@ components: - BUSINESS description: Whether the customer is an individual or a business entity example: INDIVIDUAL + ContactVerificationStatus: + type: string + description: Status of an individual contact-verification channel (email or phone). `PENDING` means verification is required but not yet completed; `VERIFIED` means the channel has been confirmed. + enum: + - PENDING + - VERIFIED + example: VERIFIED + ContactVerification: + type: object + description: |- + Email and phone verification state for the customer. This object is **only present when the customer's payment provider requires email and phone verification** (e.g. EU customers). For customers whose provider has no such requirement, this object is omitted entirely — no action is needed. + + When present, both channels must reach `VERIFIED` before the customer can begin KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). + properties: + email: + $ref: '#/components/schemas/ContactVerificationStatus' + description: Verification status of the customer's email address. + phone: + $ref: '#/components/schemas/ContactVerificationStatus' + description: Verification status of the customer's phone number. + required: + - email + - phone Customer: type: object required: @@ -8635,6 +8874,11 @@ components: description: Whether the customer is marked as deleted example: false readOnly: true + contactVerification: + allOf: + - $ref: '#/components/schemas/ContactVerification' + readOnly: true + description: Email and phone verification state. **Only present when the customer's payment provider requires it** (e.g. EU customers); omitted otherwise. KycStatus: type: string enum: @@ -9503,6 +9747,16 @@ components: type: string description: Provider-specific token that can be used in place of the hosted URL — for example, to embed the provider's SDK directly in your application. Only returned for providers that support direct SDK integration. Whether to use the hosted URL or the embedded SDK is up to you; both flows result in the same `kycStatus` update on the customer. example: _act-sbx-jwt-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... + ContactVerificationConfirmRequest: + type: object + description: Request body for confirming an email or phone verification challenge. + required: + - code + properties: + code: + type: string + description: The one-time verification code the customer received via email or SMS. In sandbox, the code is always `123456`. + example: '123456' InternalAccountType: title: Internal Account Type type: string diff --git a/openapi/components/schemas/customers/ContactVerification.yaml b/openapi/components/schemas/customers/ContactVerification.yaml new file mode 100644 index 00000000..1be4035c --- /dev/null +++ b/openapi/components/schemas/customers/ContactVerification.yaml @@ -0,0 +1,21 @@ +type: object +description: >- + Email and phone verification state for the customer. This object is **only + present when the customer's payment provider requires email and phone + verification** (e.g. EU customers). For customers whose provider has no such + requirement, this object is omitted entirely — no action is needed. + + + When present, both channels must reach `VERIFIED` before the customer can begin + KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and + `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). +properties: + email: + $ref: ./ContactVerificationStatus.yaml + description: Verification status of the customer's email address. + phone: + $ref: ./ContactVerificationStatus.yaml + description: Verification status of the customer's phone number. +required: + - email + - phone diff --git a/openapi/components/schemas/customers/ContactVerificationConfirmRequest.yaml b/openapi/components/schemas/customers/ContactVerificationConfirmRequest.yaml new file mode 100644 index 00000000..e2bebe5b --- /dev/null +++ b/openapi/components/schemas/customers/ContactVerificationConfirmRequest.yaml @@ -0,0 +1,11 @@ +type: object +description: Request body for confirming an email or phone verification challenge. +required: + - code +properties: + code: + type: string + description: >- + The one-time verification code the customer received via email or SMS. + In sandbox, the code is always `123456`. + example: '123456' diff --git a/openapi/components/schemas/customers/ContactVerificationStatus.yaml b/openapi/components/schemas/customers/ContactVerificationStatus.yaml new file mode 100644 index 00000000..56475310 --- /dev/null +++ b/openapi/components/schemas/customers/ContactVerificationStatus.yaml @@ -0,0 +1,9 @@ +type: string +description: >- + Status of an individual contact-verification channel (email or phone). + `PENDING` means verification is required but not yet completed; `VERIFIED` + means the channel has been confirmed. +enum: + - PENDING + - VERIFIED +example: VERIFIED diff --git a/openapi/components/schemas/customers/Customer.yaml b/openapi/components/schemas/customers/Customer.yaml index 9bf15bdf..32fc6b52 100644 --- a/openapi/components/schemas/customers/Customer.yaml +++ b/openapi/components/schemas/customers/Customer.yaml @@ -59,3 +59,10 @@ properties: description: Whether the customer is marked as deleted example: false readOnly: true + contactVerification: + allOf: + - $ref: ./ContactVerification.yaml + readOnly: true + description: >- + Email and phone verification state. **Only present when the customer's + payment provider requires it** (e.g. EU customers); omitted otherwise. diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 7c509543..fb5611c3 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -131,6 +131,14 @@ paths: $ref: paths/customers/customers_{customerId}.yaml /customers/{customerId}/kyc-link: $ref: paths/customers/customers_{customerId}_kyc-link.yaml + /customers/{customerId}/verify-email: + $ref: paths/customers/customers_{customerId}_verify-email.yaml + /customers/{customerId}/verify-email/confirm: + $ref: paths/customers/customers_{customerId}_verify-email_confirm.yaml + /customers/{customerId}/verify-phone: + $ref: paths/customers/customers_{customerId}_verify-phone.yaml + /customers/{customerId}/verify-phone/confirm: + $ref: paths/customers/customers_{customerId}_verify-phone_confirm.yaml /customers/internal-accounts: $ref: paths/customers/customers_internal_accounts.yaml /platform/internal-accounts: diff --git a/openapi/paths/customers/customers_{customerId}_verify-email.yaml b/openapi/paths/customers/customers_{customerId}_verify-email.yaml new file mode 100644 index 00000000..fe8ab51b --- /dev/null +++ b/openapi/paths/customers/customers_{customerId}_verify-email.yaml @@ -0,0 +1,50 @@ +parameters: + - name: customerId + in: path + description: The Grid customer ID to send an email verification code to. + required: true + schema: + type: string +post: + summary: Send an email verification code to a customer + description: | + Send (or resend) a one-time code to the customer's email address to begin + email verification. + + This endpoint is only meaningful for customers whose payment provider + requires contact verification (e.g. EU customers); the customer's + `contactVerification.email` status reflects progress. For customers whose + provider has no such requirement, this returns `409`. + + Call `POST /customers/{customerId}/verify-email/confirm` with the received + code to complete verification. Re-POST this endpoint to resend the code. + + In sandbox, no email is sent and the code is always `123456`. + operationId: sendCustomerEmailVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + responses: + '204': + description: Verification code sent. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Customer not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: >- + The customer's payment provider does not require contact verification, + or the email is already verified. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml diff --git a/openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml b/openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml new file mode 100644 index 00000000..eaaab911 --- /dev/null +++ b/openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml @@ -0,0 +1,59 @@ +parameters: + - name: customerId + in: path + description: The Grid customer ID whose email is being verified. + required: true + schema: + type: string +post: + summary: Confirm a customer's email verification code + description: | + Submit the one-time code the customer received by email to mark their email + as `VERIFIED`. On success, `contactVerification.email` becomes `VERIFIED`. + + Both email and phone must be `VERIFIED` before the customer can begin KYC. + + In sandbox, the code is always `123456`. + operationId: confirmCustomerEmailVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/customers/ContactVerificationConfirmRequest.yaml + responses: + '200': + description: Email verified. + content: + application/json: + schema: + $ref: ../../components/schemas/customers/Customer.yaml + '400': + description: Invalid or expired code + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Customer not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: >- + The customer's payment provider does not require contact verification. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml diff --git a/openapi/paths/customers/customers_{customerId}_verify-phone.yaml b/openapi/paths/customers/customers_{customerId}_verify-phone.yaml new file mode 100644 index 00000000..4bc6839a --- /dev/null +++ b/openapi/paths/customers/customers_{customerId}_verify-phone.yaml @@ -0,0 +1,50 @@ +parameters: + - name: customerId + in: path + description: The Grid customer ID to send a phone verification code to. + required: true + schema: + type: string +post: + summary: Send a phone verification code to a customer + description: | + Send (or resend) a one-time code via SMS to the customer's phone number to + begin phone verification. + + This endpoint is only meaningful for customers whose payment provider + requires contact verification (e.g. EU customers); the customer's + `contactVerification.phone` status reflects progress. For customers whose + provider has no such requirement, this returns `409`. + + Call `POST /customers/{customerId}/verify-phone/confirm` with the received + code to complete verification. Re-POST this endpoint to resend the code. + + In sandbox, no SMS is sent and the code is always `123456`. + operationId: sendCustomerPhoneVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + responses: + '204': + description: Verification code sent. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Customer not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: >- + The customer's payment provider does not require contact verification, + or the phone is already verified. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml diff --git a/openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml b/openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml new file mode 100644 index 00000000..5cc3d7a7 --- /dev/null +++ b/openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml @@ -0,0 +1,59 @@ +parameters: + - name: customerId + in: path + description: The Grid customer ID whose phone is being verified. + required: true + schema: + type: string +post: + summary: Confirm a customer's phone verification code + description: | + Submit the one-time code the customer received via SMS to mark their phone + as `VERIFIED`. On success, `contactVerification.phone` becomes `VERIFIED`. + + Both email and phone must be `VERIFIED` before the customer can begin KYC. + + In sandbox, the code is always `123456`. + operationId: confirmCustomerPhoneVerification + tags: + - Contact Verification + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/customers/ContactVerificationConfirmRequest.yaml + responses: + '200': + description: Phone verified. + content: + application/json: + schema: + $ref: ../../components/schemas/customers/Customer.yaml + '400': + description: Invalid or expired code + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Customer not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: >- + The customer's payment provider does not require contact verification. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml From 7f4b5e6dd7541011559eb369e1f9dee035ddc6d9 Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 6 Jun 2026 17:19:51 -0700 Subject: [PATCH 2/6] docs: document contact (email/phone) verification step in hosted KYC flow For regions that require it (e.g. EU), the customer must verify email and phone before a KYC link can be generated. Adds a region-scoped step to the unregulated hosted-KYC flow describing the verify-email/verify-phone send+confirm endpoints and the contactVerification status object. --- mintlify/snippets/kyc/kyc-unregulated.mdx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mintlify/snippets/kyc/kyc-unregulated.mdx b/mintlify/snippets/kyc/kyc-unregulated.mdx index 3e4df465..8c6f2b65 100644 --- a/mintlify/snippets/kyc/kyc-unregulated.mdx +++ b/mintlify/snippets/kyc/kyc-unregulated.mdx @@ -69,6 +69,21 @@ The response always includes `kycUrl` for the hosted flow. For providers that su Call `POST /customers` with `customerType` and any pre-fill fields you have. The returned `id` is the customer's Grid ID; their `kycStatus` is `PENDING` until verification completes. + + Some regions (for example, the EU) require the customer's email and phone number to be verified before KYC can begin. When this applies, the customer carries a `contactVerification` object (e.g. `{ "email": "PENDING", "phone": "PENDING" }`); when it's absent, no contact verification is required and you can skip this step. + + Drive each channel with a send-then-confirm pair (the provider delivers a one-time code by email/SMS): + + - `POST /customers/{customerId}/verify-email`, then `POST /customers/{customerId}/verify-email/confirm` with `{ "code": "..." }` + - `POST /customers/{customerId}/verify-phone`, then `POST /customers/{customerId}/verify-phone/confirm` with `{ "code": "..." }` + + Re-POST the send endpoint to resend a code. Each channel moves `PENDING` → `VERIFIED`. + + + Generating the KYC link before both channels are `VERIFIED` returns `409`. + + + Call `POST /customers/{customerId}/kyc-link`. Each call returns a fresh single-use `kycUrl` and `expiresAt`; previously-issued links remain single-use but aren't invalidated. From 722fd13c789b6c1b0d4cecb45657f91c4f659f37 Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 6 Jun 2026 17:27:35 -0700 Subject: [PATCH 3/6] Add 500 response and cover already-verified 409 on contact verification endpoints All four new verify-email/verify-phone (send + confirm) paths now document the '500' response that every comparable customer endpoint includes, and the confirm endpoints' '409' descriptions now cover the "already verified" case to match the send endpoints. Regenerated the bundled openapi.yaml and mintlify/openapi.yaml. Co-Authored-By: Claude Opus 4.8 (1M context) --- mintlify/openapi.yaml | 28 +++++++++++++++++-- openapi.yaml | 28 +++++++++++++++++-- .../customers_{customerId}_verify-email.yaml | 6 ++++ ...ers_{customerId}_verify-email_confirm.yaml | 9 +++++- .../customers_{customerId}_verify-phone.yaml | 6 ++++ ...ers_{customerId}_verify-phone_confirm.yaml | 9 +++++- 6 files changed, 80 insertions(+), 6 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 67eeb715..9a0fbd08 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -898,6 +898,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}/verify-email/confirm: parameters: - name: customerId @@ -952,11 +958,17 @@ paths: schema: $ref: '#/components/schemas/Error404' '409': - description: The customer's payment provider does not require contact verification. + description: The customer's payment provider does not require contact verification, or the email is already verified. content: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}/verify-phone: parameters: - name: customerId @@ -1006,6 +1018,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}/verify-phone/confirm: parameters: - name: customerId @@ -1060,11 +1078,17 @@ paths: schema: $ref: '#/components/schemas/Error404' '409': - description: The customer's payment provider does not require contact verification. + description: The customer's payment provider does not require contact verification, or the phone is already verified. content: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/internal-accounts: get: summary: List Customer internal accounts diff --git a/openapi.yaml b/openapi.yaml index 67eeb715..9a0fbd08 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -898,6 +898,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}/verify-email/confirm: parameters: - name: customerId @@ -952,11 +958,17 @@ paths: schema: $ref: '#/components/schemas/Error404' '409': - description: The customer's payment provider does not require contact verification. + description: The customer's payment provider does not require contact verification, or the email is already verified. content: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}/verify-phone: parameters: - name: customerId @@ -1006,6 +1018,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}/verify-phone/confirm: parameters: - name: customerId @@ -1060,11 +1078,17 @@ paths: schema: $ref: '#/components/schemas/Error404' '409': - description: The customer's payment provider does not require contact verification. + description: The customer's payment provider does not require contact verification, or the phone is already verified. content: application/json: schema: $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/internal-accounts: get: summary: List Customer internal accounts diff --git a/openapi/paths/customers/customers_{customerId}_verify-email.yaml b/openapi/paths/customers/customers_{customerId}_verify-email.yaml index fe8ab51b..f6fdac76 100644 --- a/openapi/paths/customers/customers_{customerId}_verify-email.yaml +++ b/openapi/paths/customers/customers_{customerId}_verify-email.yaml @@ -48,3 +48,9 @@ post: application/json: schema: $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml b/openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml index eaaab911..aa5e4619 100644 --- a/openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml +++ b/openapi/paths/customers/customers_{customerId}_verify-email_confirm.yaml @@ -52,8 +52,15 @@ post: $ref: ../../components/schemas/errors/Error404.yaml '409': description: >- - The customer's payment provider does not require contact verification. + The customer's payment provider does not require contact verification, + or the email is already verified. content: application/json: schema: $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/customers/customers_{customerId}_verify-phone.yaml b/openapi/paths/customers/customers_{customerId}_verify-phone.yaml index 4bc6839a..326823f4 100644 --- a/openapi/paths/customers/customers_{customerId}_verify-phone.yaml +++ b/openapi/paths/customers/customers_{customerId}_verify-phone.yaml @@ -48,3 +48,9 @@ post: application/json: schema: $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml b/openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml index 5cc3d7a7..73eb3982 100644 --- a/openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml +++ b/openapi/paths/customers/customers_{customerId}_verify-phone_confirm.yaml @@ -52,8 +52,15 @@ post: $ref: ../../components/schemas/errors/Error404.yaml '409': description: >- - The customer's payment provider does not require contact verification. + The customer's payment provider does not require contact verification, + or the phone is already verified. content: application/json: schema: $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml From 0dc40bc06a818e860cc37149e770ceac63b6174e Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 6 Jun 2026 17:40:19 -0700 Subject: [PATCH 4/6] Declare Contact Verification tag and document contact verification in Direct API flow Adds the Contact Verification tag to the root tags array so it is declared like every other operation group, and adds a note to the Direct API onboarding (KYC) flow clarifying that EU customers must verify email/phone before submitting for verification. Regenerated the bundled openapi.yaml and mintlify/openapi.yaml. Co-Authored-By: Claude Opus 4.8 (1M context) --- mintlify/openapi.yaml | 2 ++ mintlify/snippets/kyc/kyc-unregulated.mdx | 4 ++++ openapi.yaml | 2 ++ openapi/openapi.yaml | 5 +++++ 4 files changed, 13 insertions(+) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 9a0fbd08..41a419d3 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -21,6 +21,8 @@ tags: description: Platform configuration endpoints for managing global settings. You can also configure these settings in the Grid dashboard. - name: Customers description: Customer management endpoints for creating and updating customer information + - name: Contact Verification + description: Endpoints for verifying a customer's email and phone via one-time codes. Required only for customers whose payment provider mandates contact verification (e.g. EU customers); other providers return 409. - name: KYC/KYB Verifications description: Endpoints for Know Your Customer (KYC) and Know Your Business (KYB) verification, including managing beneficial owners and triggering verification for customers. - name: Documents diff --git a/mintlify/snippets/kyc/kyc-unregulated.mdx b/mintlify/snippets/kyc/kyc-unregulated.mdx index 8c6f2b65..0ac89b4e 100644 --- a/mintlify/snippets/kyc/kyc-unregulated.mdx +++ b/mintlify/snippets/kyc/kyc-unregulated.mdx @@ -147,6 +147,10 @@ The shape of the flow depends on the customer type: } }' ``` + + + Where the customer's provider requires it (for example, EU customers), the customer carries a `contactVerification` object and their email and phone must be `VERIFIED` before you submit for verification. Drive each channel with the send-then-confirm pairs (`verify-email` / `verify-email/confirm` and `verify-phone` / `verify-phone/confirm`) described in the Hosted flow's "Verify email and phone" step. When `contactVerification` is absent, no contact verification is required. + diff --git a/openapi.yaml b/openapi.yaml index 9a0fbd08..41a419d3 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -21,6 +21,8 @@ tags: description: Platform configuration endpoints for managing global settings. You can also configure these settings in the Grid dashboard. - name: Customers description: Customer management endpoints for creating and updating customer information + - name: Contact Verification + description: Endpoints for verifying a customer's email and phone via one-time codes. Required only for customers whose payment provider mandates contact verification (e.g. EU customers); other providers return 409. - name: KYC/KYB Verifications description: Endpoints for Know Your Customer (KYC) and Know Your Business (KYB) verification, including managing beneficial owners and triggering verification for customers. - name: Documents diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index fb5611c3..cc7f0e3c 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -18,6 +18,11 @@ tags: also configure these settings in the Grid dashboard. - name: Customers description: Customer management endpoints for creating and updating customer information + - name: Contact Verification + description: >- + Endpoints for verifying a customer's email and phone via one-time codes. + Required only for customers whose payment provider mandates contact + verification (e.g. EU customers); other providers return 409. - name: KYC/KYB Verifications description: >- Endpoints for Know Your Customer (KYC) and Know Your Business (KYB) From b58b3d4cb13a53907bc38389f47afdaade4d9d31 Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 6 Jun 2026 17:44:58 -0700 Subject: [PATCH 5/6] Document 409 on kyc-link for incomplete contact verification The kyc-link path was missing the 409 response that the docs and the contact verification feature describe: generating a KYC link before both email and phone are VERIFIED returns 409. Added it so the spec and docs stay in sync and SDK generators produce a handler for the case. Regenerated the bundled artifacts. Co-Authored-By: Claude Opus 4.8 (1M context) --- mintlify/openapi.yaml | 8 +++++++- openapi.yaml | 8 +++++++- .../schemas/customers/ContactVerification.yaml | 4 ++-- .../customers/customers_{customerId}_kyc-link.yaml | 10 ++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 41a419d3..7fe0e132 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -845,6 +845,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider requires contact verification and the customer's email and phone are not both `VERIFIED` yet. Complete contact verification (see `verify-email` and `verify-phone`) before generating a KYC link. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' '500': description: Internal service error content: @@ -8831,7 +8837,7 @@ components: ContactVerification: type: object description: |- - Email and phone verification state for the customer. This object is **only present when the customer's payment provider requires email and phone verification** (e.g. EU customers). For customers whose provider has no such requirement, this object is omitted entirely — no action is needed. + Email and phone verification state for the customer. This object is **only present when the customer's regulatory jurisdiction requires email and phone verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. When present, both channels must reach `VERIFIED` before the customer can begin KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). properties: diff --git a/openapi.yaml b/openapi.yaml index 41a419d3..7fe0e132 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -845,6 +845,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error404' + '409': + description: The customer's payment provider requires contact verification and the customer's email and phone are not both `VERIFIED` yet. Complete contact verification (see `verify-email` and `verify-phone`) before generating a KYC link. + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' '500': description: Internal service error content: @@ -8831,7 +8837,7 @@ components: ContactVerification: type: object description: |- - Email and phone verification state for the customer. This object is **only present when the customer's payment provider requires email and phone verification** (e.g. EU customers). For customers whose provider has no such requirement, this object is omitted entirely — no action is needed. + Email and phone verification state for the customer. This object is **only present when the customer's regulatory jurisdiction requires email and phone verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. When present, both channels must reach `VERIFIED` before the customer can begin KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). properties: diff --git a/openapi/components/schemas/customers/ContactVerification.yaml b/openapi/components/schemas/customers/ContactVerification.yaml index 1be4035c..e19e1112 100644 --- a/openapi/components/schemas/customers/ContactVerification.yaml +++ b/openapi/components/schemas/customers/ContactVerification.yaml @@ -1,8 +1,8 @@ type: object description: >- Email and phone verification state for the customer. This object is **only - present when the customer's payment provider requires email and phone - verification** (e.g. EU customers). For customers whose provider has no such + present when the customer's regulatory jurisdiction requires email and phone + verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. diff --git a/openapi/paths/customers/customers_{customerId}_kyc-link.yaml b/openapi/paths/customers/customers_{customerId}_kyc-link.yaml index 566e3874..e077e5cc 100644 --- a/openapi/paths/customers/customers_{customerId}_kyc-link.yaml +++ b/openapi/paths/customers/customers_{customerId}_kyc-link.yaml @@ -59,6 +59,16 @@ post: application/json: schema: $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: >- + The customer's payment provider requires contact verification and the + customer's email and phone are not both `VERIFIED` yet. Complete contact + verification (see `verify-email` and `verify-phone`) before generating a + KYC link. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml '500': description: Internal service error content: From 4f31360a937a1dfea11d205c2bdcc0eb4bd3b184 Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Sat, 6 Jun 2026 23:13:22 -0700 Subject: [PATCH 6/6] Make contactVerification channels independently optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A provider may require email verification, phone verification, both, or neither. Drop the required:[email,phone] constraint so each channel is reported independently — only the channels a provider actually requires are present on the object (Striga requires both, but the API no longer assumes that). Update docs accordingly (each present channel must be VERIFIED; verify-email/verify-phone 409 for a channel the provider doesn't require). --- mintlify/openapi.yaml | 11 ++++----- mintlify/snippets/kyc/kyc-unregulated.mdx | 10 ++++---- openapi.yaml | 11 ++++----- .../customers/ContactVerification.yaml | 23 +++++++++++-------- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 7fe0e132..f5aff089 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -8837,19 +8837,16 @@ components: ContactVerification: type: object description: |- - Email and phone verification state for the customer. This object is **only present when the customer's regulatory jurisdiction requires email and phone verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. + Email and/or phone verification state for the customer. This object is **only present when the customer's regulatory jurisdiction requires contact verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. - When present, both channels must reach `VERIFIED` before the customer can begin KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). + Each channel is reported independently: only the channels the customer's provider actually requires are present. A provider may require both email and phone, just one of them, or — when the object is absent — neither. Every channel that **is** present must reach `VERIFIED` before the customer can begin KYC. Drive each present channel with `POST /customers/{customerId}/verify-email` and/or `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). properties: email: $ref: '#/components/schemas/ContactVerificationStatus' - description: Verification status of the customer's email address. + description: Verification status of the customer's email address. Present only when the provider requires email verification. phone: $ref: '#/components/schemas/ContactVerificationStatus' - description: Verification status of the customer's phone number. - required: - - email - - phone + description: Verification status of the customer's phone number. Present only when the provider requires phone verification. Customer: type: object required: diff --git a/mintlify/snippets/kyc/kyc-unregulated.mdx b/mintlify/snippets/kyc/kyc-unregulated.mdx index 0ac89b4e..68fdb506 100644 --- a/mintlify/snippets/kyc/kyc-unregulated.mdx +++ b/mintlify/snippets/kyc/kyc-unregulated.mdx @@ -69,18 +69,18 @@ The response always includes `kycUrl` for the hosted flow. For providers that su Call `POST /customers` with `customerType` and any pre-fill fields you have. The returned `id` is the customer's Grid ID; their `kycStatus` is `PENDING` until verification completes. - - Some regions (for example, the EU) require the customer's email and phone number to be verified before KYC can begin. When this applies, the customer carries a `contactVerification` object (e.g. `{ "email": "PENDING", "phone": "PENDING" }`); when it's absent, no contact verification is required and you can skip this step. + + Some regions (for example, the EU) require the customer's email and/or phone to be verified before KYC can begin. When this applies, the customer carries a `contactVerification` object listing **only the channels that are required** — for example `{ "email": "PENDING", "phone": "PENDING" }`, or just `{ "email": "PENDING" }` if a provider requires email alone. When the object is absent, no contact verification is required and you can skip this step. - Drive each channel with a send-then-confirm pair (the provider delivers a one-time code by email/SMS): + For each channel that's present, drive a send-then-confirm pair (the provider delivers a one-time code by email/SMS): - `POST /customers/{customerId}/verify-email`, then `POST /customers/{customerId}/verify-email/confirm` with `{ "code": "..." }` - `POST /customers/{customerId}/verify-phone`, then `POST /customers/{customerId}/verify-phone/confirm` with `{ "code": "..." }` - Re-POST the send endpoint to resend a code. Each channel moves `PENDING` → `VERIFIED`. + Re-POST the send endpoint to resend a code. Each channel moves `PENDING` → `VERIFIED`. (`verify-email`/`verify-phone` return `409` for a channel the provider doesn't require.) - Generating the KYC link before both channels are `VERIFIED` returns `409`. + Generating the KYC link before every present channel is `VERIFIED` returns `409`. diff --git a/openapi.yaml b/openapi.yaml index 7fe0e132..f5aff089 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -8837,19 +8837,16 @@ components: ContactVerification: type: object description: |- - Email and phone verification state for the customer. This object is **only present when the customer's regulatory jurisdiction requires email and phone verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. + Email and/or phone verification state for the customer. This object is **only present when the customer's regulatory jurisdiction requires contact verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. - When present, both channels must reach `VERIFIED` before the customer can begin KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). + Each channel is reported independently: only the channels the customer's provider actually requires are present. A provider may require both email and phone, just one of them, or — when the object is absent — neither. Every channel that **is** present must reach `VERIFIED` before the customer can begin KYC. Drive each present channel with `POST /customers/{customerId}/verify-email` and/or `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). properties: email: $ref: '#/components/schemas/ContactVerificationStatus' - description: Verification status of the customer's email address. + description: Verification status of the customer's email address. Present only when the provider requires email verification. phone: $ref: '#/components/schemas/ContactVerificationStatus' - description: Verification status of the customer's phone number. - required: - - email - - phone + description: Verification status of the customer's phone number. Present only when the provider requires phone verification. Customer: type: object required: diff --git a/openapi/components/schemas/customers/ContactVerification.yaml b/openapi/components/schemas/customers/ContactVerification.yaml index e19e1112..b388897e 100644 --- a/openapi/components/schemas/customers/ContactVerification.yaml +++ b/openapi/components/schemas/customers/ContactVerification.yaml @@ -1,21 +1,26 @@ type: object description: >- - Email and phone verification state for the customer. This object is **only - present when the customer's regulatory jurisdiction requires email and phone + Email and/or phone verification state for the customer. This object is **only + present when the customer's regulatory jurisdiction requires contact verification** (e.g. EU customers). For customers who have no such requirement, this object is omitted entirely — no action is needed. - When present, both channels must reach `VERIFIED` before the customer can begin - KYC. Drive each channel with `POST /customers/{customerId}/verify-email` and + Each channel is reported independently: only the channels the customer's + provider actually requires are present. A provider may require both email and + phone, just one of them, or — when the object is absent — neither. Every + channel that **is** present must reach `VERIFIED` before the customer can + begin KYC. Drive each present channel with + `POST /customers/{customerId}/verify-email` and/or `POST /customers/{customerId}/verify-phone` (and their `/confirm` sub-routes). properties: email: $ref: ./ContactVerificationStatus.yaml - description: Verification status of the customer's email address. + description: >- + Verification status of the customer's email address. Present only when the + provider requires email verification. phone: $ref: ./ContactVerificationStatus.yaml - description: Verification status of the customer's phone number. -required: - - email - - phone + description: >- + Verification status of the customer's phone number. Present only when the + provider requires phone verification.