diff --git a/mintlify/api-reference/sandbox-testing.mdx b/mintlify/api-reference/sandbox-testing.mdx
index d73d723bc..83965cbc5 100644
--- a/mintlify/api-reference/sandbox-testing.mdx
+++ b/mintlify/api-reference/sandbox-testing.mdx
@@ -10,14 +10,14 @@ import SandboxBeneficiaryVerification from '/snippets/sandbox-beneficiary-verifi
import SandboxTransferPatterns from '/snippets/sandbox-transfer-patterns.mdx';
import SandboxQuotePatterns from '/snippets/sandbox-quote-patterns.mdx';
import SandboxUmaAddresses from '/snippets/sandbox-uma-addresses.mdx';
-import SandboxKybVerification from '/snippets/sandbox-kyb-verification.mdx';
+import SandboxVerification from '/snippets/sandbox-verification.mdx';
import SandboxGlobalAccountMagic from '/snippets/sandbox-global-account-magic.mdx';
The Grid sandbox environment simulates real payment flows without moving real money. You can control test outcomes using special account number patterns and test addresses.
## KYC/KYB verification
-
+
## Adding external accounts
diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml
index 501f49403..90378beb6 100644
--- a/mintlify/openapi.yaml
+++ b/mintlify/openapi.yaml
@@ -11274,6 +11274,35 @@ components:
`(feeType, sourceCurrency)`. Setting variable and fixed fees to 0 for
an existing fee config deactivates it. Only `sourceCurrency: USD` is
accepted today. Omit this field to leave fee configs unchanged.
+ FieldConstraint:
+ type: object
+ description: Machine-readable validator hint accompanying a 400 `INVALID_INPUT` error. Consumers use it to drive form UI (input types, dropdowns, masking, length limits) and to pre-validate the field client-side before re-submitting. Fields are additive.
+ properties:
+ format:
+ type: string
+ description: Named format the value must satisfy — HTML5 input type names (`email`, `tel`, `url`, `date`, ...) or semantic slugs (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`).
+ example: email
+ pattern:
+ type: string
+ description: Regular expression the value must match (JavaScript-flavor).
+ example: ^\d{5}(-\d{4})?$
+ enum:
+ type: array
+ items:
+ type: string
+ description: Allowed values when the field is drawn from a fixed set.
+ example:
+ - SSN
+ - ITIN
+ - NON_US_TAX_ID
+ minLength:
+ type: integer
+ description: Minimum length in characters.
+ example: 1
+ maxLength:
+ type: integer
+ description: Maximum length in characters.
+ example: 500
Error400:
type: object
required:
@@ -11375,7 +11404,14 @@ components:
description: Error message
details:
type: object
- description: Additional error details
+ description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting.
+ properties:
+ field:
+ type: string
+ description: Dot-notation path to the offending field. Present on field-validation errors from submit endpoints.
+ example: taxIdentifier
+ constraint:
+ $ref: '#/components/schemas/FieldConstraint'
additionalProperties: true
Error501:
type: object
@@ -11681,32 +11717,195 @@ components:
type: string
description: Country code (ISO 3166-1 alpha-2)
example: US
- IndividualCustomerFields:
+ IdentificationType:
+ type: string
+ enum:
+ - SSN
+ - ITIN
+ - EIN
+ - NON_US_TAX_ID
+ description: Type of tax identification
+ example: SSN
+ IndividualSourceOfFundsCategory:
+ type: string
+ enum:
+ - SALARY
+ - SELF_EMPLOYMENT_INCOME
+ - INVESTMENT_INCOME
+ - PENSION
+ - RENTAL_INCOME
+ - GIFT
+ - INHERITANCE
+ - LOAN
+ - SAVINGS
+ - SALE_OF_ASSETS
+ - OTHER
+ description: A structured source-of-funds category for an individual customer (FLOW of funds into this account). Distinct from `SourceOfFundsCategory`, which covers business customers.
+ example: SALARY
+ SourceOfWealthCategory:
+ type: string
+ enum:
+ - SALARY
+ - BUSINESS_INCOME
+ - INVESTMENTS
+ - INHERITANCE
+ - PROPERTY_SALE
+ - GIFT
+ - RETIREMENT
+ - SAVINGS
+ - OTHER
+ description: Origin of the customer's accumulated wealth (STOCK). Distinct from `SourceOfFundsCategory` which describes the FLOW of funds for this specific account.
+ example: SALARY
+ PurposeOfAccount:
+ type: string
+ enum:
+ - CONTRACTOR_PAYOUTS
+ - CREATOR_PAYOUTS
+ - EMPLOYEE_PAYOUTS
+ - MARKETPLACE_SELLER_PAYOUTS
+ - SUPPLIER_PAYMENTS
+ - CROSS_BORDER_B2B
+ - AR_AUTOMATION
+ - AP_AUTOMATION
+ - EMBEDDED_PAYMENTS
+ - PLATFORM_FEE_COLLECTION
+ - P2P_TRANSFERS
+ - CHARITABLE_DONATIONS
+ - OTHER
+ description: The intended purpose for using the Grid account
+ example: CONTRACTOR_PAYOUTS
+ ExpectedMonthlyTransactionCount:
+ type: string
+ enum:
+ - COUNT_UNDER_10
+ - COUNT_10_TO_100
+ - COUNT_100_TO_500
+ - COUNT_500_TO_1000
+ - COUNT_OVER_1000
+ description: Expected number of transactions per month
+ example: COUNT_100_TO_500
+ ExpectedMonthlyTransactionVolume:
+ type: string
+ enum:
+ - VOLUME_UNDER_10K
+ - VOLUME_10K_TO_100K
+ - VOLUME_100K_TO_1M
+ - VOLUME_1M_TO_10M
+ - VOLUME_OVER_10M
+ description: Expected total transaction volume per month in USD equivalent
+ example: VOLUME_100K_TO_1M
+ AnnualIncomeRange:
+ type: string
+ enum:
+ - UNDER_50K
+ - RANGE_50K_100K
+ - RANGE_100K_250K
+ - RANGE_250K_1M
+ - OVER_1M
+ description: Bucketed annual income (USD equivalent). Used for enhanced due diligence on higher-risk profiles.
+ example: RANGE_100K_250K
+ NetWorthRange:
+ type: string
+ enum:
+ - UNDER_100K
+ - RANGE_100K_500K
+ - RANGE_500K_1M
+ - RANGE_1M_5M
+ - RANGE_5M_25M
+ - OVER_25M
+ description: Bucketed total net worth (USD equivalent). Used for enhanced due diligence on higher-risk profiles.
+ example: RANGE_500K_1M
+ PepStatus:
+ type: string
+ enum:
+ - NONE
+ - DOMESTIC
+ - FOREIGN
+ - HIO
+ - FAMILY_OR_ASSOCIATE
+ description: Political exposure declaration (Politically Exposed Person status). `HIO` = head of an international organization. `FAMILY_OR_ASSOCIATE` covers close family members and known close associates of a PEP.
+ example: NONE
+ CustomerEdd:
type: object
- required:
- - customerType
+ description: Enhanced-due-diligence (EDD) fields available as optional patchable attributes on an individual customer. Referenced via `allOf` from `IndividualCustomerFields`, so these appear as top-level optional fields on the customer resource itself; there is no separate EDD resource. The specific set required for a given customer is driven by the KYC provider's per-jurisdiction / per-flow / per-volume-tier rules (surfaced through `MISSING_FIELD` errors on `POST /verifications`).
properties:
- customerType:
- type: string
- enum:
- - INDIVIDUAL
- kycStatus:
- $ref: '#/components/schemas/KycStatus'
- fullName:
+ sourceOfFundsCategories:
+ type: array
+ items:
+ $ref: '#/components/schemas/IndividualSourceOfFundsCategory'
+ description: Structured source-of-funds categories (FLOW of funds for this account).
+ example:
+ - SALARY
+ sourceOfFundsOtherDescription:
type: string
- description: Individual's full name
- example: John Michael Doe
- birthDate:
+ description: Free-form description of the customer's source of funds. Required when `sourceOfFundsCategories` includes `OTHER`; otherwise omitted.
+ example: Contest winnings
+ sourceOfWealthCategories:
+ type: array
+ items:
+ $ref: '#/components/schemas/SourceOfWealthCategory'
+ description: Structured source-of-wealth categories (STOCK — origin of accumulated wealth).
+ example:
+ - SALARY
+ - INVESTMENTS
+ sourceOfWealthOtherDescription:
type: string
- format: date
- description: Date of birth in ISO 8601 format (YYYY-MM-DD)
- example: '1990-01-15'
- nationality:
+ description: Free-form description of the customer's source of wealth. Required when `sourceOfWealthCategories` includes `OTHER`; otherwise omitted.
+ example: Royalty income from published works
+ purposeOfAccount:
+ $ref: '#/components/schemas/PurposeOfAccount'
+ purposeOfAccountOtherDescription:
type: string
- description: Country code (ISO 3166-1 alpha-2)
- example: US
- address:
- $ref: '#/components/schemas/Address'
+ description: Free-form description of the customer's intended purpose for the Grid account. Required when `purposeOfAccount` is `OTHER`; otherwise omitted.
+ example: Household budgeting between spouses
+ expectedMonthlyTransactionCount:
+ $ref: '#/components/schemas/ExpectedMonthlyTransactionCount'
+ expectedMonthlyTransactionVolume:
+ $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume'
+ annualIncomeRange:
+ $ref: '#/components/schemas/AnnualIncomeRange'
+ netWorthRange:
+ $ref: '#/components/schemas/NetWorthRange'
+ pepStatus:
+ $ref: '#/components/schemas/PepStatus'
+ IndividualCustomerFields:
+ allOf:
+ - type: object
+ required:
+ - customerType
+ properties:
+ customerType:
+ type: string
+ enum:
+ - INDIVIDUAL
+ kycStatus:
+ $ref: '#/components/schemas/KycStatus'
+ fullName:
+ type: string
+ description: Individual's full name
+ example: John Michael Doe
+ birthDate:
+ type: string
+ format: date
+ description: Date of birth in ISO 8601 format (YYYY-MM-DD)
+ example: '1990-01-15'
+ nationality:
+ type: string
+ description: Country code (ISO 3166-1 alpha-2)
+ example: US
+ address:
+ $ref: '#/components/schemas/Address'
+ taxIdType:
+ $ref: '#/components/schemas/IdentificationType'
+ taxIdentifier:
+ type: string
+ description: Tax-identification number. For US persons this is the SSN (format `###-##-####`) or ITIN. For non-US persons this is the tax number issued by `taxIdCountryOfIssuance`.
+ example: 123-45-6789
+ taxIdCountryOfIssuance:
+ type: string
+ description: Country that issued the tax identifier (ISO 3166-1 alpha-2). Required when `taxIdType` is `NON_US_TAX_ID`.
+ example: US
+ - $ref: '#/components/schemas/CustomerEdd'
IndividualCustomer:
title: Individual Customer
allOf:
@@ -11758,24 +11957,6 @@ components:
- ACCOMMODATION_AND_FOOD_SERVICES
- OTHER_SERVICES
- PUBLIC_ADMINISTRATION
- PurposeOfAccount:
- type: string
- enum:
- - CONTRACTOR_PAYOUTS
- - CREATOR_PAYOUTS
- - EMPLOYEE_PAYOUTS
- - MARKETPLACE_SELLER_PAYOUTS
- - SUPPLIER_PAYMENTS
- - CROSS_BORDER_B2B
- - AR_AUTOMATION
- - AP_AUTOMATION
- - EMBEDDED_PAYMENTS
- - PLATFORM_FEE_COLLECTION
- - P2P_TRANSFERS
- - CHARITABLE_DONATIONS
- - OTHER
- description: The intended purpose for using the Grid account
- example: CONTRACTOR_PAYOUTS
SourceOfFundsCategory:
type: string
enum:
@@ -12027,15 +12208,6 @@ components:
- GENERAL_PARTNER
description: Role of the beneficial owner within the business
example: UBO
- IdentificationType:
- type: string
- enum:
- - SSN
- - ITIN
- - EIN
- - NON_US_TAX_ID
- description: Type of tax identification
- example: SSN
BeneficialOwnerPersonalInfo:
type: object
required:
diff --git a/mintlify/snippets/sandbox-kyb-verification.mdx b/mintlify/snippets/sandbox-kyb-verification.mdx
deleted file mode 100644
index a055f74b6..000000000
--- a/mintlify/snippets/sandbox-kyb-verification.mdx
+++ /dev/null
@@ -1,21 +0,0 @@
-In sandbox, you can trigger specific KYC/KYB verification outcomes using magic suffixes in customer and beneficial owner fields. These let you test different verification flows without waiting for real review.
-
-### Business customer verification
-
-The **last 3 digits** of the `registrationNumber` in `businessInfo` determine the KYB status outcome when you call `POST /verifications`:
-
-| Suffix | `kybStatus` | Behavior |
-|--------|------------|----------|
-| **001** | `PENDING` | KYB verification remains pending |
-| **002** | `REJECTED` | KYB verification is rejected |
-| **Any other** | `APPROVED` | KYB verification is approved |
-
-### Beneficial owner KYC
-
-The **last 3 characters** of the `lastName` in `personalInfo` determine the individual KYC status outcome:
-
-| Suffix | `kycStatus` | Behavior |
-|--------|------------|----------|
-| **001** | `PENDING` | KYC verification remains pending |
-| **002** | `REJECTED` | KYC verification is rejected |
-| **Any other** | `APPROVED` | KYC verification is approved |
diff --git a/mintlify/snippets/sandbox-verification.mdx b/mintlify/snippets/sandbox-verification.mdx
new file mode 100644
index 000000000..413713603
--- /dev/null
+++ b/mintlify/snippets/sandbox-verification.mdx
@@ -0,0 +1,71 @@
+In sandbox, you can trigger specific KYC/KYB verification outcomes using magic suffixes in customer and beneficial owner fields. These let you test different verification flows without waiting for real review.
+
+### Individual customer verification (KYC)
+
+The **last 3 characters** of the `fullName` on `POST /customers` (with `customerType: INDIVIDUAL`) determine the outcome when you call `POST /verifications`:
+
+| Suffix | Outcome | Behavior |
+|--------|---------|----------|
+| **001** | `verificationStatus: IN_PROGRESS`, `kycStatus: PENDING` | KYC verification remains pending (manual review) |
+| **002** | `verificationStatus: REJECTED`, `kycStatus: REJECTED` | KYC verification is rejected |
+| **003** | `verificationStatus: RESOLVE_ERRORS` with `MISSING_FIELD` errors on `edd.*` fields | EDD is required — call `POST /customers/edd` with `customerId` and the requested fields, then retry `POST /verifications` |
+| **Any other** | `verificationStatus: IN_PROGRESS`, `kycStatus: APPROVED` | KYC verification is approved |
+
+EDD flow example:
+
+```bash
+# Create a customer whose fullName ends in "003" to trigger the EDD path
+curl -X POST "https://api.lightspark.com/grid/2025-10-13/customers" \
+ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "customerType": "INDIVIDUAL",
+ "fullName": "Jane Doe 003",
+ "birthDate": "1990-01-15",
+ "nationality": "US",
+ "address": { "line1": "123 Main St", "city": "SF", "state": "CA", "postalCode": "94105", "country": "US" }
+ }'
+
+# First verification attempt: returns MISSING_FIELD errors on edd.* fields
+curl -X POST "https://api.lightspark.com/grid/2025-10-13/verifications" \
+ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
+ -H "Content-Type: application/json" \
+ -d '{ "customerId": "Customer:..." }'
+
+# Supply the EDD fields
+curl -X POST "https://api.lightspark.com/grid/2025-10-13/customers/edd" \
+ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "customerId": "Customer:...",
+ "sourceOfWealthCategories": ["SALARY"],
+ "purposeOfAccount": "PERSONAL_SPEND",
+ "annualIncomeRange": "RANGE_100K_250K"
+ }'
+
+# Retry verification — now approves
+curl -X POST "https://api.lightspark.com/grid/2025-10-13/verifications" \
+ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
+ -H "Content-Type: application/json" \
+ -d '{ "customerId": "Customer:..." }'
+```
+
+### Business customer verification (KYB)
+
+The **last 3 digits** of the `registrationNumber` in `businessInfo` determine the KYB status outcome when you call `POST /verifications`:
+
+| Suffix | `kybStatus` | Behavior |
+|--------|------------|----------|
+| **001** | `PENDING` | KYB verification remains pending |
+| **002** | `REJECTED` | KYB verification is rejected |
+| **Any other** | `APPROVED` | KYB verification is approved |
+
+### Beneficial owner KYC
+
+The **last 3 characters** of the `lastName` in `personalInfo` determine the individual KYC status outcome:
+
+| Suffix | `kycStatus` | Behavior |
+|--------|------------|----------|
+| **001** | `PENDING` | KYC verification remains pending |
+| **002** | `REJECTED` | KYC verification is rejected |
+| **Any other** | `APPROVED` | KYC verification is approved |
diff --git a/openapi.yaml b/openapi.yaml
index 501f49403..90378beb6 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -11274,6 +11274,35 @@ components:
`(feeType, sourceCurrency)`. Setting variable and fixed fees to 0 for
an existing fee config deactivates it. Only `sourceCurrency: USD` is
accepted today. Omit this field to leave fee configs unchanged.
+ FieldConstraint:
+ type: object
+ description: Machine-readable validator hint accompanying a 400 `INVALID_INPUT` error. Consumers use it to drive form UI (input types, dropdowns, masking, length limits) and to pre-validate the field client-side before re-submitting. Fields are additive.
+ properties:
+ format:
+ type: string
+ description: Named format the value must satisfy — HTML5 input type names (`email`, `tel`, `url`, `date`, ...) or semantic slugs (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`).
+ example: email
+ pattern:
+ type: string
+ description: Regular expression the value must match (JavaScript-flavor).
+ example: ^\d{5}(-\d{4})?$
+ enum:
+ type: array
+ items:
+ type: string
+ description: Allowed values when the field is drawn from a fixed set.
+ example:
+ - SSN
+ - ITIN
+ - NON_US_TAX_ID
+ minLength:
+ type: integer
+ description: Minimum length in characters.
+ example: 1
+ maxLength:
+ type: integer
+ description: Maximum length in characters.
+ example: 500
Error400:
type: object
required:
@@ -11375,7 +11404,14 @@ components:
description: Error message
details:
type: object
- description: Additional error details
+ description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting.
+ properties:
+ field:
+ type: string
+ description: Dot-notation path to the offending field. Present on field-validation errors from submit endpoints.
+ example: taxIdentifier
+ constraint:
+ $ref: '#/components/schemas/FieldConstraint'
additionalProperties: true
Error501:
type: object
@@ -11681,32 +11717,195 @@ components:
type: string
description: Country code (ISO 3166-1 alpha-2)
example: US
- IndividualCustomerFields:
+ IdentificationType:
+ type: string
+ enum:
+ - SSN
+ - ITIN
+ - EIN
+ - NON_US_TAX_ID
+ description: Type of tax identification
+ example: SSN
+ IndividualSourceOfFundsCategory:
+ type: string
+ enum:
+ - SALARY
+ - SELF_EMPLOYMENT_INCOME
+ - INVESTMENT_INCOME
+ - PENSION
+ - RENTAL_INCOME
+ - GIFT
+ - INHERITANCE
+ - LOAN
+ - SAVINGS
+ - SALE_OF_ASSETS
+ - OTHER
+ description: A structured source-of-funds category for an individual customer (FLOW of funds into this account). Distinct from `SourceOfFundsCategory`, which covers business customers.
+ example: SALARY
+ SourceOfWealthCategory:
+ type: string
+ enum:
+ - SALARY
+ - BUSINESS_INCOME
+ - INVESTMENTS
+ - INHERITANCE
+ - PROPERTY_SALE
+ - GIFT
+ - RETIREMENT
+ - SAVINGS
+ - OTHER
+ description: Origin of the customer's accumulated wealth (STOCK). Distinct from `SourceOfFundsCategory` which describes the FLOW of funds for this specific account.
+ example: SALARY
+ PurposeOfAccount:
+ type: string
+ enum:
+ - CONTRACTOR_PAYOUTS
+ - CREATOR_PAYOUTS
+ - EMPLOYEE_PAYOUTS
+ - MARKETPLACE_SELLER_PAYOUTS
+ - SUPPLIER_PAYMENTS
+ - CROSS_BORDER_B2B
+ - AR_AUTOMATION
+ - AP_AUTOMATION
+ - EMBEDDED_PAYMENTS
+ - PLATFORM_FEE_COLLECTION
+ - P2P_TRANSFERS
+ - CHARITABLE_DONATIONS
+ - OTHER
+ description: The intended purpose for using the Grid account
+ example: CONTRACTOR_PAYOUTS
+ ExpectedMonthlyTransactionCount:
+ type: string
+ enum:
+ - COUNT_UNDER_10
+ - COUNT_10_TO_100
+ - COUNT_100_TO_500
+ - COUNT_500_TO_1000
+ - COUNT_OVER_1000
+ description: Expected number of transactions per month
+ example: COUNT_100_TO_500
+ ExpectedMonthlyTransactionVolume:
+ type: string
+ enum:
+ - VOLUME_UNDER_10K
+ - VOLUME_10K_TO_100K
+ - VOLUME_100K_TO_1M
+ - VOLUME_1M_TO_10M
+ - VOLUME_OVER_10M
+ description: Expected total transaction volume per month in USD equivalent
+ example: VOLUME_100K_TO_1M
+ AnnualIncomeRange:
+ type: string
+ enum:
+ - UNDER_50K
+ - RANGE_50K_100K
+ - RANGE_100K_250K
+ - RANGE_250K_1M
+ - OVER_1M
+ description: Bucketed annual income (USD equivalent). Used for enhanced due diligence on higher-risk profiles.
+ example: RANGE_100K_250K
+ NetWorthRange:
+ type: string
+ enum:
+ - UNDER_100K
+ - RANGE_100K_500K
+ - RANGE_500K_1M
+ - RANGE_1M_5M
+ - RANGE_5M_25M
+ - OVER_25M
+ description: Bucketed total net worth (USD equivalent). Used for enhanced due diligence on higher-risk profiles.
+ example: RANGE_500K_1M
+ PepStatus:
+ type: string
+ enum:
+ - NONE
+ - DOMESTIC
+ - FOREIGN
+ - HIO
+ - FAMILY_OR_ASSOCIATE
+ description: Political exposure declaration (Politically Exposed Person status). `HIO` = head of an international organization. `FAMILY_OR_ASSOCIATE` covers close family members and known close associates of a PEP.
+ example: NONE
+ CustomerEdd:
type: object
- required:
- - customerType
+ description: Enhanced-due-diligence (EDD) fields available as optional patchable attributes on an individual customer. Referenced via `allOf` from `IndividualCustomerFields`, so these appear as top-level optional fields on the customer resource itself; there is no separate EDD resource. The specific set required for a given customer is driven by the KYC provider's per-jurisdiction / per-flow / per-volume-tier rules (surfaced through `MISSING_FIELD` errors on `POST /verifications`).
properties:
- customerType:
- type: string
- enum:
- - INDIVIDUAL
- kycStatus:
- $ref: '#/components/schemas/KycStatus'
- fullName:
+ sourceOfFundsCategories:
+ type: array
+ items:
+ $ref: '#/components/schemas/IndividualSourceOfFundsCategory'
+ description: Structured source-of-funds categories (FLOW of funds for this account).
+ example:
+ - SALARY
+ sourceOfFundsOtherDescription:
type: string
- description: Individual's full name
- example: John Michael Doe
- birthDate:
+ description: Free-form description of the customer's source of funds. Required when `sourceOfFundsCategories` includes `OTHER`; otherwise omitted.
+ example: Contest winnings
+ sourceOfWealthCategories:
+ type: array
+ items:
+ $ref: '#/components/schemas/SourceOfWealthCategory'
+ description: Structured source-of-wealth categories (STOCK — origin of accumulated wealth).
+ example:
+ - SALARY
+ - INVESTMENTS
+ sourceOfWealthOtherDescription:
type: string
- format: date
- description: Date of birth in ISO 8601 format (YYYY-MM-DD)
- example: '1990-01-15'
- nationality:
+ description: Free-form description of the customer's source of wealth. Required when `sourceOfWealthCategories` includes `OTHER`; otherwise omitted.
+ example: Royalty income from published works
+ purposeOfAccount:
+ $ref: '#/components/schemas/PurposeOfAccount'
+ purposeOfAccountOtherDescription:
type: string
- description: Country code (ISO 3166-1 alpha-2)
- example: US
- address:
- $ref: '#/components/schemas/Address'
+ description: Free-form description of the customer's intended purpose for the Grid account. Required when `purposeOfAccount` is `OTHER`; otherwise omitted.
+ example: Household budgeting between spouses
+ expectedMonthlyTransactionCount:
+ $ref: '#/components/schemas/ExpectedMonthlyTransactionCount'
+ expectedMonthlyTransactionVolume:
+ $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume'
+ annualIncomeRange:
+ $ref: '#/components/schemas/AnnualIncomeRange'
+ netWorthRange:
+ $ref: '#/components/schemas/NetWorthRange'
+ pepStatus:
+ $ref: '#/components/schemas/PepStatus'
+ IndividualCustomerFields:
+ allOf:
+ - type: object
+ required:
+ - customerType
+ properties:
+ customerType:
+ type: string
+ enum:
+ - INDIVIDUAL
+ kycStatus:
+ $ref: '#/components/schemas/KycStatus'
+ fullName:
+ type: string
+ description: Individual's full name
+ example: John Michael Doe
+ birthDate:
+ type: string
+ format: date
+ description: Date of birth in ISO 8601 format (YYYY-MM-DD)
+ example: '1990-01-15'
+ nationality:
+ type: string
+ description: Country code (ISO 3166-1 alpha-2)
+ example: US
+ address:
+ $ref: '#/components/schemas/Address'
+ taxIdType:
+ $ref: '#/components/schemas/IdentificationType'
+ taxIdentifier:
+ type: string
+ description: Tax-identification number. For US persons this is the SSN (format `###-##-####`) or ITIN. For non-US persons this is the tax number issued by `taxIdCountryOfIssuance`.
+ example: 123-45-6789
+ taxIdCountryOfIssuance:
+ type: string
+ description: Country that issued the tax identifier (ISO 3166-1 alpha-2). Required when `taxIdType` is `NON_US_TAX_ID`.
+ example: US
+ - $ref: '#/components/schemas/CustomerEdd'
IndividualCustomer:
title: Individual Customer
allOf:
@@ -11758,24 +11957,6 @@ components:
- ACCOMMODATION_AND_FOOD_SERVICES
- OTHER_SERVICES
- PUBLIC_ADMINISTRATION
- PurposeOfAccount:
- type: string
- enum:
- - CONTRACTOR_PAYOUTS
- - CREATOR_PAYOUTS
- - EMPLOYEE_PAYOUTS
- - MARKETPLACE_SELLER_PAYOUTS
- - SUPPLIER_PAYMENTS
- - CROSS_BORDER_B2B
- - AR_AUTOMATION
- - AP_AUTOMATION
- - EMBEDDED_PAYMENTS
- - PLATFORM_FEE_COLLECTION
- - P2P_TRANSFERS
- - CHARITABLE_DONATIONS
- - OTHER
- description: The intended purpose for using the Grid account
- example: CONTRACTOR_PAYOUTS
SourceOfFundsCategory:
type: string
enum:
@@ -12027,15 +12208,6 @@ components:
- GENERAL_PARTNER
description: Role of the beneficial owner within the business
example: UBO
- IdentificationType:
- type: string
- enum:
- - SSN
- - ITIN
- - EIN
- - NON_US_TAX_ID
- description: Type of tax identification
- example: SSN
BeneficialOwnerPersonalInfo:
type: object
required:
diff --git a/openapi/components/schemas/customers/AnnualIncomeRange.yaml b/openapi/components/schemas/customers/AnnualIncomeRange.yaml
new file mode 100644
index 000000000..f20893f79
--- /dev/null
+++ b/openapi/components/schemas/customers/AnnualIncomeRange.yaml
@@ -0,0 +1,9 @@
+type: string
+enum:
+ - UNDER_50K
+ - RANGE_50K_100K
+ - RANGE_100K_250K
+ - RANGE_250K_1M
+ - OVER_1M
+description: Bucketed annual income (USD equivalent). Used for enhanced due diligence on higher-risk profiles.
+example: RANGE_100K_250K
diff --git a/openapi/components/schemas/customers/CustomerEdd.yaml b/openapi/components/schemas/customers/CustomerEdd.yaml
new file mode 100644
index 000000000..9d847abc5
--- /dev/null
+++ b/openapi/components/schemas/customers/CustomerEdd.yaml
@@ -0,0 +1,55 @@
+type: object
+description: >-
+ Enhanced-due-diligence (EDD) fields available as optional patchable
+ attributes on an individual customer. Referenced via `allOf` from
+ `IndividualCustomerFields`, so these appear as top-level optional
+ fields on the customer resource itself; there is no separate EDD
+ resource. The specific set required for a given customer is driven
+ by the KYC provider's per-jurisdiction / per-flow / per-volume-tier
+ rules (surfaced through `MISSING_FIELD` errors on `POST /verifications`).
+properties:
+ sourceOfFundsCategories:
+ type: array
+ items:
+ $ref: ./IndividualSourceOfFundsCategory.yaml
+ description: Structured source-of-funds categories (FLOW of funds for this account).
+ example:
+ - SALARY
+ sourceOfFundsOtherDescription:
+ type: string
+ description: >-
+ Free-form description of the customer's source of funds. Required when
+ `sourceOfFundsCategories` includes `OTHER`; otherwise omitted.
+ example: Contest winnings
+ sourceOfWealthCategories:
+ type: array
+ items:
+ $ref: ./SourceOfWealthCategory.yaml
+ description: Structured source-of-wealth categories (STOCK — origin of accumulated wealth).
+ example:
+ - SALARY
+ - INVESTMENTS
+ sourceOfWealthOtherDescription:
+ type: string
+ description: >-
+ Free-form description of the customer's source of wealth. Required when
+ `sourceOfWealthCategories` includes `OTHER`; otherwise omitted.
+ example: Royalty income from published works
+ purposeOfAccount:
+ $ref: ./PurposeOfAccount.yaml
+ purposeOfAccountOtherDescription:
+ type: string
+ description: >-
+ Free-form description of the customer's intended purpose for the Grid
+ account. Required when `purposeOfAccount` is `OTHER`; otherwise omitted.
+ example: Household budgeting between spouses
+ expectedMonthlyTransactionCount:
+ $ref: ./ExpectedMonthlyTransactionCount.yaml
+ expectedMonthlyTransactionVolume:
+ $ref: ./ExpectedMonthlyTransactionVolume.yaml
+ annualIncomeRange:
+ $ref: ./AnnualIncomeRange.yaml
+ netWorthRange:
+ $ref: ./NetWorthRange.yaml
+ pepStatus:
+ $ref: ./PepStatus.yaml
diff --git a/openapi/components/schemas/customers/ExpectedMonthlyTransactionCount.yaml b/openapi/components/schemas/customers/ExpectedMonthlyTransactionCount.yaml
new file mode 100644
index 000000000..341e19baa
--- /dev/null
+++ b/openapi/components/schemas/customers/ExpectedMonthlyTransactionCount.yaml
@@ -0,0 +1,9 @@
+type: string
+enum:
+ - COUNT_UNDER_10
+ - COUNT_10_TO_100
+ - COUNT_100_TO_500
+ - COUNT_500_TO_1000
+ - COUNT_OVER_1000
+description: Expected number of transactions per month
+example: COUNT_100_TO_500
diff --git a/openapi/components/schemas/customers/ExpectedMonthlyTransactionVolume.yaml b/openapi/components/schemas/customers/ExpectedMonthlyTransactionVolume.yaml
new file mode 100644
index 000000000..629b2938b
--- /dev/null
+++ b/openapi/components/schemas/customers/ExpectedMonthlyTransactionVolume.yaml
@@ -0,0 +1,9 @@
+type: string
+enum:
+ - VOLUME_UNDER_10K
+ - VOLUME_10K_TO_100K
+ - VOLUME_100K_TO_1M
+ - VOLUME_1M_TO_10M
+ - VOLUME_OVER_10M
+description: Expected total transaction volume per month in USD equivalent
+example: VOLUME_100K_TO_1M
diff --git a/openapi/components/schemas/customers/IndividualCustomerFields.yaml b/openapi/components/schemas/customers/IndividualCustomerFields.yaml
index 45790ce28..36c980a30 100644
--- a/openapi/components/schemas/customers/IndividualCustomerFields.yaml
+++ b/openapi/components/schemas/customers/IndividualCustomerFields.yaml
@@ -1,25 +1,42 @@
-type: object
-required:
- - customerType
-properties:
- customerType:
- type: string
- enum:
- - INDIVIDUAL
- kycStatus:
- $ref: ./KycStatus.yaml
- fullName:
- type: string
- description: Individual's full name
- example: John Michael Doe
- birthDate:
- type: string
- format: date
- description: Date of birth in ISO 8601 format (YYYY-MM-DD)
- example: '1990-01-15'
- nationality:
- type: string
- description: Country code (ISO 3166-1 alpha-2)
- example: US
- address:
- $ref: ../common/Address.yaml
+allOf:
+ - type: object
+ required:
+ - customerType
+ properties:
+ customerType:
+ type: string
+ enum:
+ - INDIVIDUAL
+ kycStatus:
+ $ref: ./KycStatus.yaml
+ fullName:
+ type: string
+ description: Individual's full name
+ example: John Michael Doe
+ birthDate:
+ type: string
+ format: date
+ description: Date of birth in ISO 8601 format (YYYY-MM-DD)
+ example: '1990-01-15'
+ nationality:
+ type: string
+ description: Country code (ISO 3166-1 alpha-2)
+ example: US
+ address:
+ $ref: ../common/Address.yaml
+ taxIdType:
+ $ref: ./IdentificationType.yaml
+ taxIdentifier:
+ type: string
+ description: >-
+ Tax-identification number. For US persons this is the SSN (format
+ `###-##-####`) or ITIN. For non-US persons this is the tax number
+ issued by `taxIdCountryOfIssuance`.
+ example: 123-45-6789
+ taxIdCountryOfIssuance:
+ type: string
+ description: >-
+ Country that issued the tax identifier (ISO 3166-1 alpha-2). Required
+ when `taxIdType` is `NON_US_TAX_ID`.
+ example: US
+ - $ref: ./CustomerEdd.yaml
diff --git a/openapi/components/schemas/customers/IndividualSourceOfFundsCategory.yaml b/openapi/components/schemas/customers/IndividualSourceOfFundsCategory.yaml
new file mode 100644
index 000000000..cde87609d
--- /dev/null
+++ b/openapi/components/schemas/customers/IndividualSourceOfFundsCategory.yaml
@@ -0,0 +1,18 @@
+type: string
+enum:
+ - SALARY
+ - SELF_EMPLOYMENT_INCOME
+ - INVESTMENT_INCOME
+ - PENSION
+ - RENTAL_INCOME
+ - GIFT
+ - INHERITANCE
+ - LOAN
+ - SAVINGS
+ - SALE_OF_ASSETS
+ - OTHER
+description: >-
+ A structured source-of-funds category for an individual customer (FLOW of
+ funds into this account). Distinct from `SourceOfFundsCategory`, which
+ covers business customers.
+example: SALARY
diff --git a/openapi/components/schemas/customers/NetWorthRange.yaml b/openapi/components/schemas/customers/NetWorthRange.yaml
new file mode 100644
index 000000000..cce66428e
--- /dev/null
+++ b/openapi/components/schemas/customers/NetWorthRange.yaml
@@ -0,0 +1,10 @@
+type: string
+enum:
+ - UNDER_100K
+ - RANGE_100K_500K
+ - RANGE_500K_1M
+ - RANGE_1M_5M
+ - RANGE_5M_25M
+ - OVER_25M
+description: Bucketed total net worth (USD equivalent). Used for enhanced due diligence on higher-risk profiles.
+example: RANGE_500K_1M
diff --git a/openapi/components/schemas/customers/PepStatus.yaml b/openapi/components/schemas/customers/PepStatus.yaml
new file mode 100644
index 000000000..a1d15b0ad
--- /dev/null
+++ b/openapi/components/schemas/customers/PepStatus.yaml
@@ -0,0 +1,12 @@
+type: string
+enum:
+ - NONE
+ - DOMESTIC
+ - FOREIGN
+ - HIO
+ - FAMILY_OR_ASSOCIATE
+description: >-
+ Political exposure declaration (Politically Exposed Person status).
+ `HIO` = head of an international organization. `FAMILY_OR_ASSOCIATE` covers
+ close family members and known close associates of a PEP.
+example: NONE
diff --git a/openapi/components/schemas/customers/SourceOfWealthCategory.yaml b/openapi/components/schemas/customers/SourceOfWealthCategory.yaml
new file mode 100644
index 000000000..42654e910
--- /dev/null
+++ b/openapi/components/schemas/customers/SourceOfWealthCategory.yaml
@@ -0,0 +1,16 @@
+type: string
+enum:
+ - SALARY
+ - BUSINESS_INCOME
+ - INVESTMENTS
+ - INHERITANCE
+ - PROPERTY_SALE
+ - GIFT
+ - RETIREMENT
+ - SAVINGS
+ - OTHER
+description: >-
+ Origin of the customer's accumulated wealth (STOCK). Distinct from
+ `SourceOfFundsCategory` which describes the FLOW of funds for this specific
+ account.
+example: SALARY
diff --git a/openapi/components/schemas/errors/Error400.yaml b/openapi/components/schemas/errors/Error400.yaml
index 481fb4580..248011211 100644
--- a/openapi/components/schemas/errors/Error400.yaml
+++ b/openapi/components/schemas/errors/Error400.yaml
@@ -98,5 +98,18 @@ properties:
description: Error message
details:
type: object
- description: Additional error details
+ description: >-
+ Additional error details. Shape varies by `code`. For field-validation
+ errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`),
+ `details.field` and `details.constraint` are populated so platforms can
+ pre-validate their onboarding form before re-submitting.
+ properties:
+ field:
+ type: string
+ description: >-
+ Dot-notation path to the offending field. Present on field-validation
+ errors from submit endpoints.
+ example: taxIdentifier
+ constraint:
+ $ref: ./FieldConstraint.yaml
additionalProperties: true
diff --git a/openapi/components/schemas/errors/FieldConstraint.yaml b/openapi/components/schemas/errors/FieldConstraint.yaml
new file mode 100644
index 000000000..547c82525
--- /dev/null
+++ b/openapi/components/schemas/errors/FieldConstraint.yaml
@@ -0,0 +1,35 @@
+type: object
+description: >-
+ Machine-readable validator hint accompanying a 400 `INVALID_INPUT`
+ error. Consumers use it to drive form UI (input types, dropdowns,
+ masking, length limits) and to pre-validate the field client-side
+ before re-submitting. Fields are additive.
+properties:
+ format:
+ type: string
+ description: >-
+ Named format the value must satisfy — HTML5 input type names
+ (`email`, `tel`, `url`, `date`, ...) or semantic slugs
+ (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`).
+ example: email
+ pattern:
+ type: string
+ description: Regular expression the value must match (JavaScript-flavor).
+ example: ^\d{5}(-\d{4})?$
+ enum:
+ type: array
+ items:
+ type: string
+ description: Allowed values when the field is drawn from a fixed set.
+ example:
+ - SSN
+ - ITIN
+ - NON_US_TAX_ID
+ minLength:
+ type: integer
+ description: Minimum length in characters.
+ example: 1
+ maxLength:
+ type: integer
+ description: Maximum length in characters.
+ example: 500