---
title: "Confirm a customer's email verification code"
method: POST
path: "/customers/{customerId}/verify-email/confirm"
tags: ["Contact Verification"]
---

# Confirm a customer's email verification code

`POST /customers/{customerId}/verify-email/confirm`

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`.

## Request body

- ContactVerificationConfirmRequest — Request body for confirming an email or phone verification challenge.
  - `code` string, required — The one-time verification code the customer received via email or SMS. In sandbox, the code is always `123456`.

## Response `200`

Email verified.

- Customer
  - `id` string — System-generated unique identifier
  - `platformCustomerId` string, required — Platform-specific customer identifier
  - `customerType` 'INDIVIDUAL' | 'BUSINESS', required — Whether the customer is an individual or a business entity
  - `endUserTermsConsent` EndUserTermsConsent
    - `acceptedAt` string, date-time, required — Date and time when the customer accepted the End User Terms.
    - `ipAddress` string, required — IP address of the device the customer used when accepting the terms.
    - `termsVersion` string, required — Version identifier of the accepted Grid End User Terms.
    - `acceptanceMethod` 'CHECKBOX' | 'CLICK_TO_ACCEPT', required — Method the customer used to affirmatively accept the End User Terms.
  - `region` string — Country code (ISO 3166-1 alpha-2) representing the customer's regional identity and regulatory jurisdiction.
  - `currencies` string[] — List of currency codes enabled for this customer.
  - `email` string, email — Email address for the customer.
  - `phoneNumber` string — Phone number for the customer in strict E.164 format.
  - `umaAddress` string, required — Full UMA address (always present in responses, even if system-generated). This is an optional identifier to route payments to the customer.
  - `createdAt` string, date-time — Creation timestamp
  - `updatedAt` string, date-time — Last update timestamp
  - `isDeleted` boolean — Whether the customer is marked as deleted
  - `contactVerification` ContactVerification — 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. 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).
    - `email` 'PENDING' | 'VERIFIED' — 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.
    - `phone` 'PENDING' | 'VERIFIED' — 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.

## Other responses

- `400` — Invalid or expired code
- `401` — Unauthorized
- `404` — Customer not found
- `409` — The customer's payment provider does not require contact verification, or the email is already verified.
- `500` — Internal service error

## Changes

- **2026-08-14** `aaa1fb8782c8` — 1 warning
  - added the new `EXTERNAL_ACCOUNT_VERIFICATION_REQUIRED` enum value to the `code` response property for the response status `400`
- **2026-08-13** `df12ec487f0e` — 1 warning
  - added the new `TRANSACTION_SIZE_LIMIT_EXCEEDED` enum value to the `code` response property for the response status `400`
- **2026-08-11** `b06902b6595a` — 4 warning
  - added the new `CARDHOLDER_KYC_NOT_APPROVED` enum value to the `code` response property for the response status `400`
  - added the new `CARD_ALREADY_CLOSED` enum value to the `code` response property for the response status `409`
  - added the new `CARD_NOT_MUTABLE` enum value to the `code` response property for the response status `409`
  - added the new `INVALID_STATE_TRANSITION` enum value to the `code` response property for the response status `409`
- **2026-08-06** `526036c12609` — 1 warning, 1 info
  - added the new `END_USER_TERMS_VERSION_NOT_FOUND` enum value to the `code` response property for the response status `400`
  - added the optional property `endUserTermsConsent` to the response with the `200` status
- **2026-07-31** `b21ed434ee6e` — 2 warning, 1 info
  - added the new `BENEFICIARY_TRUSTED` enum value to the `code` response property for the response status `409`
  - added the new `SCA_SESSION_REQUIRED` enum value to the `code` response property for the response status `409`
  - added the optional property `details/errors` to the response with the `400` status

[Full history](https://skmtc.dev/stainless-api/apis/grid-api/changes/customers/:customerId/verify-email/confirm/post.md)

---

[API](https://skmtc.dev/stainless-api/apis/grid-api.md) · [All operations](https://skmtc.dev/stainless-api/apis/grid-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/stainless-api/grid-api/revisions/f0fa3ab7c7b0/schema)
