From be7912c3bbe28b41bbd6223f98907a47583e4d22 Mon Sep 17 00:00:00 2001 From: Aaron Kanter Date: Wed, 22 Jul 2026 19:51:51 +0000 Subject: [PATCH 1/6] plan-kyc-singleton-implementation --- mintlify/api-reference/sandbox-testing.mdx | 4 +- mintlify/openapi.yaml | 485 ++++++++++++++---- .../snippets/sandbox-kyb-verification.mdx | 21 - mintlify/snippets/sandbox-verification.mdx | 71 +++ openapi.yaml | 485 ++++++++++++++---- .../schemas/customers/AnnualIncomeRange.yaml | 9 + .../schemas/customers/CustomerEdd.yaml | 52 ++ .../customers/CustomerEddCreateRequest.yaml | 13 + .../ExpectedMonthlyTransactionCount.yaml | 9 + .../ExpectedMonthlyTransactionVolume.yaml | 9 + .../customers/IndividualCustomerFields.yaml | 2 + .../IndividualSourceOfFundsCategory.yaml | 18 + .../schemas/customers/NetWorthRange.yaml | 10 + .../schemas/customers/PepStatus.yaml | 12 + .../customers/SourceOfWealthCategory.yaml | 16 + .../schemas/customers/TaxIdentification.yaml | 20 + .../components/schemas/errors/Error400.yaml | 16 +- .../schemas/errors/FieldConstraint.yaml | 33 ++ openapi/openapi.yaml | 2 + openapi/paths/customers/customers_edd.yaml | 151 ++++++ 20 files changed, 1198 insertions(+), 240 deletions(-) delete mode 100644 mintlify/snippets/sandbox-kyb-verification.mdx create mode 100644 mintlify/snippets/sandbox-verification.mdx create mode 100644 openapi/components/schemas/customers/AnnualIncomeRange.yaml create mode 100644 openapi/components/schemas/customers/CustomerEdd.yaml create mode 100644 openapi/components/schemas/customers/CustomerEddCreateRequest.yaml create mode 100644 openapi/components/schemas/customers/ExpectedMonthlyTransactionCount.yaml create mode 100644 openapi/components/schemas/customers/ExpectedMonthlyTransactionVolume.yaml create mode 100644 openapi/components/schemas/customers/IndividualSourceOfFundsCategory.yaml create mode 100644 openapi/components/schemas/customers/NetWorthRange.yaml create mode 100644 openapi/components/schemas/customers/PepStatus.yaml create mode 100644 openapi/components/schemas/customers/SourceOfWealthCategory.yaml create mode 100644 openapi/components/schemas/customers/TaxIdentification.yaml create mode 100644 openapi/components/schemas/errors/FieldConstraint.yaml create mode 100644 openapi/paths/customers/customers_edd.yaml 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..6e1cd7018 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -594,6 +594,150 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /customers/edd: + get: + summary: Get a customer's enhanced-due-diligence (EDD) fields + description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. + operationId: getCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: The Grid customer ID to retrieve EDD data for. + required: true + schema: + type: string + responses: + '200': + description: EDD payload retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found or no EDD data recorded for this customer + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + post: + summary: Create or replace a customer's enhanced-due-diligence (EDD) fields + description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. + operationId: createCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEddCreateRequest' + responses: + '200': + description: EDD payload created or replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + 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' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + patch: + summary: Partially update a customer's enhanced-due-diligence (EDD) fields + description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. + operationId: updateCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: The Grid customer ID whose EDD data is being updated. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + responses: + '200': + description: EDD payload updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found or no EDD data recorded to update + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}: parameters: - name: customerId @@ -3687,7 +3831,6 @@ paths: totalReceivingAmount: 9200 exchangeRate: 0.92 feesIncluded: 10 - platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000005 '202': description: | @@ -9366,7 +9509,6 @@ webhooks: totalReceivingAmount: 4625000 exchangeRate: 92.5 feesIncluded: 250 - platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 createdAt: '2025-10-03T15:00:00Z' updatedAt: '2025-10-03T15:00:00Z' @@ -11038,73 +11180,6 @@ components: $ref: '#/components/schemas/CardTokenization2FAEmailConfig' sms: $ref: '#/components/schemas/CardTokenization2FASmsConfig' - FeeType: - type: string - enum: - - CROSS_CURRENCY_TRANSACTION - description: | - The kind of activity this fee applies to. - - - `CROSS_CURRENCY_TRANSACTION` — fee charged on a cross-currency Grid transaction - (source currency differs from destination currency). - example: CROSS_CURRENCY_TRANSACTION - Currency: - type: object - properties: - code: - type: string - description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) - example: USD - name: - type: string - description: Full name of the currency - example: United States Dollar - symbol: - type: string - description: Symbol of the currency - example: $ - decimals: - type: integer - description: Number of decimal places for the currency - minimum: 0 - example: 2 - CurrencyAmount: - type: object - required: - - amount - - currency - properties: - amount: - type: integer - format: int64 - description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) - example: 12550 - currency: - $ref: '#/components/schemas/Currency' - FeeConfig: - type: object - description: A platform-configured fee collected by Grid and settled to the platform internal account. There can be at most one fee config for a given fee type and source currency pair. The fee will apply to all transactions of the fee type that originate in the source currency. - properties: - feeType: - $ref: '#/components/schemas/FeeType' - sourceCurrency: - type: string - description: Currency code of the sending side this fee applies to. Only `USD` is accepted today; other currencies return a `NOT_IMPLEMENTED` error. - example: USD - variableFeeBps: - type: integer - minimum: 0 - maximum: 10000 - description: Variable fee in basis points (1 bps = 0.01%) to apply to a transaction's source-currency amount. - example: 30 - fixedFee: - $ref: '#/components/schemas/CurrencyAmount' - description: Fixed fee charged per transaction, in the smallest unit of the source currency. The fixed fee currency must match the fee config's `sourceCurrency`. - required: - - feeType - - sourceCurrency - - variableFeeBps - - fixedFee PlatformConfig: type: object properties: @@ -11151,14 +11226,6 @@ components: description: | Branding and sender configuration for card-tokenization authentication messages. This configuration is independent of embedded-wallet support. - feeConfigs: - type: array - items: - $ref: '#/components/schemas/FeeConfig' - description: | - Platform-collected fees that should be added on top of - Grid-collected fees. Contains every currently-active fee config - for the platform. createdAt: type: string format: date-time @@ -11265,15 +11332,35 @@ components: Update card-tokenization authentication branding and delivery settings. Fields omitted from the nested object are left unchanged. Changes apply to subsequent delivery attempts. - feeConfigs: + FieldConstraint: + type: object + description: Machine-readable validator hint. Platforms use it to pre-validate their own onboarding form before submitting, and to render form UI (e.g., surface a dropdown for `enum`, mask input by `pattern`). + properties: + format: + type: string + description: 'Named format the value must satisfy. Examples: `date`, `email`, `iso3166-1-alpha-2`, `bcp47-language-tag`.' + example: iso3166-1-alpha-2 + pattern: + type: string + description: Regular expression the value must match (JavaScript-flavor). + example: ^\d{5}(-\d{4})?$ + enum: type: array items: - $ref: '#/components/schemas/FeeConfig' - description: | - Merge-by-key upsert of platform fee configs, keyed by - `(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. + 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 +11462,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}`, `POST /customers/edd`, `PATCH /customers/edd`), `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: taxIdentification.identifier + constraint: + $ref: '#/components/schemas/FieldConstraint' additionalProperties: true Error501: type: object @@ -11406,6 +11500,26 @@ components: type: object description: Additional error details additionalProperties: true + Currency: + type: object + properties: + code: + type: string + description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) + example: USD + name: + type: string + description: Full name of the currency + example: United States Dollar + symbol: + type: string + description: Symbol of the currency + example: $ + decimals: + type: integer + description: Number of decimal places for the currency + minimum: 0 + example: 2 PaymentRail: type: string enum: @@ -11681,6 +11795,31 @@ components: type: string description: Country code (ISO 3166-1 alpha-2) example: US + IdentificationType: + type: string + enum: + - SSN + - ITIN + - EIN + - NON_US_TAX_ID + description: Type of tax identification + example: SSN + TaxIdentification: + type: object + required: + - idType + - identifier + properties: + idType: + $ref: '#/components/schemas/IdentificationType' + identifier: + type: string + description: The tax-identification number. For US persons this is the SSN (format `###-##-####`) or ITIN. For non-US persons this is the tax number issued by `countryOfIssuance`. + example: 123-45-6789 + countryOfIssuance: + type: string + description: Country that issued the tax identifier (ISO 3166-1 alpha-2). Required when `idType` is `NON_US_TAX_ID`. + example: US IndividualCustomerFields: type: object required: @@ -11707,6 +11846,8 @@ components: example: US address: $ref: '#/components/schemas/Address' + taxIdentification: + $ref: '#/components/schemas/TaxIdentification' IndividualCustomer: title: Individual Customer allOf: @@ -12027,15 +12168,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: @@ -12232,12 +12364,12 @@ components: email: type: string format: email - description: Email address for the customer. **Required in regions that verify the email address before identity verification** (e.g. the EU); optional otherwise. + description: Email address for the customer. example: john.doe@example.com phoneNumber: type: string pattern: ^\+[1-9]\d{1,14}$ - description: Phone number for the customer in strict E.164 format. **Required in regions that verify the phone number before identity verification** (e.g. the EU); optional otherwise. + description: Phone number for the customer in strict E.164 format. example: '+14155551234' umaAddress: type: string @@ -12424,6 +12556,130 @@ components: type: object description: Additional error details additionalProperties: true + 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 + 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 + description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' + 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: '#/components/schemas/SourceOfWealthCategory' + 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: '#/components/schemas/PurposeOfAccount' + 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: '#/components/schemas/ExpectedMonthlyTransactionCount' + expectedMonthlyTransactionVolume: + $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' + annualIncomeRange: + $ref: '#/components/schemas/AnnualIncomeRange' + netWorthRange: + $ref: '#/components/schemas/NetWorthRange' + pepStatus: + $ref: '#/components/schemas/PepStatus' Error404: type: object required: @@ -12469,6 +12725,18 @@ components: type: object description: Additional error details additionalProperties: true + CustomerEddCreateRequest: + description: Request body for `POST /customers/edd`. Composes the full `CustomerEdd` field set and adds the required `customerId` link. + allOf: + - $ref: '#/components/schemas/CustomerEdd' + - type: object + required: + - customerId + properties: + customerId: + type: string + description: The Grid customer ID whose EDD data is being created or replaced. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 Error410: type: object required: @@ -13330,6 +13598,19 @@ components: - `FROZEN`: The account cannot send or receive payments. Grid may freeze an account in response to compliance or fraud signals; payments are blocked while the account remains frozen. - `FAILED`: The account could not be provisioned. Grid was unable to create the underlying account, so it cannot send or receive payments and requires remediation. example: ACTIVE + CurrencyAmount: + type: object + required: + - amount + - currency + properties: + amount: + type: integer + format: int64 + description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) + example: 12550 + currency: + $ref: '#/components/schemas/Currency' PaymentAccountType: type: string enum: @@ -20239,12 +20520,6 @@ components: description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). minimum: 0 example: 10 - platformFees: - type: integer - format: int64 - description: The portion of `fees` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `fees`. - minimum: 0 - example: 5 reconciliationInstructions: $ref: '#/components/schemas/ReconciliationInstructions' description: Reconciliation details for this transaction. For the on-chain hash of a crypto payout to an external wallet, see the destination's `onChainTransaction` instead. @@ -20825,12 +21100,6 @@ components: description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' minimum: 0 example: 10 - platformFeesIncluded: - type: integer - format: int64 - description: The portion of `feesIncluded` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `feesIncluded`. May be omitted from payloads produced before platform fees existed. - minimum: 0 - example: 5 paymentInstructions: type: array description: Payment instructions for executing the payment. This is not required when using an internal account source. 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..6e1cd7018 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -594,6 +594,150 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /customers/edd: + get: + summary: Get a customer's enhanced-due-diligence (EDD) fields + description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. + operationId: getCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: The Grid customer ID to retrieve EDD data for. + required: true + schema: + type: string + responses: + '200': + description: EDD payload retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found or no EDD data recorded for this customer + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + post: + summary: Create or replace a customer's enhanced-due-diligence (EDD) fields + description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. + operationId: createCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEddCreateRequest' + responses: + '200': + description: EDD payload created or replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + 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' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + patch: + summary: Partially update a customer's enhanced-due-diligence (EDD) fields + description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. + operationId: updateCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: The Grid customer ID whose EDD data is being updated. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + responses: + '200': + description: EDD payload updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found or no EDD data recorded to update + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/{customerId}: parameters: - name: customerId @@ -3687,7 +3831,6 @@ paths: totalReceivingAmount: 9200 exchangeRate: 0.92 feesIncluded: 10 - platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000005 '202': description: | @@ -9366,7 +9509,6 @@ webhooks: totalReceivingAmount: 4625000 exchangeRate: 92.5 feesIncluded: 250 - platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 createdAt: '2025-10-03T15:00:00Z' updatedAt: '2025-10-03T15:00:00Z' @@ -11038,73 +11180,6 @@ components: $ref: '#/components/schemas/CardTokenization2FAEmailConfig' sms: $ref: '#/components/schemas/CardTokenization2FASmsConfig' - FeeType: - type: string - enum: - - CROSS_CURRENCY_TRANSACTION - description: | - The kind of activity this fee applies to. - - - `CROSS_CURRENCY_TRANSACTION` — fee charged on a cross-currency Grid transaction - (source currency differs from destination currency). - example: CROSS_CURRENCY_TRANSACTION - Currency: - type: object - properties: - code: - type: string - description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) - example: USD - name: - type: string - description: Full name of the currency - example: United States Dollar - symbol: - type: string - description: Symbol of the currency - example: $ - decimals: - type: integer - description: Number of decimal places for the currency - minimum: 0 - example: 2 - CurrencyAmount: - type: object - required: - - amount - - currency - properties: - amount: - type: integer - format: int64 - description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) - example: 12550 - currency: - $ref: '#/components/schemas/Currency' - FeeConfig: - type: object - description: A platform-configured fee collected by Grid and settled to the platform internal account. There can be at most one fee config for a given fee type and source currency pair. The fee will apply to all transactions of the fee type that originate in the source currency. - properties: - feeType: - $ref: '#/components/schemas/FeeType' - sourceCurrency: - type: string - description: Currency code of the sending side this fee applies to. Only `USD` is accepted today; other currencies return a `NOT_IMPLEMENTED` error. - example: USD - variableFeeBps: - type: integer - minimum: 0 - maximum: 10000 - description: Variable fee in basis points (1 bps = 0.01%) to apply to a transaction's source-currency amount. - example: 30 - fixedFee: - $ref: '#/components/schemas/CurrencyAmount' - description: Fixed fee charged per transaction, in the smallest unit of the source currency. The fixed fee currency must match the fee config's `sourceCurrency`. - required: - - feeType - - sourceCurrency - - variableFeeBps - - fixedFee PlatformConfig: type: object properties: @@ -11151,14 +11226,6 @@ components: description: | Branding and sender configuration for card-tokenization authentication messages. This configuration is independent of embedded-wallet support. - feeConfigs: - type: array - items: - $ref: '#/components/schemas/FeeConfig' - description: | - Platform-collected fees that should be added on top of - Grid-collected fees. Contains every currently-active fee config - for the platform. createdAt: type: string format: date-time @@ -11265,15 +11332,35 @@ components: Update card-tokenization authentication branding and delivery settings. Fields omitted from the nested object are left unchanged. Changes apply to subsequent delivery attempts. - feeConfigs: + FieldConstraint: + type: object + description: Machine-readable validator hint. Platforms use it to pre-validate their own onboarding form before submitting, and to render form UI (e.g., surface a dropdown for `enum`, mask input by `pattern`). + properties: + format: + type: string + description: 'Named format the value must satisfy. Examples: `date`, `email`, `iso3166-1-alpha-2`, `bcp47-language-tag`.' + example: iso3166-1-alpha-2 + pattern: + type: string + description: Regular expression the value must match (JavaScript-flavor). + example: ^\d{5}(-\d{4})?$ + enum: type: array items: - $ref: '#/components/schemas/FeeConfig' - description: | - Merge-by-key upsert of platform fee configs, keyed by - `(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. + 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 +11462,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}`, `POST /customers/edd`, `PATCH /customers/edd`), `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: taxIdentification.identifier + constraint: + $ref: '#/components/schemas/FieldConstraint' additionalProperties: true Error501: type: object @@ -11406,6 +11500,26 @@ components: type: object description: Additional error details additionalProperties: true + Currency: + type: object + properties: + code: + type: string + description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) + example: USD + name: + type: string + description: Full name of the currency + example: United States Dollar + symbol: + type: string + description: Symbol of the currency + example: $ + decimals: + type: integer + description: Number of decimal places for the currency + minimum: 0 + example: 2 PaymentRail: type: string enum: @@ -11681,6 +11795,31 @@ components: type: string description: Country code (ISO 3166-1 alpha-2) example: US + IdentificationType: + type: string + enum: + - SSN + - ITIN + - EIN + - NON_US_TAX_ID + description: Type of tax identification + example: SSN + TaxIdentification: + type: object + required: + - idType + - identifier + properties: + idType: + $ref: '#/components/schemas/IdentificationType' + identifier: + type: string + description: The tax-identification number. For US persons this is the SSN (format `###-##-####`) or ITIN. For non-US persons this is the tax number issued by `countryOfIssuance`. + example: 123-45-6789 + countryOfIssuance: + type: string + description: Country that issued the tax identifier (ISO 3166-1 alpha-2). Required when `idType` is `NON_US_TAX_ID`. + example: US IndividualCustomerFields: type: object required: @@ -11707,6 +11846,8 @@ components: example: US address: $ref: '#/components/schemas/Address' + taxIdentification: + $ref: '#/components/schemas/TaxIdentification' IndividualCustomer: title: Individual Customer allOf: @@ -12027,15 +12168,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: @@ -12232,12 +12364,12 @@ components: email: type: string format: email - description: Email address for the customer. **Required in regions that verify the email address before identity verification** (e.g. the EU); optional otherwise. + description: Email address for the customer. example: john.doe@example.com phoneNumber: type: string pattern: ^\+[1-9]\d{1,14}$ - description: Phone number for the customer in strict E.164 format. **Required in regions that verify the phone number before identity verification** (e.g. the EU); optional otherwise. + description: Phone number for the customer in strict E.164 format. example: '+14155551234' umaAddress: type: string @@ -12424,6 +12556,130 @@ components: type: object description: Additional error details additionalProperties: true + 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 + 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 + description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' + 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: '#/components/schemas/SourceOfWealthCategory' + 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: '#/components/schemas/PurposeOfAccount' + 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: '#/components/schemas/ExpectedMonthlyTransactionCount' + expectedMonthlyTransactionVolume: + $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' + annualIncomeRange: + $ref: '#/components/schemas/AnnualIncomeRange' + netWorthRange: + $ref: '#/components/schemas/NetWorthRange' + pepStatus: + $ref: '#/components/schemas/PepStatus' Error404: type: object required: @@ -12469,6 +12725,18 @@ components: type: object description: Additional error details additionalProperties: true + CustomerEddCreateRequest: + description: Request body for `POST /customers/edd`. Composes the full `CustomerEdd` field set and adds the required `customerId` link. + allOf: + - $ref: '#/components/schemas/CustomerEdd' + - type: object + required: + - customerId + properties: + customerId: + type: string + description: The Grid customer ID whose EDD data is being created or replaced. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 Error410: type: object required: @@ -13330,6 +13598,19 @@ components: - `FROZEN`: The account cannot send or receive payments. Grid may freeze an account in response to compliance or fraud signals; payments are blocked while the account remains frozen. - `FAILED`: The account could not be provisioned. Grid was unable to create the underlying account, so it cannot send or receive payments and requires remediation. example: ACTIVE + CurrencyAmount: + type: object + required: + - amount + - currency + properties: + amount: + type: integer + format: int64 + description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) + example: 12550 + currency: + $ref: '#/components/schemas/Currency' PaymentAccountType: type: string enum: @@ -20239,12 +20520,6 @@ components: description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). minimum: 0 example: 10 - platformFees: - type: integer - format: int64 - description: The portion of `fees` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `fees`. - minimum: 0 - example: 5 reconciliationInstructions: $ref: '#/components/schemas/ReconciliationInstructions' description: Reconciliation details for this transaction. For the on-chain hash of a crypto payout to an external wallet, see the destination's `onChainTransaction` instead. @@ -20825,12 +21100,6 @@ components: description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' minimum: 0 example: 10 - platformFeesIncluded: - type: integer - format: int64 - description: The portion of `feesIncluded` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `feesIncluded`. May be omitted from payloads produced before platform fees existed. - minimum: 0 - example: 5 paymentInstructions: type: array description: Payment instructions for executing the payment. This is not required when using an internal account source. 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..62e84034e --- /dev/null +++ b/openapi/components/schemas/customers/CustomerEdd.yaml @@ -0,0 +1,52 @@ +type: object +description: >- + Enhanced-due-diligence (EDD) fields for an individual customer. All fields + are optional; 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/CustomerEddCreateRequest.yaml b/openapi/components/schemas/customers/CustomerEddCreateRequest.yaml new file mode 100644 index 000000000..ea2db277a --- /dev/null +++ b/openapi/components/schemas/customers/CustomerEddCreateRequest.yaml @@ -0,0 +1,13 @@ +description: >- + Request body for `POST /customers/edd`. Composes the full `CustomerEdd` + field set and adds the required `customerId` link. +allOf: + - $ref: ./CustomerEdd.yaml + - type: object + required: + - customerId + properties: + customerId: + type: string + description: The Grid customer ID whose EDD data is being created or replaced. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 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..6519ca508 100644 --- a/openapi/components/schemas/customers/IndividualCustomerFields.yaml +++ b/openapi/components/schemas/customers/IndividualCustomerFields.yaml @@ -23,3 +23,5 @@ properties: example: US address: $ref: ../common/Address.yaml + taxIdentification: + $ref: ./TaxIdentification.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/customers/TaxIdentification.yaml b/openapi/components/schemas/customers/TaxIdentification.yaml new file mode 100644 index 000000000..3c1ef6945 --- /dev/null +++ b/openapi/components/schemas/customers/TaxIdentification.yaml @@ -0,0 +1,20 @@ +type: object +required: + - idType + - identifier +properties: + idType: + $ref: ./IdentificationType.yaml + identifier: + type: string + description: >- + The tax-identification number. For US persons this is the SSN (format + `###-##-####`) or ITIN. For non-US persons this is the tax number issued + by `countryOfIssuance`. + example: 123-45-6789 + countryOfIssuance: + type: string + description: >- + Country that issued the tax identifier (ISO 3166-1 alpha-2). Required + when `idType` is `NON_US_TAX_ID`. + example: US diff --git a/openapi/components/schemas/errors/Error400.yaml b/openapi/components/schemas/errors/Error400.yaml index 481fb4580..77a443959 100644 --- a/openapi/components/schemas/errors/Error400.yaml +++ b/openapi/components/schemas/errors/Error400.yaml @@ -98,5 +98,19 @@ 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}`, + `POST /customers/edd`, `PATCH /customers/edd`), `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: taxIdentification.identifier + 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..8541c18a2 --- /dev/null +++ b/openapi/components/schemas/errors/FieldConstraint.yaml @@ -0,0 +1,33 @@ +type: object +description: >- + Machine-readable validator hint. Platforms use it to pre-validate their own + onboarding form before submitting, and to render form UI (e.g., surface a + dropdown for `enum`, mask input by `pattern`). +properties: + format: + type: string + description: >- + Named format the value must satisfy. Examples: `date`, `email`, `iso3166-1-alpha-2`, + `bcp47-language-tag`. + example: iso3166-1-alpha-2 + 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 diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index f5b2f8028..33ca1e02f 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -141,6 +141,8 @@ paths: $ref: paths/discoveries/discoveries.yaml /customers: $ref: paths/customers/customers.yaml + /customers/edd: + $ref: paths/customers/customers_edd.yaml /customers/{customerId}: $ref: paths/customers/customers_{customerId}.yaml /customers/{customerId}/kyc-link: diff --git a/openapi/paths/customers/customers_edd.yaml b/openapi/paths/customers/customers_edd.yaml new file mode 100644 index 000000000..8dcde2e71 --- /dev/null +++ b/openapi/paths/customers/customers_edd.yaml @@ -0,0 +1,151 @@ +get: + summary: Get a customer's enhanced-due-diligence (EDD) fields + description: >- + Retrieve the EDD fields previously supplied for a customer. Returns `404` + if no EDD data has been recorded for the customer yet. + operationId: getCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: The Grid customer ID to retrieve EDD data for. + required: true + schema: + type: string + responses: + '200': + description: EDD payload retrieved successfully + content: + application/json: + schema: + $ref: ../../components/schemas/customers/CustomerEdd.yaml + '400': + description: Bad request - Invalid parameters + 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 or no EDD data recorded for this customer + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml +post: + summary: Create or replace a customer's enhanced-due-diligence (EDD) fields + description: >- + Supply the EDD fields for a customer. Overwrites any previously recorded + EDD data for that customer. Call this endpoint when `POST /verifications` + returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry + `POST /verifications` to complete the KYC check. + operationId: createCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/customers/CustomerEddCreateRequest.yaml + responses: + '200': + description: EDD payload created or replaced successfully + content: + application/json: + schema: + $ref: ../../components/schemas/customers/CustomerEdd.yaml + '400': + description: Bad request + 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 + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml +patch: + summary: Partially update a customer's enhanced-due-diligence (EDD) fields + description: >- + Merge the provided EDD fields into any previously recorded EDD data for + the customer. Fields omitted from the request body are left unchanged. + operationId: updateCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: The Grid customer ID whose EDD data is being updated. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/customers/CustomerEdd.yaml + responses: + '200': + description: EDD payload updated successfully + content: + application/json: + schema: + $ref: ../../components/schemas/customers/CustomerEdd.yaml + '400': + description: Bad request + 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 or no EDD data recorded to update + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml From 8e3fd35fc1e562c6a191efefc73d717d277f8269 Mon Sep 17 00:00:00 2001 From: Aaron Kanter Date: Fri, 24 Jul 2026 16:47:07 +0000 Subject: [PATCH 2/6] Expand FieldConstraint descriptions to document consumer contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses @jklein24's review questions on grid-api#726: - top-level: explicit that FieldConstraint drives both client-side pre-validation and direct form-UI rendering (HTML5 input type, inputmode, autocomplete, maxlength attributes). - format: usage guidance — prefer HTML5 input type names when the field maps to one; use semantic slugs otherwise; treat unknown values as opaque and fall back to accompanying pattern/length constraints. Example changed to `email` (HTML5 canonical). - pattern: notes that length is surfaced as separate minLength/ maxLength fields so consumers can wire native controls without regex evaluation. - minLength / maxLength: rationale for being distinct fields (native wire-up) documented. No schema shape change; description-only. Co-Authored-By: jklein24 --- mintlify/openapi.yaml | 12 +++--- openapi.yaml | 12 +++--- .../schemas/errors/FieldConstraint.yaml | 41 +++++++++++++++---- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 6e1cd7018..f08ead206 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -11334,15 +11334,15 @@ components: to subsequent delivery attempts. FieldConstraint: type: object - description: Machine-readable validator hint. Platforms use it to pre-validate their own onboarding form before submitting, and to render form UI (e.g., surface a dropdown for `enum`, mask input by `pattern`). + description: 'Machine-readable validator hint. Platforms use it to (a) pre-validate the end-user''s input on their onboarding form before submitting, and (b) drive form UI directly — HTML5 `` selection and `autocomplete` / `inputmode` / a11y attributes via `format`, dropdown menus via `enum`, input masking via `pattern`, native length limits via `minLength` / `maxLength`. Fields are additive; a single constraint may set several (e.g. `format: email` + `maxLength: 254`). Grid emits only constraints it enforces server-side.' properties: format: type: string - description: 'Named format the value must satisfy. Examples: `date`, `email`, `iso3166-1-alpha-2`, `bcp47-language-tag`.' - example: iso3166-1-alpha-2 + description: Named format the value must satisfy — primarily consumed by form UIs to choose HTML5 ``, `inputmode`, and `autocomplete` attributes. Prefer HTML5 input type names when the field maps to one (`email`, `tel`, `url`, `date`, `datetime-local`, `time`, `number`, `password`); use semantic slugs for domain-specific formats that don't (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`). Treat unknown values as opaque — fall back to string validation with any accompanying `pattern` / `minLength` / `maxLength` constraints. + example: email pattern: type: string - description: Regular expression the value must match (JavaScript-flavor). + description: Regular expression the value must match (JavaScript-flavor). Length constraints (`minLength` / `maxLength`) are exposed separately so consumers can drive HTML5 `` attributes or perform plain length checks without evaluating a regex — encoding length inside `pattern` (e.g. `^.{3,10}$`) is valid but harder to consume. example: ^\d{5}(-\d{4})?$ enum: type: array @@ -11355,11 +11355,11 @@ components: - NON_US_TAX_ID minLength: type: integer - description: Minimum length in characters. + description: Minimum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to native controls directly. example: 1 maxLength: type: integer - description: Maximum length in characters. + description: Maximum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to `` directly. example: 500 Error400: type: object diff --git a/openapi.yaml b/openapi.yaml index 6e1cd7018..f08ead206 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -11334,15 +11334,15 @@ components: to subsequent delivery attempts. FieldConstraint: type: object - description: Machine-readable validator hint. Platforms use it to pre-validate their own onboarding form before submitting, and to render form UI (e.g., surface a dropdown for `enum`, mask input by `pattern`). + description: 'Machine-readable validator hint. Platforms use it to (a) pre-validate the end-user''s input on their onboarding form before submitting, and (b) drive form UI directly — HTML5 `` selection and `autocomplete` / `inputmode` / a11y attributes via `format`, dropdown menus via `enum`, input masking via `pattern`, native length limits via `minLength` / `maxLength`. Fields are additive; a single constraint may set several (e.g. `format: email` + `maxLength: 254`). Grid emits only constraints it enforces server-side.' properties: format: type: string - description: 'Named format the value must satisfy. Examples: `date`, `email`, `iso3166-1-alpha-2`, `bcp47-language-tag`.' - example: iso3166-1-alpha-2 + description: Named format the value must satisfy — primarily consumed by form UIs to choose HTML5 ``, `inputmode`, and `autocomplete` attributes. Prefer HTML5 input type names when the field maps to one (`email`, `tel`, `url`, `date`, `datetime-local`, `time`, `number`, `password`); use semantic slugs for domain-specific formats that don't (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`). Treat unknown values as opaque — fall back to string validation with any accompanying `pattern` / `minLength` / `maxLength` constraints. + example: email pattern: type: string - description: Regular expression the value must match (JavaScript-flavor). + description: Regular expression the value must match (JavaScript-flavor). Length constraints (`minLength` / `maxLength`) are exposed separately so consumers can drive HTML5 `` attributes or perform plain length checks without evaluating a regex — encoding length inside `pattern` (e.g. `^.{3,10}$`) is valid but harder to consume. example: ^\d{5}(-\d{4})?$ enum: type: array @@ -11355,11 +11355,11 @@ components: - NON_US_TAX_ID minLength: type: integer - description: Minimum length in characters. + description: Minimum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to native controls directly. example: 1 maxLength: type: integer - description: Maximum length in characters. + description: Maximum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to `` directly. example: 500 Error400: type: object diff --git a/openapi/components/schemas/errors/FieldConstraint.yaml b/openapi/components/schemas/errors/FieldConstraint.yaml index 8541c18a2..7f7fdb96a 100644 --- a/openapi/components/schemas/errors/FieldConstraint.yaml +++ b/openapi/components/schemas/errors/FieldConstraint.yaml @@ -1,18 +1,35 @@ type: object description: >- - Machine-readable validator hint. Platforms use it to pre-validate their own - onboarding form before submitting, and to render form UI (e.g., surface a - dropdown for `enum`, mask input by `pattern`). + Machine-readable validator hint. Platforms use it to (a) pre-validate the + end-user's input on their onboarding form before submitting, and (b) drive + form UI directly — HTML5 `` selection and `autocomplete` / + `inputmode` / a11y attributes via `format`, dropdown menus via `enum`, + input masking via `pattern`, native length limits via `minLength` / + `maxLength`. Fields are additive; a single constraint may set several + (e.g. `format: email` + `maxLength: 254`). Grid emits only constraints + it enforces server-side. properties: format: type: string description: >- - Named format the value must satisfy. Examples: `date`, `email`, `iso3166-1-alpha-2`, - `bcp47-language-tag`. - example: iso3166-1-alpha-2 + Named format the value must satisfy — primarily consumed by form UIs + to choose HTML5 ``, `inputmode`, and `autocomplete` + attributes. Prefer HTML5 input type names when the field maps to one + (`email`, `tel`, `url`, `date`, `datetime-local`, `time`, `number`, + `password`); use semantic slugs for domain-specific formats that + don't (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, + `e.164`). Treat unknown values as opaque — fall back to string + validation with any accompanying `pattern` / `minLength` / + `maxLength` constraints. + example: email pattern: type: string - description: Regular expression the value must match (JavaScript-flavor). + description: >- + Regular expression the value must match (JavaScript-flavor). Length + constraints (`minLength` / `maxLength`) are exposed separately so + consumers can drive HTML5 `` attributes or perform + plain length checks without evaluating a regex — encoding length + inside `pattern` (e.g. `^.{3,10}$`) is valid but harder to consume. example: ^\d{5}(-\d{4})?$ enum: type: array @@ -25,9 +42,15 @@ properties: - NON_US_TAX_ID minLength: type: integer - description: Minimum length in characters. + description: >- + Minimum length in characters. Exposed as a distinct field (rather + than folded into `pattern`) so form UIs can wire it to native + controls directly. example: 1 maxLength: type: integer - description: Maximum length in characters. + description: >- + Maximum length in characters. Exposed as a distinct field (rather + than folded into `pattern`) so form UIs can wire it to + `` directly. example: 500 From 8652bd535f38117baa6d4e500c473a95bcbf4bb0 Mon Sep 17 00:00:00 2001 From: Aaron Kanter Date: Fri, 24 Jul 2026 17:01:53 +0000 Subject: [PATCH 3/6] grid-api#726 R12: flatten taxIdentification to top-level taxIdType/taxIdentifier/taxIdCountryOfIssuance (@akanter direction, Stripe-style) --- mintlify/openapi.yaml | 52 ++++++++++--------- openapi.yaml | 52 ++++++++++--------- .../schemas/customers/CustomerEdd.yaml | 12 +++++ .../customers/IndividualCustomerFields.yaml | 17 +++++- .../schemas/customers/TaxIdentification.yaml | 20 ------- .../components/schemas/errors/Error400.yaml | 2 +- .../schemas/errors/FieldConstraint.yaml | 41 ++++----------- 7 files changed, 94 insertions(+), 102 deletions(-) delete mode 100644 openapi/components/schemas/customers/TaxIdentification.yaml diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index f08ead206..678aa237e 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -11334,15 +11334,15 @@ components: to subsequent delivery attempts. FieldConstraint: type: object - description: 'Machine-readable validator hint. Platforms use it to (a) pre-validate the end-user''s input on their onboarding form before submitting, and (b) drive form UI directly — HTML5 `` selection and `autocomplete` / `inputmode` / a11y attributes via `format`, dropdown menus via `enum`, input masking via `pattern`, native length limits via `minLength` / `maxLength`. Fields are additive; a single constraint may set several (e.g. `format: email` + `maxLength: 254`). Grid emits only constraints it enforces server-side.' + 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 — primarily consumed by form UIs to choose HTML5 ``, `inputmode`, and `autocomplete` attributes. Prefer HTML5 input type names when the field maps to one (`email`, `tel`, `url`, `date`, `datetime-local`, `time`, `number`, `password`); use semantic slugs for domain-specific formats that don't (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`). Treat unknown values as opaque — fall back to string validation with any accompanying `pattern` / `minLength` / `maxLength` constraints. + 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). Length constraints (`minLength` / `maxLength`) are exposed separately so consumers can drive HTML5 `` attributes or perform plain length checks without evaluating a regex — encoding length inside `pattern` (e.g. `^.{3,10}$`) is valid but harder to consume. + description: Regular expression the value must match (JavaScript-flavor). example: ^\d{5}(-\d{4})?$ enum: type: array @@ -11355,11 +11355,11 @@ components: - NON_US_TAX_ID minLength: type: integer - description: Minimum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to native controls directly. + description: Minimum length in characters. example: 1 maxLength: type: integer - description: Maximum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to `` directly. + description: Maximum length in characters. example: 500 Error400: type: object @@ -11467,7 +11467,7 @@ components: field: type: string description: Dot-notation path to the offending field. Present on field-validation errors from submit endpoints. - example: taxIdentification.identifier + example: taxIdentifier constraint: $ref: '#/components/schemas/FieldConstraint' additionalProperties: true @@ -11804,22 +11804,6 @@ components: - NON_US_TAX_ID description: Type of tax identification example: SSN - TaxIdentification: - type: object - required: - - idType - - identifier - properties: - idType: - $ref: '#/components/schemas/IdentificationType' - identifier: - type: string - description: The tax-identification number. For US persons this is the SSN (format `###-##-####`) or ITIN. For non-US persons this is the tax number issued by `countryOfIssuance`. - example: 123-45-6789 - countryOfIssuance: - type: string - description: Country that issued the tax identifier (ISO 3166-1 alpha-2). Required when `idType` is `NON_US_TAX_ID`. - example: US IndividualCustomerFields: type: object required: @@ -11846,8 +11830,16 @@ components: example: US address: $ref: '#/components/schemas/Address' - taxIdentification: - $ref: '#/components/schemas/TaxIdentification' + 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 IndividualCustomer: title: Individual Customer allOf: @@ -12680,6 +12672,18 @@ components: $ref: '#/components/schemas/NetWorthRange' pepStatus: $ref: '#/components/schemas/PepStatus' + createdAt: + type: string + format: date-time + description: Creation timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' Error404: type: object required: diff --git a/openapi.yaml b/openapi.yaml index f08ead206..678aa237e 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -11334,15 +11334,15 @@ components: to subsequent delivery attempts. FieldConstraint: type: object - description: 'Machine-readable validator hint. Platforms use it to (a) pre-validate the end-user''s input on their onboarding form before submitting, and (b) drive form UI directly — HTML5 `` selection and `autocomplete` / `inputmode` / a11y attributes via `format`, dropdown menus via `enum`, input masking via `pattern`, native length limits via `minLength` / `maxLength`. Fields are additive; a single constraint may set several (e.g. `format: email` + `maxLength: 254`). Grid emits only constraints it enforces server-side.' + 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 — primarily consumed by form UIs to choose HTML5 ``, `inputmode`, and `autocomplete` attributes. Prefer HTML5 input type names when the field maps to one (`email`, `tel`, `url`, `date`, `datetime-local`, `time`, `number`, `password`); use semantic slugs for domain-specific formats that don't (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`). Treat unknown values as opaque — fall back to string validation with any accompanying `pattern` / `minLength` / `maxLength` constraints. + 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). Length constraints (`minLength` / `maxLength`) are exposed separately so consumers can drive HTML5 `` attributes or perform plain length checks without evaluating a regex — encoding length inside `pattern` (e.g. `^.{3,10}$`) is valid but harder to consume. + description: Regular expression the value must match (JavaScript-flavor). example: ^\d{5}(-\d{4})?$ enum: type: array @@ -11355,11 +11355,11 @@ components: - NON_US_TAX_ID minLength: type: integer - description: Minimum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to native controls directly. + description: Minimum length in characters. example: 1 maxLength: type: integer - description: Maximum length in characters. Exposed as a distinct field (rather than folded into `pattern`) so form UIs can wire it to `` directly. + description: Maximum length in characters. example: 500 Error400: type: object @@ -11467,7 +11467,7 @@ components: field: type: string description: Dot-notation path to the offending field. Present on field-validation errors from submit endpoints. - example: taxIdentification.identifier + example: taxIdentifier constraint: $ref: '#/components/schemas/FieldConstraint' additionalProperties: true @@ -11804,22 +11804,6 @@ components: - NON_US_TAX_ID description: Type of tax identification example: SSN - TaxIdentification: - type: object - required: - - idType - - identifier - properties: - idType: - $ref: '#/components/schemas/IdentificationType' - identifier: - type: string - description: The tax-identification number. For US persons this is the SSN (format `###-##-####`) or ITIN. For non-US persons this is the tax number issued by `countryOfIssuance`. - example: 123-45-6789 - countryOfIssuance: - type: string - description: Country that issued the tax identifier (ISO 3166-1 alpha-2). Required when `idType` is `NON_US_TAX_ID`. - example: US IndividualCustomerFields: type: object required: @@ -11846,8 +11830,16 @@ components: example: US address: $ref: '#/components/schemas/Address' - taxIdentification: - $ref: '#/components/schemas/TaxIdentification' + 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 IndividualCustomer: title: Individual Customer allOf: @@ -12680,6 +12672,18 @@ components: $ref: '#/components/schemas/NetWorthRange' pepStatus: $ref: '#/components/schemas/PepStatus' + createdAt: + type: string + format: date-time + description: Creation timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' Error404: type: object required: diff --git a/openapi/components/schemas/customers/CustomerEdd.yaml b/openapi/components/schemas/customers/CustomerEdd.yaml index 62e84034e..3e88d5edd 100644 --- a/openapi/components/schemas/customers/CustomerEdd.yaml +++ b/openapi/components/schemas/customers/CustomerEdd.yaml @@ -50,3 +50,15 @@ properties: $ref: ./NetWorthRange.yaml pepStatus: $ref: ./PepStatus.yaml + createdAt: + type: string + format: date-time + description: Creation timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' diff --git a/openapi/components/schemas/customers/IndividualCustomerFields.yaml b/openapi/components/schemas/customers/IndividualCustomerFields.yaml index 6519ca508..1b2bde21d 100644 --- a/openapi/components/schemas/customers/IndividualCustomerFields.yaml +++ b/openapi/components/schemas/customers/IndividualCustomerFields.yaml @@ -23,5 +23,18 @@ properties: example: US address: $ref: ../common/Address.yaml - taxIdentification: - $ref: ./TaxIdentification.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 diff --git a/openapi/components/schemas/customers/TaxIdentification.yaml b/openapi/components/schemas/customers/TaxIdentification.yaml deleted file mode 100644 index 3c1ef6945..000000000 --- a/openapi/components/schemas/customers/TaxIdentification.yaml +++ /dev/null @@ -1,20 +0,0 @@ -type: object -required: - - idType - - identifier -properties: - idType: - $ref: ./IdentificationType.yaml - identifier: - type: string - description: >- - The tax-identification number. For US persons this is the SSN (format - `###-##-####`) or ITIN. For non-US persons this is the tax number issued - by `countryOfIssuance`. - example: 123-45-6789 - countryOfIssuance: - type: string - description: >- - Country that issued the tax identifier (ISO 3166-1 alpha-2). Required - when `idType` is `NON_US_TAX_ID`. - example: US diff --git a/openapi/components/schemas/errors/Error400.yaml b/openapi/components/schemas/errors/Error400.yaml index 77a443959..89ecc8b17 100644 --- a/openapi/components/schemas/errors/Error400.yaml +++ b/openapi/components/schemas/errors/Error400.yaml @@ -110,7 +110,7 @@ properties: description: >- Dot-notation path to the offending field. Present on field-validation errors from submit endpoints. - example: taxIdentification.identifier + example: taxIdentifier constraint: $ref: ./FieldConstraint.yaml additionalProperties: true diff --git a/openapi/components/schemas/errors/FieldConstraint.yaml b/openapi/components/schemas/errors/FieldConstraint.yaml index 7f7fdb96a..547c82525 100644 --- a/openapi/components/schemas/errors/FieldConstraint.yaml +++ b/openapi/components/schemas/errors/FieldConstraint.yaml @@ -1,35 +1,20 @@ type: object description: >- - Machine-readable validator hint. Platforms use it to (a) pre-validate the - end-user's input on their onboarding form before submitting, and (b) drive - form UI directly — HTML5 `` selection and `autocomplete` / - `inputmode` / a11y attributes via `format`, dropdown menus via `enum`, - input masking via `pattern`, native length limits via `minLength` / - `maxLength`. Fields are additive; a single constraint may set several - (e.g. `format: email` + `maxLength: 254`). Grid emits only constraints - it enforces server-side. + 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 — primarily consumed by form UIs - to choose HTML5 ``, `inputmode`, and `autocomplete` - attributes. Prefer HTML5 input type names when the field maps to one - (`email`, `tel`, `url`, `date`, `datetime-local`, `time`, `number`, - `password`); use semantic slugs for domain-specific formats that - don't (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, - `e.164`). Treat unknown values as opaque — fall back to string - validation with any accompanying `pattern` / `minLength` / - `maxLength` constraints. + 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). Length - constraints (`minLength` / `maxLength`) are exposed separately so - consumers can drive HTML5 `` attributes or perform - plain length checks without evaluating a regex — encoding length - inside `pattern` (e.g. `^.{3,10}$`) is valid but harder to consume. + description: Regular expression the value must match (JavaScript-flavor). example: ^\d{5}(-\d{4})?$ enum: type: array @@ -42,15 +27,9 @@ properties: - NON_US_TAX_ID minLength: type: integer - description: >- - Minimum length in characters. Exposed as a distinct field (rather - than folded into `pattern`) so form UIs can wire it to native - controls directly. + description: Minimum length in characters. example: 1 maxLength: type: integer - description: >- - Maximum length in characters. Exposed as a distinct field (rather - than folded into `pattern`) so form UIs can wire it to - `` directly. + description: Maximum length in characters. example: 500 From 770f16b96719d6cd41219737e8b92cf7ffada94d Mon Sep 17 00:00:00 2001 From: Aaron Kanter Date: Fri, 24 Jul 2026 20:29:30 +0000 Subject: [PATCH 4/6] grid-api#726 R13: switch /customers/edd to /customers/{customerId}/edd (pathParam nesting per @akanter direction) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restful pathParam nesting matches shreyav's and jklein24's inclination: - Renamed openapi/paths/customers/customers_edd.yaml → customers_{customerId}_edd.yaml - Added path-level customerId path parameter (inherited by GET/POST/PATCH) - Removed per-operation customerId query parameter - Deleted CustomerEddCreateRequest.yaml (customerId no longer in body; CustomerEdd.yaml is now the POST request body directly) - openapi/openapi.yaml: path key /customers/edd -> /customers/{customerId}/edd, grouped with other /customers/{customerId}/... subresources Composes naturally to /transactions/{id}/edd if we ever ship transaction-EDD. --- mintlify/openapi.yaml | 717 +++++++++--------- openapi.yaml | 717 +++++++++--------- .../customers/CustomerEddCreateRequest.yaml | 13 - openapi/openapi.yaml | 4 +- ...d.yaml => customers_{customerId}_edd.yaml} | 23 +- 5 files changed, 708 insertions(+), 766 deletions(-) delete mode 100644 openapi/components/schemas/customers/CustomerEddCreateRequest.yaml rename openapi/paths/customers/{customers_edd.yaml => customers_{customerId}_edd.yaml} (90%) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 678aa237e..05ba36606 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -594,150 +594,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/edd: - get: - summary: Get a customer's enhanced-due-diligence (EDD) fields - description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. - operationId: getCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - parameters: - - name: customerId - in: query - description: The Grid customer ID to retrieve EDD data for. - required: true - schema: - type: string - responses: - '200': - description: EDD payload retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - Invalid parameters - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded for this customer - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - post: - summary: Create or replace a customer's enhanced-due-diligence (EDD) fields - description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. - operationId: createCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEddCreateRequest' - responses: - '200': - description: EDD payload created or replaced successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - 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' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - patch: - summary: Partially update a customer's enhanced-due-diligence (EDD) fields - description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. - operationId: updateCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - parameters: - - name: customerId - in: query - description: The Grid customer ID whose EDD data is being updated. - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - responses: - '200': - description: EDD payload updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded to update - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' /customers/{customerId}: parameters: - name: customerId @@ -970,51 +826,31 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/kyc-link: + /customers/{customerId}/edd: parameters: - name: customerId in: path - description: The Grid customer ID to generate a KYC link for. + description: The Grid customer ID. required: true schema: type: string - post: - summary: Generate a hosted KYC link for an existing customer - description: | - Generate a single-use hosted URL the customer can complete to verify their identity, and (where supported) a provider-specific `token` for embedding the verification flow directly via the provider's SDK. - - The customer must already exist — create them with `POST /customers` first. Calling this endpoint does not change the customer's `kycStatus`; the customer remains `PENDING` until they complete (or fail) the hosted flow. - - Each call returns a fresh link. Previously-issued links are not invalidated, but they remain single-use and will expire on their own. For request-level retry safety, include an `Idempotency-Key` header. - operationId: createCustomerKycLink + get: + summary: Get a customer's enhanced-due-diligence (EDD) fields + description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. + operationId: getCustomerEdd tags: - KYC/KYB Verifications security: - BasicAuth: [] - parameters: - - name: Idempotency-Key - in: header - required: false - description: | - A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. - schema: - type: string - example: - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/KycLinkCreateRequest' responses: - '201': - description: KYC link generated + '200': + description: EDD payload retrieved successfully content: application/json: schema: - $ref: '#/components/schemas/KycLinkResponse' + $ref: '#/components/schemas/CustomerEdd' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: @@ -1026,54 +862,44 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Customer not found + description: Customer not found or no EDD data recorded for this customer content: 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: 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 + summary: Create or replace a customer's enhanced-due-diligence (EDD) fields + description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. + operationId: createCustomerEdd tags: - - Contact Verification + - KYC/KYB Verifications security: - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' responses: - '204': - description: Verification code sent. + '200': + description: EDD payload created or replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' '401': description: Unauthorized content: @@ -1086,26 +912,193 @@ paths: 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' '500': description: Internal service error content: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/verify-email/confirm: - parameters: - - name: customerId - in: path - description: The Grid customer ID whose email is being verified. + patch: + summary: Partially update a customer's enhanced-due-diligence (EDD) fields + description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. + operationId: updateCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + requestBody: required: true - schema: - type: string + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + responses: + '200': + description: EDD payload updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found or no EDD data recorded to update + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /customers/{customerId}/kyc-link: + parameters: + - name: customerId + in: path + description: The Grid customer ID to generate a KYC link for. + required: true + schema: + type: string + post: + summary: Generate a hosted KYC link for an existing customer + description: | + Generate a single-use hosted URL the customer can complete to verify their identity, and (where supported) a provider-specific `token` for embedding the verification flow directly via the provider's SDK. + + The customer must already exist — create them with `POST /customers` first. Calling this endpoint does not change the customer's `kycStatus`; the customer remains `PENDING` until they complete (or fail) the hosted flow. + + Each call returns a fresh link. Previously-issued links are not invalidated, but they remain single-use and will expire on their own. For request-level retry safety, include an `Idempotency-Key` header. + operationId: createCustomerKycLink + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/KycLinkCreateRequest' + responses: + '201': + description: KYC link generated + content: + application/json: + schema: + $ref: '#/components/schemas/KycLinkResponse' + '400': + description: Bad request + 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 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: + 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' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /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: | @@ -12548,142 +12541,6 @@ components: type: object description: Additional error details additionalProperties: true - 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 - 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 - description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' - 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: '#/components/schemas/SourceOfWealthCategory' - 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: '#/components/schemas/PurposeOfAccount' - 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: '#/components/schemas/ExpectedMonthlyTransactionCount' - expectedMonthlyTransactionVolume: - $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' - annualIncomeRange: - $ref: '#/components/schemas/AnnualIncomeRange' - netWorthRange: - $ref: '#/components/schemas/NetWorthRange' - pepStatus: - $ref: '#/components/schemas/PepStatus' - createdAt: - type: string - format: date-time - description: Creation timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' - updatedAt: - type: string - format: date-time - description: Last update timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' Error404: type: object required: @@ -12729,18 +12586,6 @@ components: type: object description: Additional error details additionalProperties: true - CustomerEddCreateRequest: - description: Request body for `POST /customers/edd`. Composes the full `CustomerEdd` field set and adds the required `customerId` link. - allOf: - - $ref: '#/components/schemas/CustomerEdd' - - type: object - required: - - customerId - properties: - customerId: - type: string - description: The Grid customer ID whose EDD data is being created or replaced. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 Error410: type: object required: @@ -12876,6 +12721,142 @@ components: type: object description: Additional error details additionalProperties: true + 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 + 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 + description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' + 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: '#/components/schemas/SourceOfWealthCategory' + 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: '#/components/schemas/PurposeOfAccount' + 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: '#/components/schemas/ExpectedMonthlyTransactionCount' + expectedMonthlyTransactionVolume: + $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' + annualIncomeRange: + $ref: '#/components/schemas/AnnualIncomeRange' + netWorthRange: + $ref: '#/components/schemas/NetWorthRange' + pepStatus: + $ref: '#/components/schemas/PepStatus' + createdAt: + type: string + format: date-time + description: Creation timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' KycLinkCreateRequest: type: object description: Request body for generating a hosted KYC link for an existing customer. diff --git a/openapi.yaml b/openapi.yaml index 678aa237e..05ba36606 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -594,150 +594,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/edd: - get: - summary: Get a customer's enhanced-due-diligence (EDD) fields - description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. - operationId: getCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - parameters: - - name: customerId - in: query - description: The Grid customer ID to retrieve EDD data for. - required: true - schema: - type: string - responses: - '200': - description: EDD payload retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - Invalid parameters - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded for this customer - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - post: - summary: Create or replace a customer's enhanced-due-diligence (EDD) fields - description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. - operationId: createCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEddCreateRequest' - responses: - '200': - description: EDD payload created or replaced successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - 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' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - patch: - summary: Partially update a customer's enhanced-due-diligence (EDD) fields - description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. - operationId: updateCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - parameters: - - name: customerId - in: query - description: The Grid customer ID whose EDD data is being updated. - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - responses: - '200': - description: EDD payload updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded to update - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' /customers/{customerId}: parameters: - name: customerId @@ -970,51 +826,31 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/kyc-link: + /customers/{customerId}/edd: parameters: - name: customerId in: path - description: The Grid customer ID to generate a KYC link for. + description: The Grid customer ID. required: true schema: type: string - post: - summary: Generate a hosted KYC link for an existing customer - description: | - Generate a single-use hosted URL the customer can complete to verify their identity, and (where supported) a provider-specific `token` for embedding the verification flow directly via the provider's SDK. - - The customer must already exist — create them with `POST /customers` first. Calling this endpoint does not change the customer's `kycStatus`; the customer remains `PENDING` until they complete (or fail) the hosted flow. - - Each call returns a fresh link. Previously-issued links are not invalidated, but they remain single-use and will expire on their own. For request-level retry safety, include an `Idempotency-Key` header. - operationId: createCustomerKycLink + get: + summary: Get a customer's enhanced-due-diligence (EDD) fields + description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. + operationId: getCustomerEdd tags: - KYC/KYB Verifications security: - BasicAuth: [] - parameters: - - name: Idempotency-Key - in: header - required: false - description: | - A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. - schema: - type: string - example: - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/KycLinkCreateRequest' responses: - '201': - description: KYC link generated + '200': + description: EDD payload retrieved successfully content: application/json: schema: - $ref: '#/components/schemas/KycLinkResponse' + $ref: '#/components/schemas/CustomerEdd' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: @@ -1026,54 +862,44 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Customer not found + description: Customer not found or no EDD data recorded for this customer content: 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: 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 + summary: Create or replace a customer's enhanced-due-diligence (EDD) fields + description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. + operationId: createCustomerEdd tags: - - Contact Verification + - KYC/KYB Verifications security: - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' responses: - '204': - description: Verification code sent. + '200': + description: EDD payload created or replaced successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' '401': description: Unauthorized content: @@ -1086,26 +912,193 @@ paths: 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' '500': description: Internal service error content: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/verify-email/confirm: - parameters: - - name: customerId - in: path - description: The Grid customer ID whose email is being verified. + patch: + summary: Partially update a customer's enhanced-due-diligence (EDD) fields + description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. + operationId: updateCustomerEdd + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + requestBody: required: true - schema: - type: string + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + responses: + '200': + description: EDD payload updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerEdd' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer not found or no EDD data recorded to update + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /customers/{customerId}/kyc-link: + parameters: + - name: customerId + in: path + description: The Grid customer ID to generate a KYC link for. + required: true + schema: + type: string + post: + summary: Generate a hosted KYC link for an existing customer + description: | + Generate a single-use hosted URL the customer can complete to verify their identity, and (where supported) a provider-specific `token` for embedding the verification flow directly via the provider's SDK. + + The customer must already exist — create them with `POST /customers` first. Calling this endpoint does not change the customer's `kycStatus`; the customer remains `PENDING` until they complete (or fail) the hosted flow. + + Each call returns a fresh link. Previously-issued links are not invalidated, but they remain single-use and will expire on their own. For request-level retry safety, include an `Idempotency-Key` header. + operationId: createCustomerKycLink + tags: + - KYC/KYB Verifications + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/KycLinkCreateRequest' + responses: + '201': + description: KYC link generated + content: + application/json: + schema: + $ref: '#/components/schemas/KycLinkResponse' + '400': + description: Bad request + 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 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: + 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' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /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: | @@ -12548,142 +12541,6 @@ components: type: object description: Additional error details additionalProperties: true - 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 - 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 - description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' - 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: '#/components/schemas/SourceOfWealthCategory' - 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: '#/components/schemas/PurposeOfAccount' - 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: '#/components/schemas/ExpectedMonthlyTransactionCount' - expectedMonthlyTransactionVolume: - $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' - annualIncomeRange: - $ref: '#/components/schemas/AnnualIncomeRange' - netWorthRange: - $ref: '#/components/schemas/NetWorthRange' - pepStatus: - $ref: '#/components/schemas/PepStatus' - createdAt: - type: string - format: date-time - description: Creation timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' - updatedAt: - type: string - format: date-time - description: Last update timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' Error404: type: object required: @@ -12729,18 +12586,6 @@ components: type: object description: Additional error details additionalProperties: true - CustomerEddCreateRequest: - description: Request body for `POST /customers/edd`. Composes the full `CustomerEdd` field set and adds the required `customerId` link. - allOf: - - $ref: '#/components/schemas/CustomerEdd' - - type: object - required: - - customerId - properties: - customerId: - type: string - description: The Grid customer ID whose EDD data is being created or replaced. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 Error410: type: object required: @@ -12876,6 +12721,142 @@ components: type: object description: Additional error details additionalProperties: true + 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 + 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 + description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' + 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: '#/components/schemas/SourceOfWealthCategory' + 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: '#/components/schemas/PurposeOfAccount' + 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: '#/components/schemas/ExpectedMonthlyTransactionCount' + expectedMonthlyTransactionVolume: + $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' + annualIncomeRange: + $ref: '#/components/schemas/AnnualIncomeRange' + netWorthRange: + $ref: '#/components/schemas/NetWorthRange' + pepStatus: + $ref: '#/components/schemas/PepStatus' + createdAt: + type: string + format: date-time + description: Creation timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + readOnly: true + example: '2026-07-24T17:32:28Z' KycLinkCreateRequest: type: object description: Request body for generating a hosted KYC link for an existing customer. diff --git a/openapi/components/schemas/customers/CustomerEddCreateRequest.yaml b/openapi/components/schemas/customers/CustomerEddCreateRequest.yaml deleted file mode 100644 index ea2db277a..000000000 --- a/openapi/components/schemas/customers/CustomerEddCreateRequest.yaml +++ /dev/null @@ -1,13 +0,0 @@ -description: >- - Request body for `POST /customers/edd`. Composes the full `CustomerEdd` - field set and adds the required `customerId` link. -allOf: - - $ref: ./CustomerEdd.yaml - - type: object - required: - - customerId - properties: - customerId: - type: string - description: The Grid customer ID whose EDD data is being created or replaced. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 33ca1e02f..fa67281ab 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -141,10 +141,10 @@ paths: $ref: paths/discoveries/discoveries.yaml /customers: $ref: paths/customers/customers.yaml - /customers/edd: - $ref: paths/customers/customers_edd.yaml /customers/{customerId}: $ref: paths/customers/customers_{customerId}.yaml + /customers/{customerId}/edd: + $ref: paths/customers/customers_{customerId}_edd.yaml /customers/{customerId}/kyc-link: $ref: paths/customers/customers_{customerId}_kyc-link.yaml /customers/{customerId}/verify-email: diff --git a/openapi/paths/customers/customers_edd.yaml b/openapi/paths/customers/customers_{customerId}_edd.yaml similarity index 90% rename from openapi/paths/customers/customers_edd.yaml rename to openapi/paths/customers/customers_{customerId}_edd.yaml index 8dcde2e71..6cb34cc09 100644 --- a/openapi/paths/customers/customers_edd.yaml +++ b/openapi/paths/customers/customers_{customerId}_edd.yaml @@ -1,3 +1,10 @@ +parameters: + - name: customerId + in: path + description: The Grid customer ID. + required: true + schema: + type: string get: summary: Get a customer's enhanced-due-diligence (EDD) fields description: >- @@ -8,13 +15,6 @@ get: - KYC/KYB Verifications security: - BasicAuth: [] - parameters: - - name: customerId - in: query - description: The Grid customer ID to retrieve EDD data for. - required: true - schema: - type: string responses: '200': description: EDD payload retrieved successfully @@ -63,7 +63,7 @@ post: content: application/json: schema: - $ref: ../../components/schemas/customers/CustomerEddCreateRequest.yaml + $ref: ../../components/schemas/customers/CustomerEdd.yaml responses: '200': description: EDD payload created or replaced successfully @@ -105,13 +105,6 @@ patch: - KYC/KYB Verifications security: - BasicAuth: [] - parameters: - - name: customerId - in: query - description: The Grid customer ID whose EDD data is being updated. - required: true - schema: - type: string requestBody: required: true content: From f4117e107da0705f463fda1f4e30d42ceb75f100 Mon Sep 17 00:00:00 2001 From: Aaron Kanter Date: Fri, 24 Jul 2026 20:30:33 +0000 Subject: [PATCH 5/6] R13 followup: update Error400 description to reference /customers/{id}/edd --- mintlify/openapi.yaml | 2 +- openapi.yaml | 2 +- openapi/components/schemas/errors/Error400.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 05ba36606..0a5cfab91 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -11455,7 +11455,7 @@ components: description: Error message details: type: object - description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, `POST /customers/edd`, `PATCH /customers/edd`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting. + description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, `POST /customers/{id}/edd`, `PATCH /customers/{id}/edd`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting. properties: field: type: string diff --git a/openapi.yaml b/openapi.yaml index 05ba36606..0a5cfab91 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -11455,7 +11455,7 @@ components: description: Error message details: type: object - description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, `POST /customers/edd`, `PATCH /customers/edd`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting. + description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, `POST /customers/{id}/edd`, `PATCH /customers/{id}/edd`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting. properties: field: type: string diff --git a/openapi/components/schemas/errors/Error400.yaml b/openapi/components/schemas/errors/Error400.yaml index 89ecc8b17..3839dd840 100644 --- a/openapi/components/schemas/errors/Error400.yaml +++ b/openapi/components/schemas/errors/Error400.yaml @@ -101,7 +101,7 @@ properties: description: >- Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, - `POST /customers/edd`, `PATCH /customers/edd`), `details.field` and + `POST /customers/{id}/edd`, `PATCH /customers/{id}/edd`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting. properties: From af730cd5c2eadc9c43ff63bac2f3a11f9785423c Mon Sep 17 00:00:00 2001 From: Aaron Kanter Date: Mon, 27 Jul 2026 22:15:00 +0000 Subject: [PATCH 6/6] grid-api#726 R14: EDD fields on Customer resource (drop separate /customers/{id}/edd endpoint) @akanter's landed direction after design discussion + 8-vendor competitive research (BaaS precedent unanimous: Stripe/Bridge/Unit all put EDD on the customer resource). - Delete openapi/paths/customers/customers_{customerId}_edd.yaml (was R13's endpoint file) - Remove /customers/{customerId}/edd path key from openapi/openapi.yaml - IndividualCustomerFields.yaml: restructure to allOf composition with CustomerEdd.yaml, so the 11 EDD fields (SoF, SoW, PEP, income, net worth, purpose, txn volume/count, plus 3 *OtherDescription companions) become optional top-level attributes on the customer - CustomerEdd.yaml: drop createdAt/updatedAt (no longer a resource; Customer's own timestamps suffice); update description to reflect the new pattern - Error400.yaml: drop /customers/{id}/edd from submit-endpoints example list API surface != DB schema: sparkcore-side still keeps EntUmaaasCustomerEdd as a separate 1:1-nullable table to avoid NULL bloat on IndividualUserInfo; only customers who submit EDD get a row. See webdev#31107 PR A rework for the sparkcore-side change. --- mintlify/openapi.yaml | 690 ++++++++---------- openapi.yaml | 690 ++++++++---------- .../schemas/customers/CustomerEdd.yaml | 23 +- .../customers/IndividualCustomerFields.yaml | 82 ++- .../components/schemas/errors/Error400.yaml | 7 +- openapi/openapi.yaml | 2 - .../customers/customers_{customerId}_edd.yaml | 144 ---- 7 files changed, 660 insertions(+), 978 deletions(-) delete mode 100644 openapi/paths/customers/customers_{customerId}_edd.yaml diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 0a5cfab91..90378beb6 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -826,143 +826,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/edd: - parameters: - - name: customerId - in: path - description: The Grid customer ID. - required: true - schema: - type: string - get: - summary: Get a customer's enhanced-due-diligence (EDD) fields - description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. - operationId: getCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - responses: - '200': - description: EDD payload retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - Invalid parameters - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded for this customer - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - post: - summary: Create or replace a customer's enhanced-due-diligence (EDD) fields - description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. - operationId: createCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - responses: - '200': - description: EDD payload created or replaced successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - 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' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - patch: - summary: Partially update a customer's enhanced-due-diligence (EDD) fields - description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. - operationId: updateCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - responses: - '200': - description: EDD payload updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded to update - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' /customers/{customerId}/kyc-link: parameters: - name: customerId @@ -3824,6 +3687,7 @@ paths: totalReceivingAmount: 9200 exchangeRate: 0.92 feesIncluded: 10 + platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000005 '202': description: | @@ -9502,6 +9366,7 @@ webhooks: totalReceivingAmount: 4625000 exchangeRate: 92.5 feesIncluded: 250 + platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 createdAt: '2025-10-03T15:00:00Z' updatedAt: '2025-10-03T15:00:00Z' @@ -11173,6 +11038,73 @@ components: $ref: '#/components/schemas/CardTokenization2FAEmailConfig' sms: $ref: '#/components/schemas/CardTokenization2FASmsConfig' + FeeType: + type: string + enum: + - CROSS_CURRENCY_TRANSACTION + description: | + The kind of activity this fee applies to. + + - `CROSS_CURRENCY_TRANSACTION` — fee charged on a cross-currency Grid transaction + (source currency differs from destination currency). + example: CROSS_CURRENCY_TRANSACTION + Currency: + type: object + properties: + code: + type: string + description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) + example: USD + name: + type: string + description: Full name of the currency + example: United States Dollar + symbol: + type: string + description: Symbol of the currency + example: $ + decimals: + type: integer + description: Number of decimal places for the currency + minimum: 0 + example: 2 + CurrencyAmount: + type: object + required: + - amount + - currency + properties: + amount: + type: integer + format: int64 + description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) + example: 12550 + currency: + $ref: '#/components/schemas/Currency' + FeeConfig: + type: object + description: A platform-configured fee collected by Grid and settled to the platform internal account. There can be at most one fee config for a given fee type and source currency pair. The fee will apply to all transactions of the fee type that originate in the source currency. + properties: + feeType: + $ref: '#/components/schemas/FeeType' + sourceCurrency: + type: string + description: Currency code of the sending side this fee applies to. Only `USD` is accepted today; other currencies return a `NOT_IMPLEMENTED` error. + example: USD + variableFeeBps: + type: integer + minimum: 0 + maximum: 10000 + description: Variable fee in basis points (1 bps = 0.01%) to apply to a transaction's source-currency amount. + example: 30 + fixedFee: + $ref: '#/components/schemas/CurrencyAmount' + description: Fixed fee charged per transaction, in the smallest unit of the source currency. The fixed fee currency must match the fee config's `sourceCurrency`. + required: + - feeType + - sourceCurrency + - variableFeeBps + - fixedFee PlatformConfig: type: object properties: @@ -11219,6 +11151,14 @@ components: description: | Branding and sender configuration for card-tokenization authentication messages. This configuration is independent of embedded-wallet support. + feeConfigs: + type: array + items: + $ref: '#/components/schemas/FeeConfig' + description: | + Platform-collected fees that should be added on top of + Grid-collected fees. Contains every currently-active fee config + for the platform. createdAt: type: string format: date-time @@ -11325,6 +11265,15 @@ components: Update card-tokenization authentication branding and delivery settings. Fields omitted from the nested object are left unchanged. Changes apply to subsequent delivery attempts. + feeConfigs: + type: array + items: + $ref: '#/components/schemas/FeeConfig' + description: | + Merge-by-key upsert of platform fee configs, keyed by + `(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. @@ -11455,7 +11404,7 @@ components: description: Error message details: type: object - description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, `POST /customers/{id}/edd`, `PATCH /customers/{id}/edd`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting. + 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 @@ -11493,26 +11442,6 @@ components: type: object description: Additional error details additionalProperties: true - Currency: - type: object - properties: - code: - type: string - description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) - example: USD - name: - type: string - description: Full name of the currency - example: United States Dollar - symbol: - type: string - description: Symbol of the currency - example: $ - decimals: - type: integer - description: Number of decimal places for the currency - minimum: 0 - example: 2 PaymentRail: type: string enum: @@ -11797,69 +11726,213 @@ components: - NON_US_TAX_ID description: Type of tax identification example: SSN - IndividualCustomerFields: - 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 - IndividualCustomer: - title: Individual Customer - allOf: - - $ref: '#/components/schemas/Customer' - - $ref: '#/components/schemas/IndividualCustomerFields' - KybStatus: + IndividualSourceOfFundsCategory: type: string enum: - - UNVERIFIED - - PENDING - - APPROVED - - REJECTED - - HOLD - description: The current KYB status of a business customer. `HOLD` means the customer is placed on hold and may be required to update or provide more information. - example: APPROVED - EntityType: + - 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: - - SOLE_PROPRIETORSHIP - - PARTNERSHIP - - LLC - - CORPORATION - - S_CORPORATION - - NON_PROFIT - - OTHER - description: Legal entity type of the business - example: LLC + - 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 + 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: '#/components/schemas/IndividualSourceOfFundsCategory' + 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: '#/components/schemas/SourceOfWealthCategory' + 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: '#/components/schemas/PurposeOfAccount' + 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: '#/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: + - $ref: '#/components/schemas/Customer' + - $ref: '#/components/schemas/IndividualCustomerFields' + KybStatus: + type: string + enum: + - UNVERIFIED + - PENDING + - APPROVED + - REJECTED + - HOLD + description: The current KYB status of a business customer. `HOLD` means the customer is placed on hold and may be required to update or provide more information. + example: APPROVED + EntityType: + type: string + enum: + - SOLE_PROPRIETORSHIP + - PARTNERSHIP + - LLC + - CORPORATION + - S_CORPORATION + - NON_PROFIT + - OTHER + description: Legal entity type of the business + example: LLC BusinessType: type: string description: The high-level industry category of the business @@ -11884,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: @@ -12349,12 +12404,12 @@ components: email: type: string format: email - description: Email address for the customer. + description: Email address for the customer. **Required in regions that verify the email address before identity verification** (e.g. the EU); optional otherwise. example: john.doe@example.com phoneNumber: type: string pattern: ^\+[1-9]\d{1,14}$ - description: Phone number for the customer in strict E.164 format. + description: Phone number for the customer in strict E.164 format. **Required in regions that verify the phone number before identity verification** (e.g. the EU); optional otherwise. example: '+14155551234' umaAddress: type: string @@ -12721,142 +12776,6 @@ components: type: object description: Additional error details additionalProperties: true - 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 - 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 - description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' - 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: '#/components/schemas/SourceOfWealthCategory' - 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: '#/components/schemas/PurposeOfAccount' - 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: '#/components/schemas/ExpectedMonthlyTransactionCount' - expectedMonthlyTransactionVolume: - $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' - annualIncomeRange: - $ref: '#/components/schemas/AnnualIncomeRange' - netWorthRange: - $ref: '#/components/schemas/NetWorthRange' - pepStatus: - $ref: '#/components/schemas/PepStatus' - createdAt: - type: string - format: date-time - description: Creation timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' - updatedAt: - type: string - format: date-time - description: Last update timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' KycLinkCreateRequest: type: object description: Request body for generating a hosted KYC link for an existing customer. @@ -13583,19 +13502,6 @@ components: - `FROZEN`: The account cannot send or receive payments. Grid may freeze an account in response to compliance or fraud signals; payments are blocked while the account remains frozen. - `FAILED`: The account could not be provisioned. Grid was unable to create the underlying account, so it cannot send or receive payments and requires remediation. example: ACTIVE - CurrencyAmount: - type: object - required: - - amount - - currency - properties: - amount: - type: integer - format: int64 - description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) - example: 12550 - currency: - $ref: '#/components/schemas/Currency' PaymentAccountType: type: string enum: @@ -20505,6 +20411,12 @@ components: description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). minimum: 0 example: 10 + platformFees: + type: integer + format: int64 + description: The portion of `fees` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `fees`. + minimum: 0 + example: 5 reconciliationInstructions: $ref: '#/components/schemas/ReconciliationInstructions' description: Reconciliation details for this transaction. For the on-chain hash of a crypto payout to an external wallet, see the destination's `onChainTransaction` instead. @@ -21085,6 +20997,12 @@ components: description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' minimum: 0 example: 10 + platformFeesIncluded: + type: integer + format: int64 + description: The portion of `feesIncluded` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `feesIncluded`. May be omitted from payloads produced before platform fees existed. + minimum: 0 + example: 5 paymentInstructions: type: array description: Payment instructions for executing the payment. This is not required when using an internal account source. diff --git a/openapi.yaml b/openapi.yaml index 0a5cfab91..90378beb6 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -826,143 +826,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/edd: - parameters: - - name: customerId - in: path - description: The Grid customer ID. - required: true - schema: - type: string - get: - summary: Get a customer's enhanced-due-diligence (EDD) fields - description: Retrieve the EDD fields previously supplied for a customer. Returns `404` if no EDD data has been recorded for the customer yet. - operationId: getCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - responses: - '200': - description: EDD payload retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - Invalid parameters - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded for this customer - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - post: - summary: Create or replace a customer's enhanced-due-diligence (EDD) fields - description: Supply the EDD fields for a customer. Overwrites any previously recorded EDD data for that customer. Call this endpoint when `POST /verifications` returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry `POST /verifications` to complete the KYC check. - operationId: createCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - responses: - '200': - description: EDD payload created or replaced successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - 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' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - patch: - summary: Partially update a customer's enhanced-due-diligence (EDD) fields - description: Merge the provided EDD fields into any previously recorded EDD data for the customer. Fields omitted from the request body are left unchanged. - operationId: updateCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - responses: - '200': - description: EDD payload updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/CustomerEdd' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer not found or no EDD data recorded to update - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' /customers/{customerId}/kyc-link: parameters: - name: customerId @@ -3824,6 +3687,7 @@ paths: totalReceivingAmount: 9200 exchangeRate: 0.92 feesIncluded: 10 + platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000005 '202': description: | @@ -9502,6 +9366,7 @@ webhooks: totalReceivingAmount: 4625000 exchangeRate: 92.5 feesIncluded: 250 + platformFeesIncluded: 0 transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 createdAt: '2025-10-03T15:00:00Z' updatedAt: '2025-10-03T15:00:00Z' @@ -11173,6 +11038,73 @@ components: $ref: '#/components/schemas/CardTokenization2FAEmailConfig' sms: $ref: '#/components/schemas/CardTokenization2FASmsConfig' + FeeType: + type: string + enum: + - CROSS_CURRENCY_TRANSACTION + description: | + The kind of activity this fee applies to. + + - `CROSS_CURRENCY_TRANSACTION` — fee charged on a cross-currency Grid transaction + (source currency differs from destination currency). + example: CROSS_CURRENCY_TRANSACTION + Currency: + type: object + properties: + code: + type: string + description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) + example: USD + name: + type: string + description: Full name of the currency + example: United States Dollar + symbol: + type: string + description: Symbol of the currency + example: $ + decimals: + type: integer + description: Number of decimal places for the currency + minimum: 0 + example: 2 + CurrencyAmount: + type: object + required: + - amount + - currency + properties: + amount: + type: integer + format: int64 + description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) + example: 12550 + currency: + $ref: '#/components/schemas/Currency' + FeeConfig: + type: object + description: A platform-configured fee collected by Grid and settled to the platform internal account. There can be at most one fee config for a given fee type and source currency pair. The fee will apply to all transactions of the fee type that originate in the source currency. + properties: + feeType: + $ref: '#/components/schemas/FeeType' + sourceCurrency: + type: string + description: Currency code of the sending side this fee applies to. Only `USD` is accepted today; other currencies return a `NOT_IMPLEMENTED` error. + example: USD + variableFeeBps: + type: integer + minimum: 0 + maximum: 10000 + description: Variable fee in basis points (1 bps = 0.01%) to apply to a transaction's source-currency amount. + example: 30 + fixedFee: + $ref: '#/components/schemas/CurrencyAmount' + description: Fixed fee charged per transaction, in the smallest unit of the source currency. The fixed fee currency must match the fee config's `sourceCurrency`. + required: + - feeType + - sourceCurrency + - variableFeeBps + - fixedFee PlatformConfig: type: object properties: @@ -11219,6 +11151,14 @@ components: description: | Branding and sender configuration for card-tokenization authentication messages. This configuration is independent of embedded-wallet support. + feeConfigs: + type: array + items: + $ref: '#/components/schemas/FeeConfig' + description: | + Platform-collected fees that should be added on top of + Grid-collected fees. Contains every currently-active fee config + for the platform. createdAt: type: string format: date-time @@ -11325,6 +11265,15 @@ components: Update card-tokenization authentication branding and delivery settings. Fields omitted from the nested object are left unchanged. Changes apply to subsequent delivery attempts. + feeConfigs: + type: array + items: + $ref: '#/components/schemas/FeeConfig' + description: | + Merge-by-key upsert of platform fee configs, keyed by + `(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. @@ -11455,7 +11404,7 @@ components: description: Error message details: type: object - description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, `POST /customers/{id}/edd`, `PATCH /customers/{id}/edd`), `details.field` and `details.constraint` are populated so platforms can pre-validate their onboarding form before re-submitting. + 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 @@ -11493,26 +11442,6 @@ components: type: object description: Additional error details additionalProperties: true - Currency: - type: object - properties: - code: - type: string - description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.) - example: USD - name: - type: string - description: Full name of the currency - example: United States Dollar - symbol: - type: string - description: Symbol of the currency - example: $ - decimals: - type: integer - description: Number of decimal places for the currency - minimum: 0 - example: 2 PaymentRail: type: string enum: @@ -11797,69 +11726,213 @@ components: - NON_US_TAX_ID description: Type of tax identification example: SSN - IndividualCustomerFields: - 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 - IndividualCustomer: - title: Individual Customer - allOf: - - $ref: '#/components/schemas/Customer' - - $ref: '#/components/schemas/IndividualCustomerFields' - KybStatus: + IndividualSourceOfFundsCategory: type: string enum: - - UNVERIFIED - - PENDING - - APPROVED - - REJECTED - - HOLD - description: The current KYB status of a business customer. `HOLD` means the customer is placed on hold and may be required to update or provide more information. - example: APPROVED - EntityType: + - 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: - - SOLE_PROPRIETORSHIP - - PARTNERSHIP - - LLC - - CORPORATION - - S_CORPORATION - - NON_PROFIT - - OTHER - description: Legal entity type of the business - example: LLC + - 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 + 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: '#/components/schemas/IndividualSourceOfFundsCategory' + 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: '#/components/schemas/SourceOfWealthCategory' + 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: '#/components/schemas/PurposeOfAccount' + 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: '#/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: + - $ref: '#/components/schemas/Customer' + - $ref: '#/components/schemas/IndividualCustomerFields' + KybStatus: + type: string + enum: + - UNVERIFIED + - PENDING + - APPROVED + - REJECTED + - HOLD + description: The current KYB status of a business customer. `HOLD` means the customer is placed on hold and may be required to update or provide more information. + example: APPROVED + EntityType: + type: string + enum: + - SOLE_PROPRIETORSHIP + - PARTNERSHIP + - LLC + - CORPORATION + - S_CORPORATION + - NON_PROFIT + - OTHER + description: Legal entity type of the business + example: LLC BusinessType: type: string description: The high-level industry category of the business @@ -11884,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: @@ -12349,12 +12404,12 @@ components: email: type: string format: email - description: Email address for the customer. + description: Email address for the customer. **Required in regions that verify the email address before identity verification** (e.g. the EU); optional otherwise. example: john.doe@example.com phoneNumber: type: string pattern: ^\+[1-9]\d{1,14}$ - description: Phone number for the customer in strict E.164 format. + description: Phone number for the customer in strict E.164 format. **Required in regions that verify the phone number before identity verification** (e.g. the EU); optional otherwise. example: '+14155551234' umaAddress: type: string @@ -12721,142 +12776,6 @@ components: type: object description: Additional error details additionalProperties: true - 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 - 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 - description: Enhanced-due-diligence (EDD) fields for an individual customer. All fields are optional; 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: '#/components/schemas/IndividualSourceOfFundsCategory' - 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: '#/components/schemas/SourceOfWealthCategory' - 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: '#/components/schemas/PurposeOfAccount' - 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: '#/components/schemas/ExpectedMonthlyTransactionCount' - expectedMonthlyTransactionVolume: - $ref: '#/components/schemas/ExpectedMonthlyTransactionVolume' - annualIncomeRange: - $ref: '#/components/schemas/AnnualIncomeRange' - netWorthRange: - $ref: '#/components/schemas/NetWorthRange' - pepStatus: - $ref: '#/components/schemas/PepStatus' - createdAt: - type: string - format: date-time - description: Creation timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' - updatedAt: - type: string - format: date-time - description: Last update timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' KycLinkCreateRequest: type: object description: Request body for generating a hosted KYC link for an existing customer. @@ -13583,19 +13502,6 @@ components: - `FROZEN`: The account cannot send or receive payments. Grid may freeze an account in response to compliance or fraud signals; payments are blocked while the account remains frozen. - `FAILED`: The account could not be provisioned. Grid was unable to create the underlying account, so it cannot send or receive payments and requires remediation. example: ACTIVE - CurrencyAmount: - type: object - required: - - amount - - currency - properties: - amount: - type: integer - format: int64 - description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) - example: 12550 - currency: - $ref: '#/components/schemas/Currency' PaymentAccountType: type: string enum: @@ -20505,6 +20411,12 @@ components: description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). minimum: 0 example: 10 + platformFees: + type: integer + format: int64 + description: The portion of `fees` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `fees`. + minimum: 0 + example: 5 reconciliationInstructions: $ref: '#/components/schemas/ReconciliationInstructions' description: Reconciliation details for this transaction. For the on-chain hash of a crypto payout to an external wallet, see the destination's `onChainTransaction` instead. @@ -21085,6 +20997,12 @@ components: description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' minimum: 0 example: 10 + platformFeesIncluded: + type: integer + format: int64 + description: The portion of `feesIncluded` collected by the platform (platform-configured transaction fees), in the smallest unit of the sending currency. 0 when the platform has no applicable fee configured. Already included in `feesIncluded`. May be omitted from payloads produced before platform fees existed. + minimum: 0 + example: 5 paymentInstructions: type: array description: Payment instructions for executing the payment. This is not required when using an internal account source. diff --git a/openapi/components/schemas/customers/CustomerEdd.yaml b/openapi/components/schemas/customers/CustomerEdd.yaml index 3e88d5edd..9d847abc5 100644 --- a/openapi/components/schemas/customers/CustomerEdd.yaml +++ b/openapi/components/schemas/customers/CustomerEdd.yaml @@ -1,9 +1,12 @@ type: object description: >- - Enhanced-due-diligence (EDD) fields for an individual customer. All fields - are optional; 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`). + 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 @@ -50,15 +53,3 @@ properties: $ref: ./NetWorthRange.yaml pepStatus: $ref: ./PepStatus.yaml - createdAt: - type: string - format: date-time - description: Creation timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' - updatedAt: - type: string - format: date-time - description: Last update timestamp - readOnly: true - example: '2026-07-24T17:32:28Z' diff --git a/openapi/components/schemas/customers/IndividualCustomerFields.yaml b/openapi/components/schemas/customers/IndividualCustomerFields.yaml index 1b2bde21d..36c980a30 100644 --- a/openapi/components/schemas/customers/IndividualCustomerFields.yaml +++ b/openapi/components/schemas/customers/IndividualCustomerFields.yaml @@ -1,40 +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 - 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 +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/errors/Error400.yaml b/openapi/components/schemas/errors/Error400.yaml index 3839dd840..248011211 100644 --- a/openapi/components/schemas/errors/Error400.yaml +++ b/openapi/components/schemas/errors/Error400.yaml @@ -100,10 +100,9 @@ properties: type: object description: >- Additional error details. Shape varies by `code`. For field-validation - errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`, - `POST /customers/{id}/edd`, `PATCH /customers/{id}/edd`), `details.field` and - `details.constraint` are populated so platforms can pre-validate their - onboarding form before re-submitting. + 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 diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index fa67281ab..f5b2f8028 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -143,8 +143,6 @@ paths: $ref: paths/customers/customers.yaml /customers/{customerId}: $ref: paths/customers/customers_{customerId}.yaml - /customers/{customerId}/edd: - $ref: paths/customers/customers_{customerId}_edd.yaml /customers/{customerId}/kyc-link: $ref: paths/customers/customers_{customerId}_kyc-link.yaml /customers/{customerId}/verify-email: diff --git a/openapi/paths/customers/customers_{customerId}_edd.yaml b/openapi/paths/customers/customers_{customerId}_edd.yaml deleted file mode 100644 index 6cb34cc09..000000000 --- a/openapi/paths/customers/customers_{customerId}_edd.yaml +++ /dev/null @@ -1,144 +0,0 @@ -parameters: - - name: customerId - in: path - description: The Grid customer ID. - required: true - schema: - type: string -get: - summary: Get a customer's enhanced-due-diligence (EDD) fields - description: >- - Retrieve the EDD fields previously supplied for a customer. Returns `404` - if no EDD data has been recorded for the customer yet. - operationId: getCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - responses: - '200': - description: EDD payload retrieved successfully - content: - application/json: - schema: - $ref: ../../components/schemas/customers/CustomerEdd.yaml - '400': - description: Bad request - Invalid parameters - 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 or no EDD data recorded for this customer - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error404.yaml - '500': - description: Internal service error - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error500.yaml -post: - summary: Create or replace a customer's enhanced-due-diligence (EDD) fields - description: >- - Supply the EDD fields for a customer. Overwrites any previously recorded - EDD data for that customer. Call this endpoint when `POST /verifications` - returns `MISSING_FIELD` errors pointing at `edd.*` fields, then retry - `POST /verifications` to complete the KYC check. - operationId: createCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../../components/schemas/customers/CustomerEdd.yaml - responses: - '200': - description: EDD payload created or replaced successfully - content: - application/json: - schema: - $ref: ../../components/schemas/customers/CustomerEdd.yaml - '400': - description: Bad request - 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 - '500': - description: Internal service error - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error500.yaml -patch: - summary: Partially update a customer's enhanced-due-diligence (EDD) fields - description: >- - Merge the provided EDD fields into any previously recorded EDD data for - the customer. Fields omitted from the request body are left unchanged. - operationId: updateCustomerEdd - tags: - - KYC/KYB Verifications - security: - - BasicAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../../components/schemas/customers/CustomerEdd.yaml - responses: - '200': - description: EDD payload updated successfully - content: - application/json: - schema: - $ref: ../../components/schemas/customers/CustomerEdd.yaml - '400': - description: Bad request - 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 or no EDD data recorded to update - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error404.yaml - '500': - description: Internal service error - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error500.yaml