From 585cb955cde0bffbc788c1401b472a8b53e10355 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 31 Jul 2026 23:43:32 +0000 Subject: [PATCH 1/4] add end-user terms consent customer APIs Co-Authored-By: github-actions Co-Authored-By: jklein24 --- .stainless/stainless.yml | 8 + mintlify/openapi.yaml | 172 ++++++++++++++++++ .../onboarding/disclosures.mdx | 4 + openapi.yaml | 172 ++++++++++++++++++ .../schemas/customers/Customer.yaml | 9 + .../customers/CustomerCreateRequest.yaml | 2 + .../schemas/customers/EndUserTerms.yaml | 14 ++ .../EndUserTermsAcceptanceMethod.yaml | 6 + .../customers/EndUserTermsConsent.yaml | 9 + .../customers/EndUserTermsConsentRequest.yaml | 22 +++ .../components/schemas/errors/Error400.yaml | 2 + openapi/openapi.yaml | 4 + .../customers/customers_end-user-terms.yaml | 21 +++ ...s_{customerId}_end-user-terms-consent.yaml | 80 ++++++++ openapi/webhooks/customer-update.yaml | 4 + 15 files changed, 529 insertions(+) create mode 100644 openapi/components/schemas/customers/EndUserTerms.yaml create mode 100644 openapi/components/schemas/customers/EndUserTermsAcceptanceMethod.yaml create mode 100644 openapi/components/schemas/customers/EndUserTermsConsent.yaml create mode 100644 openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml create mode 100644 openapi/paths/customers/customers_end-user-terms.yaml create mode 100644 openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index 38f41cd35..294f0c937 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -113,6 +113,9 @@ resources: business_customer_create_request: '#/components/schemas/BusinessCustomerCreateRequest' individual_customer_update_request: '#/components/schemas/IndividualCustomerUpdateRequest' business_customer_update_request: '#/components/schemas/BusinessCustomerUpdateRequest' + end_user_terms: '#/components/schemas/EndUserTerms' + end_user_terms_consent: '#/components/schemas/EndUserTermsConsent' + end_user_terms_consent_request: '#/components/schemas/EndUserTermsConsentRequest' # Internal-account management (list/update/export under this resource) internal_account_list_response: '#/components/schemas/InternalAccountListResponse' internal_account_update_request: '#/components/schemas/InternalAccountUpdateRequest' @@ -139,6 +142,11 @@ resources: create_kyc_link: endpoint: post /customers/{customerId}/kyc-link body_param_name: KycLinkCreateRequest + retrieve_end_user_terms: get /customers/end-user-terms + retrieve_end_user_terms_consent: get /customers/{customerId}/end-user-terms-consent + update_end_user_terms_consent: + endpoint: patch /customers/{customerId}/end-user-terms-consent + body_param_name: EndUserTermsConsentRequest # Subresources define resources that are nested within another for more powerful # logical groupings, e.g. `cards.payments`. subresources: diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index e7f98bd63..4c6373834 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -826,6 +826,109 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /customers/{customerId}/end-user-terms-consent: + get: + summary: Get a customer's End User Terms consent + description: Retrieve the End User Terms acceptance recorded for one customer. + operationId: getCustomerEndUserTermsConsent + tags: + - Customers + security: + - BasicAuth: [] + parameters: + - name: customerId + in: path + required: true + description: Unique Grid identifier for the customer. + schema: + type: string + responses: + '200': + description: End User Terms consent retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTermsConsent' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer or consent record not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + patch: + summary: Update a customer's End User Terms consent + description: Record or replace the End User Terms acceptance for one customer. + operationId: updateCustomerEndUserTermsConsent + tags: + - Customers + security: + - BasicAuth: [] + parameters: + - name: customerId + in: path + required: true + description: Unique Grid identifier for the customer. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTermsConsentRequest' + responses: + '200': + description: End User Terms consent updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTermsConsent' + '400': + description: Invalid input or unsupported terms version + 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' + /customers/end-user-terms: + get: + summary: Get the current Grid End User Terms + description: Retrieve the current version and Grid-hosted URL of the End User Terms. + operationId: getEndUserTerms + tags: + - Customers + security: + - BasicAuth: [] + responses: + '200': + description: Current End User Terms retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTerms' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' /customers/{customerId}/kyc-link: parameters: - name: customerId @@ -10470,6 +10573,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 9f84e0c2a72c4fa customerType: INDIVIDUAL + hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -10499,6 +10603,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000002 platformCustomerId: 4b7c1e9d3f5a8e2 customerType: INDIVIDUAL + hasAcceptedEndUserTerms: true region: US currencies: - USD @@ -10521,6 +10626,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000003 platformCustomerId: 7a2f9d4e1b8c3f5 customerType: BUSINESS + hasAcceptedEndUserTerms: true region: US currencies: - USD @@ -10551,6 +10657,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000004 platformCustomerId: 3c8e5f2a9d1b7e4 customerType: BUSINESS + hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -11750,6 +11857,7 @@ components: | Error Code | Description | |------------|-------------| | INVALID_INPUT | Invalid input provided | + | END_USER_TERMS_VERSION_NOT_FOUND | The submitted End User Terms version is not supported | | MISSING_MANDATORY_USER_INFO | Required customer information is missing | | INVITATION_ALREADY_CLAIMED | Invitation has already been claimed | | INVITATIONS_NOT_CONFIGURED | Invitations are not configured | @@ -11790,6 +11898,7 @@ components: | STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active provider account links exist; pass `stablecoinProviderAccountId` to select one | enum: - INVALID_INPUT + - END_USER_TERMS_VERSION_NOT_FOUND - MISSING_MANDATORY_USER_INFO - INVITATION_ALREADY_CLAIMED - INVITATIONS_NOT_CONFIGURED @@ -12064,6 +12173,7 @@ components: - umaAddress - platformCustomerId - customerType + - hasAcceptedEndUserTerms properties: id: type: string @@ -12076,6 +12186,11 @@ components: example: 9f84e0c2a72c4fa customerType: $ref: '#/components/schemas/CustomerType' + hasAcceptedEndUserTerms: + type: boolean + readOnly: true + description: Whether Grid has recorded the customer's acceptance of the End User Terms. For platforms where acceptance is required, a value of `false` means the customer cannot open an account until consent is recorded. + example: true region: type: string description: Country code (ISO 3166-1 alpha-2) representing the customer's regional identity and regulatory jurisdiction. @@ -12830,6 +12945,36 @@ components: type: object description: Additional error details additionalProperties: true + EndUserTermsAcceptanceMethod: + type: string + description: Method the customer used to affirmatively accept the End User Terms. + enum: + - CHECKBOX + - CLICK_TO_ACCEPT + example: CHECKBOX + EndUserTermsConsentRequest: + type: object + required: + - acceptedAt + - ipAddress + - termsVersion + - acceptanceMethod + properties: + acceptedAt: + type: string + format: date-time + description: Date and time when the customer accepted the End User Terms. + ipAddress: + type: string + maxLength: 45 + description: IP address of the device the customer used when accepting the terms. + example: 198.51.100.24 + termsVersion: + type: string + description: Version identifier of the accepted Grid End User Terms. + example: '2026-07-31' + acceptanceMethod: + $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' CustomerCreateRequest: type: object required: @@ -12867,6 +13012,8 @@ components: type: string description: Optional UMA address identifier. If not provided during customer creation, one will be generated by the system. If provided during customer update, the UMA address will be updated to the provided value. This is an optional identifier to route payments to the customer. This is an optional identifier to route payments to the customer. example: $john.doe@uma.domain.com + endUserTermsConsent: + $ref: '#/components/schemas/EndUserTermsConsentRequest' IndividualCustomerCreateRequest: title: Individual Customer Create Request allOf: @@ -13232,6 +13379,31 @@ components: type: object description: Additional error details additionalProperties: true + EndUserTermsConsent: + allOf: + - $ref: '#/components/schemas/EndUserTermsConsentRequest' + - type: object + required: + - customerId + properties: + customerId: + type: string + description: Unique Grid identifier for the customer. + EndUserTerms: + type: object + required: + - version + - url + properties: + version: + type: string + description: Current version identifier of the Grid End User Terms. + example: '2026-07-31' + url: + type: string + format: uri + description: URL where Grid hosts this version of the End User Terms. + example: https://www.lightspark.com/legal/grid/enduserterms KycLinkCreateRequest: type: object description: Request body for generating a hosted KYC link for an existing customer. diff --git a/mintlify/payouts-and-b2b/onboarding/disclosures.mdx b/mintlify/payouts-and-b2b/onboarding/disclosures.mdx index 05004b0bd..b54d6445e 100644 --- a/mintlify/payouts-and-b2b/onboarding/disclosures.mdx +++ b/mintlify/payouts-and-b2b/onboarding/disclosures.mdx @@ -19,6 +19,10 @@ Copy Lightspark's End User Terms and append them to your own terms of service, s Present the combined terms in your onboarding or consent flow, and require each end user to affirmatively accept them (for example, an unchecked checkbox or an "I Agree" button) before they can use Grid. +Use `GET /customers/end-user-terms` to retrieve the current terms URL and version. Record acceptance when you create the customer with `endUserTermsConsent`, or later with `PATCH /customers/{customerId}/end-user-terms-consent`. The acceptance record includes the timestamp, device IP address, terms version, and acceptance method. Grid rejects versions that it does not recognize. + +For unregulated platforms, Grid does not open customer accounts until you record this acceptance. You can retrieve the current record with `GET /customers/{customerId}/end-user-terms-consent`. + ## Provide evidence of your consent flow Send Lightspark evidence that your end users are shown the End User Terms and consent to them. Provide both: diff --git a/openapi.yaml b/openapi.yaml index e7f98bd63..4c6373834 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -826,6 +826,109 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /customers/{customerId}/end-user-terms-consent: + get: + summary: Get a customer's End User Terms consent + description: Retrieve the End User Terms acceptance recorded for one customer. + operationId: getCustomerEndUserTermsConsent + tags: + - Customers + security: + - BasicAuth: [] + parameters: + - name: customerId + in: path + required: true + description: Unique Grid identifier for the customer. + schema: + type: string + responses: + '200': + description: End User Terms consent retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTermsConsent' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Customer or consent record not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + patch: + summary: Update a customer's End User Terms consent + description: Record or replace the End User Terms acceptance for one customer. + operationId: updateCustomerEndUserTermsConsent + tags: + - Customers + security: + - BasicAuth: [] + parameters: + - name: customerId + in: path + required: true + description: Unique Grid identifier for the customer. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTermsConsentRequest' + responses: + '200': + description: End User Terms consent updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTermsConsent' + '400': + description: Invalid input or unsupported terms version + 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' + /customers/end-user-terms: + get: + summary: Get the current Grid End User Terms + description: Retrieve the current version and Grid-hosted URL of the End User Terms. + operationId: getEndUserTerms + tags: + - Customers + security: + - BasicAuth: [] + responses: + '200': + description: Current End User Terms retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/EndUserTerms' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' /customers/{customerId}/kyc-link: parameters: - name: customerId @@ -10470,6 +10573,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 9f84e0c2a72c4fa customerType: INDIVIDUAL + hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -10499,6 +10603,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000002 platformCustomerId: 4b7c1e9d3f5a8e2 customerType: INDIVIDUAL + hasAcceptedEndUserTerms: true region: US currencies: - USD @@ -10521,6 +10626,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000003 platformCustomerId: 7a2f9d4e1b8c3f5 customerType: BUSINESS + hasAcceptedEndUserTerms: true region: US currencies: - USD @@ -10551,6 +10657,7 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000004 platformCustomerId: 3c8e5f2a9d1b7e4 customerType: BUSINESS + hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -11750,6 +11857,7 @@ components: | Error Code | Description | |------------|-------------| | INVALID_INPUT | Invalid input provided | + | END_USER_TERMS_VERSION_NOT_FOUND | The submitted End User Terms version is not supported | | MISSING_MANDATORY_USER_INFO | Required customer information is missing | | INVITATION_ALREADY_CLAIMED | Invitation has already been claimed | | INVITATIONS_NOT_CONFIGURED | Invitations are not configured | @@ -11790,6 +11898,7 @@ components: | STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active provider account links exist; pass `stablecoinProviderAccountId` to select one | enum: - INVALID_INPUT + - END_USER_TERMS_VERSION_NOT_FOUND - MISSING_MANDATORY_USER_INFO - INVITATION_ALREADY_CLAIMED - INVITATIONS_NOT_CONFIGURED @@ -12064,6 +12173,7 @@ components: - umaAddress - platformCustomerId - customerType + - hasAcceptedEndUserTerms properties: id: type: string @@ -12076,6 +12186,11 @@ components: example: 9f84e0c2a72c4fa customerType: $ref: '#/components/schemas/CustomerType' + hasAcceptedEndUserTerms: + type: boolean + readOnly: true + description: Whether Grid has recorded the customer's acceptance of the End User Terms. For platforms where acceptance is required, a value of `false` means the customer cannot open an account until consent is recorded. + example: true region: type: string description: Country code (ISO 3166-1 alpha-2) representing the customer's regional identity and regulatory jurisdiction. @@ -12830,6 +12945,36 @@ components: type: object description: Additional error details additionalProperties: true + EndUserTermsAcceptanceMethod: + type: string + description: Method the customer used to affirmatively accept the End User Terms. + enum: + - CHECKBOX + - CLICK_TO_ACCEPT + example: CHECKBOX + EndUserTermsConsentRequest: + type: object + required: + - acceptedAt + - ipAddress + - termsVersion + - acceptanceMethod + properties: + acceptedAt: + type: string + format: date-time + description: Date and time when the customer accepted the End User Terms. + ipAddress: + type: string + maxLength: 45 + description: IP address of the device the customer used when accepting the terms. + example: 198.51.100.24 + termsVersion: + type: string + description: Version identifier of the accepted Grid End User Terms. + example: '2026-07-31' + acceptanceMethod: + $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' CustomerCreateRequest: type: object required: @@ -12867,6 +13012,8 @@ components: type: string description: Optional UMA address identifier. If not provided during customer creation, one will be generated by the system. If provided during customer update, the UMA address will be updated to the provided value. This is an optional identifier to route payments to the customer. This is an optional identifier to route payments to the customer. example: $john.doe@uma.domain.com + endUserTermsConsent: + $ref: '#/components/schemas/EndUserTermsConsentRequest' IndividualCustomerCreateRequest: title: Individual Customer Create Request allOf: @@ -13232,6 +13379,31 @@ components: type: object description: Additional error details additionalProperties: true + EndUserTermsConsent: + allOf: + - $ref: '#/components/schemas/EndUserTermsConsentRequest' + - type: object + required: + - customerId + properties: + customerId: + type: string + description: Unique Grid identifier for the customer. + EndUserTerms: + type: object + required: + - version + - url + properties: + version: + type: string + description: Current version identifier of the Grid End User Terms. + example: '2026-07-31' + url: + type: string + format: uri + description: URL where Grid hosts this version of the End User Terms. + example: https://www.lightspark.com/legal/grid/enduserterms KycLinkCreateRequest: type: object description: Request body for generating a hosted KYC link for an existing customer. diff --git a/openapi/components/schemas/customers/Customer.yaml b/openapi/components/schemas/customers/Customer.yaml index 1e11a5c7c..f416046a2 100644 --- a/openapi/components/schemas/customers/Customer.yaml +++ b/openapi/components/schemas/customers/Customer.yaml @@ -3,6 +3,7 @@ required: - umaAddress - platformCustomerId - customerType + - hasAcceptedEndUserTerms properties: id: type: string @@ -15,6 +16,14 @@ properties: example: 9f84e0c2a72c4fa customerType: $ref: ./CustomerType.yaml + hasAcceptedEndUserTerms: + type: boolean + readOnly: true + description: >- + Whether Grid has recorded the customer's acceptance of the End User Terms. + For platforms where acceptance is required, a value of `false` means the + customer cannot open an account until consent is recorded. + example: true region: type: string description: >- diff --git a/openapi/components/schemas/customers/CustomerCreateRequest.yaml b/openapi/components/schemas/customers/CustomerCreateRequest.yaml index 47d1e0765..a82792e34 100644 --- a/openapi/components/schemas/customers/CustomerCreateRequest.yaml +++ b/openapi/components/schemas/customers/CustomerCreateRequest.yaml @@ -54,3 +54,5 @@ properties: If provided during customer update, the UMA address will be updated to the provided value. This is an optional identifier to route payments to the customer. This is an optional identifier to route payments to the customer. example: $john.doe@uma.domain.com + endUserTermsConsent: + $ref: ./EndUserTermsConsentRequest.yaml diff --git a/openapi/components/schemas/customers/EndUserTerms.yaml b/openapi/components/schemas/customers/EndUserTerms.yaml new file mode 100644 index 000000000..b3202c95e --- /dev/null +++ b/openapi/components/schemas/customers/EndUserTerms.yaml @@ -0,0 +1,14 @@ +type: object +required: + - version + - url +properties: + version: + type: string + description: Current version identifier of the Grid End User Terms. + example: '2026-07-31' + url: + type: string + format: uri + description: URL where Grid hosts this version of the End User Terms. + example: https://www.lightspark.com/legal/grid/enduserterms diff --git a/openapi/components/schemas/customers/EndUserTermsAcceptanceMethod.yaml b/openapi/components/schemas/customers/EndUserTermsAcceptanceMethod.yaml new file mode 100644 index 000000000..f4d315ae6 --- /dev/null +++ b/openapi/components/schemas/customers/EndUserTermsAcceptanceMethod.yaml @@ -0,0 +1,6 @@ +type: string +description: Method the customer used to affirmatively accept the End User Terms. +enum: + - CHECKBOX + - CLICK_TO_ACCEPT +example: CHECKBOX diff --git a/openapi/components/schemas/customers/EndUserTermsConsent.yaml b/openapi/components/schemas/customers/EndUserTermsConsent.yaml new file mode 100644 index 000000000..fe5a090d2 --- /dev/null +++ b/openapi/components/schemas/customers/EndUserTermsConsent.yaml @@ -0,0 +1,9 @@ +allOf: + - $ref: ./EndUserTermsConsentRequest.yaml + - type: object + required: + - customerId + properties: + customerId: + type: string + description: Unique Grid identifier for the customer. diff --git a/openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml b/openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml new file mode 100644 index 000000000..0395abed2 --- /dev/null +++ b/openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml @@ -0,0 +1,22 @@ +type: object +required: + - acceptedAt + - ipAddress + - termsVersion + - acceptanceMethod +properties: + acceptedAt: + type: string + format: date-time + description: Date and time when the customer accepted the End User Terms. + ipAddress: + type: string + maxLength: 45 + description: IP address of the device the customer used when accepting the terms. + example: 198.51.100.24 + termsVersion: + type: string + description: Version identifier of the accepted Grid End User Terms. + example: '2026-07-31' + acceptanceMethod: + $ref: ./EndUserTermsAcceptanceMethod.yaml diff --git a/openapi/components/schemas/errors/Error400.yaml b/openapi/components/schemas/errors/Error400.yaml index 97bcaad55..e38f562c2 100644 --- a/openapi/components/schemas/errors/Error400.yaml +++ b/openapi/components/schemas/errors/Error400.yaml @@ -15,6 +15,7 @@ properties: | Error Code | Description | |------------|-------------| | INVALID_INPUT | Invalid input provided | + | END_USER_TERMS_VERSION_NOT_FOUND | The submitted End User Terms version is not supported | | MISSING_MANDATORY_USER_INFO | Required customer information is missing | | INVITATION_ALREADY_CLAIMED | Invitation has already been claimed | | INVITATIONS_NOT_CONFIGURED | Invitations are not configured | @@ -55,6 +56,7 @@ properties: | STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active provider account links exist; pass `stablecoinProviderAccountId` to select one | enum: - INVALID_INPUT + - END_USER_TERMS_VERSION_NOT_FOUND - MISSING_MANDATORY_USER_INFO - INVITATION_ALREADY_CLAIMED - INVITATIONS_NOT_CONFIGURED diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index f18130315..aeb83db8b 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -143,6 +143,10 @@ paths: $ref: paths/customers/customers.yaml /customers/{customerId}: $ref: paths/customers/customers_{customerId}.yaml + /customers/{customerId}/end-user-terms-consent: + $ref: paths/customers/customers_{customerId}_end-user-terms-consent.yaml + /customers/end-user-terms: + $ref: paths/customers/customers_end-user-terms.yaml /customers/{customerId}/kyc-link: $ref: paths/customers/customers_{customerId}_kyc-link.yaml /customers/{customerId}/verify-email: diff --git a/openapi/paths/customers/customers_end-user-terms.yaml b/openapi/paths/customers/customers_end-user-terms.yaml new file mode 100644 index 000000000..fd10b0089 --- /dev/null +++ b/openapi/paths/customers/customers_end-user-terms.yaml @@ -0,0 +1,21 @@ +get: + summary: Get the current Grid End User Terms + description: Retrieve the current version and Grid-hosted URL of the End User Terms. + operationId: getEndUserTerms + tags: + - Customers + security: + - BasicAuth: [] + responses: + '200': + description: Current End User Terms retrieved successfully + content: + application/json: + schema: + $ref: ../../components/schemas/customers/EndUserTerms.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml diff --git a/openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml b/openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml new file mode 100644 index 000000000..c491e3de3 --- /dev/null +++ b/openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml @@ -0,0 +1,80 @@ +get: + summary: Get a customer's End User Terms consent + description: Retrieve the End User Terms acceptance recorded for one customer. + operationId: getCustomerEndUserTermsConsent + tags: + - Customers + security: + - BasicAuth: [] + parameters: + - name: customerId + in: path + required: true + description: Unique Grid identifier for the customer. + schema: + type: string + responses: + '200': + description: End User Terms consent retrieved successfully + content: + application/json: + schema: + $ref: ../../components/schemas/customers/EndUserTermsConsent.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Customer or consent record not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml +patch: + summary: Update a customer's End User Terms consent + description: Record or replace the End User Terms acceptance for one customer. + operationId: updateCustomerEndUserTermsConsent + tags: + - Customers + security: + - BasicAuth: [] + parameters: + - name: customerId + in: path + required: true + description: Unique Grid identifier for the customer. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/customers/EndUserTermsConsentRequest.yaml + responses: + '200': + description: End User Terms consent updated successfully + content: + application/json: + schema: + $ref: ../../components/schemas/customers/EndUserTermsConsent.yaml + '400': + description: Invalid input or unsupported terms version + 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 diff --git a/openapi/webhooks/customer-update.yaml b/openapi/webhooks/customer-update.yaml index 2a811dac0..d8032e96a 100644 --- a/openapi/webhooks/customer-update.yaml +++ b/openapi/webhooks/customer-update.yaml @@ -47,6 +47,7 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 9f84e0c2a72c4fa customerType: INDIVIDUAL + hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -76,6 +77,7 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000002 platformCustomerId: 4b7c1e9d3f5a8e2 customerType: INDIVIDUAL + hasAcceptedEndUserTerms: true region: US currencies: - USD @@ -98,6 +100,7 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000003 platformCustomerId: 7a2f9d4e1b8c3f5 customerType: BUSINESS + hasAcceptedEndUserTerms: true region: US currencies: - USD @@ -128,6 +131,7 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000004 platformCustomerId: 3c8e5f2a9d1b7e4 customerType: BUSINESS + hasAcceptedEndUserTerms: false region: US currencies: - USD From 73aa2ab15ad0ae1ded6339cf9f8cd79d6686e445 Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 4 Aug 2026 20:40:24 +0000 Subject: [PATCH 2/4] Use sequential End User Terms version identifiers Start the version identifier at V1 so future revisions increment to V2, V3, and so on, rather than encoding a release date. Co-Authored-By: bsiaotickchong --- mintlify/openapi.yaml | 4 ++-- openapi.yaml | 4 ++-- openapi/components/schemas/customers/EndUserTerms.yaml | 2 +- .../schemas/customers/EndUserTermsConsentRequest.yaml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 4c6373834..7e4d8bb29 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -12972,7 +12972,7 @@ components: termsVersion: type: string description: Version identifier of the accepted Grid End User Terms. - example: '2026-07-31' + example: V1 acceptanceMethod: $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' CustomerCreateRequest: @@ -13398,7 +13398,7 @@ components: version: type: string description: Current version identifier of the Grid End User Terms. - example: '2026-07-31' + example: V1 url: type: string format: uri diff --git a/openapi.yaml b/openapi.yaml index 4c6373834..7e4d8bb29 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -12972,7 +12972,7 @@ components: termsVersion: type: string description: Version identifier of the accepted Grid End User Terms. - example: '2026-07-31' + example: V1 acceptanceMethod: $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' CustomerCreateRequest: @@ -13398,7 +13398,7 @@ components: version: type: string description: Current version identifier of the Grid End User Terms. - example: '2026-07-31' + example: V1 url: type: string format: uri diff --git a/openapi/components/schemas/customers/EndUserTerms.yaml b/openapi/components/schemas/customers/EndUserTerms.yaml index b3202c95e..b39f6ac6e 100644 --- a/openapi/components/schemas/customers/EndUserTerms.yaml +++ b/openapi/components/schemas/customers/EndUserTerms.yaml @@ -6,7 +6,7 @@ properties: version: type: string description: Current version identifier of the Grid End User Terms. - example: '2026-07-31' + example: V1 url: type: string format: uri diff --git a/openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml b/openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml index 0395abed2..a5e30dfa7 100644 --- a/openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml +++ b/openapi/components/schemas/customers/EndUserTermsConsentRequest.yaml @@ -17,6 +17,6 @@ properties: termsVersion: type: string description: Version identifier of the accepted Grid End User Terms. - example: '2026-07-31' + example: V1 acceptanceMethod: $ref: ./EndUserTermsAcceptanceMethod.yaml From da602133f392f8af98832e475de10be57d688a63 Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 4 Aug 2026 23:23:23 +0000 Subject: [PATCH 3/4] feat: Embed end-user terms consent in customers Co-Authored-By: bsiaotickchong --- .stainless/stainless.yml | 4 - mintlify/openapi.yaml | 252 +++++++----------- .../onboarding/disclosures.mdx | 4 +- openapi.yaml | 252 +++++++----------- .../schemas/customers/Customer.yaml | 11 +- .../customers/CustomerUpdateRequest.yaml | 2 + .../customers/EndUserTermsConsent.yaml | 7 - .../components/schemas/errors/Error403.yaml | 2 + openapi/openapi.yaml | 2 - ...s_{customerId}_end-user-terms-consent.yaml | 80 ------ openapi/paths/quotes/quotes.yaml | 6 + openapi/webhooks/customer-update.yaml | 14 +- 12 files changed, 204 insertions(+), 432 deletions(-) delete mode 100644 openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index 294f0c937..49100e04c 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -143,10 +143,6 @@ resources: endpoint: post /customers/{customerId}/kyc-link body_param_name: KycLinkCreateRequest retrieve_end_user_terms: get /customers/end-user-terms - retrieve_end_user_terms_consent: get /customers/{customerId}/end-user-terms-consent - update_end_user_terms_consent: - endpoint: patch /customers/{customerId}/end-user-terms-consent - body_param_name: EndUserTermsConsentRequest # Subresources define resources that are nested within another for more powerful # logical groupings, e.g. `cards.payments`. subresources: diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 7e4d8bb29..6823c2d1e 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -826,87 +826,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/end-user-terms-consent: - get: - summary: Get a customer's End User Terms consent - description: Retrieve the End User Terms acceptance recorded for one customer. - operationId: getCustomerEndUserTermsConsent - tags: - - Customers - security: - - BasicAuth: [] - parameters: - - name: customerId - in: path - required: true - description: Unique Grid identifier for the customer. - schema: - type: string - responses: - '200': - description: End User Terms consent retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/EndUserTermsConsent' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer or consent record not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - patch: - summary: Update a customer's End User Terms consent - description: Record or replace the End User Terms acceptance for one customer. - operationId: updateCustomerEndUserTermsConsent - tags: - - Customers - security: - - BasicAuth: [] - parameters: - - name: customerId - in: path - required: true - description: Unique Grid identifier for the customer. - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EndUserTermsConsentRequest' - responses: - '200': - description: End User Terms consent updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/EndUserTermsConsent' - '400': - description: Invalid input or unsupported terms version - 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' /customers/end-user-terms: get: summary: Get the current Grid End User Terms @@ -3819,6 +3738,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error401' + '403': + description: Customer has not accepted the End User Terms + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' '412': description: Counterparty doesn't support UMA version content: @@ -10573,7 +10498,6 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 9f84e0c2a72c4fa customerType: INDIVIDUAL - hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -10603,7 +10527,11 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000002 platformCustomerId: 4b7c1e9d3f5a8e2 customerType: INDIVIDUAL - hasAcceptedEndUserTerms: true + endUserTermsConsent: + acceptedAt: '2025-07-21T17:30:00Z' + ipAddress: 203.0.113.42 + termsVersion: '2025-10-13' + acceptanceMethod: CHECKBOX region: US currencies: - USD @@ -10626,7 +10554,11 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000003 platformCustomerId: 7a2f9d4e1b8c3f5 customerType: BUSINESS - hasAcceptedEndUserTerms: true + endUserTermsConsent: + acceptedAt: '2025-07-21T17:30:00Z' + ipAddress: 203.0.113.42 + termsVersion: '2025-10-13' + acceptanceMethod: CHECKBOX region: US currencies: - USD @@ -10657,7 +10589,6 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000004 platformCustomerId: 3c8e5f2a9d1b7e4 customerType: BUSINESS - hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -12147,6 +12078,39 @@ components: - BUSINESS description: Whether the customer is an individual or a business entity example: INDIVIDUAL + EndUserTermsAcceptanceMethod: + type: string + description: Method the customer used to affirmatively accept the End User Terms. + enum: + - CHECKBOX + - CLICK_TO_ACCEPT + example: CHECKBOX + EndUserTermsConsentRequest: + type: object + required: + - acceptedAt + - ipAddress + - termsVersion + - acceptanceMethod + properties: + acceptedAt: + type: string + format: date-time + description: Date and time when the customer accepted the End User Terms. + ipAddress: + type: string + maxLength: 45 + description: IP address of the device the customer used when accepting the terms. + example: 198.51.100.24 + termsVersion: + type: string + description: Version identifier of the accepted Grid End User Terms. + example: V1 + acceptanceMethod: + $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' + EndUserTermsConsent: + allOf: + - $ref: '#/components/schemas/EndUserTermsConsentRequest' ContactVerificationStatus: type: string description: Status of an individual contact-verification channel (email or phone). `PENDING` means verification is required but not yet completed; `VERIFIED` means the channel has been confirmed. @@ -12173,7 +12137,6 @@ components: - umaAddress - platformCustomerId - customerType - - hasAcceptedEndUserTerms properties: id: type: string @@ -12186,11 +12149,10 @@ components: example: 9f84e0c2a72c4fa customerType: $ref: '#/components/schemas/CustomerType' - hasAcceptedEndUserTerms: - type: boolean + endUserTermsConsent: + $ref: '#/components/schemas/EndUserTermsConsent' readOnly: true - description: Whether Grid has recorded the customer's acceptance of the End User Terms. For platforms where acceptance is required, a value of `false` means the customer cannot open an account until consent is recorded. - example: true + description: The customer's recorded acceptance of the End User Terms. Omitted until acceptance has been recorded. region: type: string description: Country code (ISO 3166-1 alpha-2) representing the customer's regional identity and regulatory jurisdiction. @@ -12945,36 +12907,6 @@ components: type: object description: Additional error details additionalProperties: true - EndUserTermsAcceptanceMethod: - type: string - description: Method the customer used to affirmatively accept the End User Terms. - enum: - - CHECKBOX - - CLICK_TO_ACCEPT - example: CHECKBOX - EndUserTermsConsentRequest: - type: object - required: - - acceptedAt - - ipAddress - - termsVersion - - acceptanceMethod - properties: - acceptedAt: - type: string - format: date-time - description: Date and time when the customer accepted the End User Terms. - ipAddress: - type: string - maxLength: 45 - description: IP address of the device the customer used when accepting the terms. - example: 198.51.100.24 - termsVersion: - type: string - description: Version identifier of the accepted Grid End User Terms. - example: V1 - acceptanceMethod: - $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' CustomerCreateRequest: type: object required: @@ -13303,6 +13235,8 @@ components: type: string description: Optional UMA address identifier. If provided, the customer's UMA address will be updated. This is an optional identifier to route payments to the customer. example: $john.doe@uma.domain.com + endUserTermsConsent: + $ref: '#/components/schemas/EndUserTermsConsentRequest' IndividualCustomerUpdateRequest: title: Individual Customer Update Request allOf: @@ -13379,16 +13313,6 @@ components: type: object description: Additional error details additionalProperties: true - EndUserTermsConsent: - allOf: - - $ref: '#/components/schemas/EndUserTermsConsentRequest' - - type: object - required: - - customerId - properties: - customerId: - type: string - description: Unique Grid identifier for the customer. EndUserTerms: type: object required: @@ -21881,6 +21805,41 @@ components: example: FULL_NAME: Jane Receiver NATIONALITY: FR + Error403: + type: object + required: + - message + - status + - code + properties: + status: + type: integer + enum: + - 403 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | FORBIDDEN | Insufficient permissions | + | USER_NOT_READY | Customer exists but is not ready for operation | + | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | + | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | + | END_USER_TERMS_NOT_ACCEPTED | Customer has not accepted the End User Terms | + enum: + - FORBIDDEN + - USER_NOT_READY + - COUNTERPARTY_NOT_ALLOWED + - VELOCITY_LIMIT_EXCEEDED + - END_USER_TERMS_NOT_ACCEPTED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true ExecuteQuoteRequest: type: object description: Optional body for executing a quote. Only needed to request a specific Strong Customer Authentication factor (`scaFactor`) for the challenge this call issues; omit the body entirely otherwise. @@ -22230,39 +22189,6 @@ components: type: string description: The UMA address of the customer claiming the invitation example: $invitee@uma.domain - Error403: - type: object - required: - - message - - status - - code - properties: - status: - type: integer - enum: - - 403 - description: HTTP status code - code: - type: string - description: | - | Error Code | Description | - |------------|-------------| - | FORBIDDEN | Insufficient permissions | - | USER_NOT_READY | Customer exists but is not ready for operation | - | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | - | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | - enum: - - FORBIDDEN - - USER_NOT_READY - - COUNTERPARTY_NOT_ALLOWED - - VELOCITY_LIMIT_EXCEEDED - message: - type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true SandboxSendRequest: type: object required: diff --git a/mintlify/payouts-and-b2b/onboarding/disclosures.mdx b/mintlify/payouts-and-b2b/onboarding/disclosures.mdx index b54d6445e..8b5f10e04 100644 --- a/mintlify/payouts-and-b2b/onboarding/disclosures.mdx +++ b/mintlify/payouts-and-b2b/onboarding/disclosures.mdx @@ -19,9 +19,9 @@ Copy Lightspark's End User Terms and append them to your own terms of service, s Present the combined terms in your onboarding or consent flow, and require each end user to affirmatively accept them (for example, an unchecked checkbox or an "I Agree" button) before they can use Grid. -Use `GET /customers/end-user-terms` to retrieve the current terms URL and version. Record acceptance when you create the customer with `endUserTermsConsent`, or later with `PATCH /customers/{customerId}/end-user-terms-consent`. The acceptance record includes the timestamp, device IP address, terms version, and acceptance method. Grid rejects versions that it does not recognize. +Use `GET /customers/end-user-terms` to retrieve the current terms URL and version. Record acceptance with the `endUserTermsConsent` field when you create or update the customer. The acceptance record includes the timestamp, device IP address, terms version, and acceptance method. Grid rejects versions that it does not recognize. -For unregulated platforms, Grid does not open customer accounts until you record this acceptance. You can retrieve the current record with `GET /customers/{customerId}/end-user-terms-consent`. +For unregulated platforms, Grid does not open customer accounts until you record this acceptance. Customer responses include the full `endUserTermsConsent` object after acceptance is recorded. ## Provide evidence of your consent flow diff --git a/openapi.yaml b/openapi.yaml index 7e4d8bb29..6823c2d1e 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -826,87 +826,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /customers/{customerId}/end-user-terms-consent: - get: - summary: Get a customer's End User Terms consent - description: Retrieve the End User Terms acceptance recorded for one customer. - operationId: getCustomerEndUserTermsConsent - tags: - - Customers - security: - - BasicAuth: [] - parameters: - - name: customerId - in: path - required: true - description: Unique Grid identifier for the customer. - schema: - type: string - responses: - '200': - description: End User Terms consent retrieved successfully - content: - application/json: - schema: - $ref: '#/components/schemas/EndUserTermsConsent' - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Customer or consent record not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - patch: - summary: Update a customer's End User Terms consent - description: Record or replace the End User Terms acceptance for one customer. - operationId: updateCustomerEndUserTermsConsent - tags: - - Customers - security: - - BasicAuth: [] - parameters: - - name: customerId - in: path - required: true - description: Unique Grid identifier for the customer. - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EndUserTermsConsentRequest' - responses: - '200': - description: End User Terms consent updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/EndUserTermsConsent' - '400': - description: Invalid input or unsupported terms version - 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' /customers/end-user-terms: get: summary: Get the current Grid End User Terms @@ -3819,6 +3738,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error401' + '403': + description: Customer has not accepted the End User Terms + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' '412': description: Counterparty doesn't support UMA version content: @@ -10573,7 +10498,6 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 9f84e0c2a72c4fa customerType: INDIVIDUAL - hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -10603,7 +10527,11 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000002 platformCustomerId: 4b7c1e9d3f5a8e2 customerType: INDIVIDUAL - hasAcceptedEndUserTerms: true + endUserTermsConsent: + acceptedAt: '2025-07-21T17:30:00Z' + ipAddress: 203.0.113.42 + termsVersion: '2025-10-13' + acceptanceMethod: CHECKBOX region: US currencies: - USD @@ -10626,7 +10554,11 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000003 platformCustomerId: 7a2f9d4e1b8c3f5 customerType: BUSINESS - hasAcceptedEndUserTerms: true + endUserTermsConsent: + acceptedAt: '2025-07-21T17:30:00Z' + ipAddress: 203.0.113.42 + termsVersion: '2025-10-13' + acceptanceMethod: CHECKBOX region: US currencies: - USD @@ -10657,7 +10589,6 @@ webhooks: id: Customer:019542f5-b3e7-1d02-0000-000000000004 platformCustomerId: 3c8e5f2a9d1b7e4 customerType: BUSINESS - hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -12147,6 +12078,39 @@ components: - BUSINESS description: Whether the customer is an individual or a business entity example: INDIVIDUAL + EndUserTermsAcceptanceMethod: + type: string + description: Method the customer used to affirmatively accept the End User Terms. + enum: + - CHECKBOX + - CLICK_TO_ACCEPT + example: CHECKBOX + EndUserTermsConsentRequest: + type: object + required: + - acceptedAt + - ipAddress + - termsVersion + - acceptanceMethod + properties: + acceptedAt: + type: string + format: date-time + description: Date and time when the customer accepted the End User Terms. + ipAddress: + type: string + maxLength: 45 + description: IP address of the device the customer used when accepting the terms. + example: 198.51.100.24 + termsVersion: + type: string + description: Version identifier of the accepted Grid End User Terms. + example: V1 + acceptanceMethod: + $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' + EndUserTermsConsent: + allOf: + - $ref: '#/components/schemas/EndUserTermsConsentRequest' ContactVerificationStatus: type: string description: Status of an individual contact-verification channel (email or phone). `PENDING` means verification is required but not yet completed; `VERIFIED` means the channel has been confirmed. @@ -12173,7 +12137,6 @@ components: - umaAddress - platformCustomerId - customerType - - hasAcceptedEndUserTerms properties: id: type: string @@ -12186,11 +12149,10 @@ components: example: 9f84e0c2a72c4fa customerType: $ref: '#/components/schemas/CustomerType' - hasAcceptedEndUserTerms: - type: boolean + endUserTermsConsent: + $ref: '#/components/schemas/EndUserTermsConsent' readOnly: true - description: Whether Grid has recorded the customer's acceptance of the End User Terms. For platforms where acceptance is required, a value of `false` means the customer cannot open an account until consent is recorded. - example: true + description: The customer's recorded acceptance of the End User Terms. Omitted until acceptance has been recorded. region: type: string description: Country code (ISO 3166-1 alpha-2) representing the customer's regional identity and regulatory jurisdiction. @@ -12945,36 +12907,6 @@ components: type: object description: Additional error details additionalProperties: true - EndUserTermsAcceptanceMethod: - type: string - description: Method the customer used to affirmatively accept the End User Terms. - enum: - - CHECKBOX - - CLICK_TO_ACCEPT - example: CHECKBOX - EndUserTermsConsentRequest: - type: object - required: - - acceptedAt - - ipAddress - - termsVersion - - acceptanceMethod - properties: - acceptedAt: - type: string - format: date-time - description: Date and time when the customer accepted the End User Terms. - ipAddress: - type: string - maxLength: 45 - description: IP address of the device the customer used when accepting the terms. - example: 198.51.100.24 - termsVersion: - type: string - description: Version identifier of the accepted Grid End User Terms. - example: V1 - acceptanceMethod: - $ref: '#/components/schemas/EndUserTermsAcceptanceMethod' CustomerCreateRequest: type: object required: @@ -13303,6 +13235,8 @@ components: type: string description: Optional UMA address identifier. If provided, the customer's UMA address will be updated. This is an optional identifier to route payments to the customer. example: $john.doe@uma.domain.com + endUserTermsConsent: + $ref: '#/components/schemas/EndUserTermsConsentRequest' IndividualCustomerUpdateRequest: title: Individual Customer Update Request allOf: @@ -13379,16 +13313,6 @@ components: type: object description: Additional error details additionalProperties: true - EndUserTermsConsent: - allOf: - - $ref: '#/components/schemas/EndUserTermsConsentRequest' - - type: object - required: - - customerId - properties: - customerId: - type: string - description: Unique Grid identifier for the customer. EndUserTerms: type: object required: @@ -21881,6 +21805,41 @@ components: example: FULL_NAME: Jane Receiver NATIONALITY: FR + Error403: + type: object + required: + - message + - status + - code + properties: + status: + type: integer + enum: + - 403 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | FORBIDDEN | Insufficient permissions | + | USER_NOT_READY | Customer exists but is not ready for operation | + | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | + | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | + | END_USER_TERMS_NOT_ACCEPTED | Customer has not accepted the End User Terms | + enum: + - FORBIDDEN + - USER_NOT_READY + - COUNTERPARTY_NOT_ALLOWED + - VELOCITY_LIMIT_EXCEEDED + - END_USER_TERMS_NOT_ACCEPTED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true ExecuteQuoteRequest: type: object description: Optional body for executing a quote. Only needed to request a specific Strong Customer Authentication factor (`scaFactor`) for the challenge this call issues; omit the body entirely otherwise. @@ -22230,39 +22189,6 @@ components: type: string description: The UMA address of the customer claiming the invitation example: $invitee@uma.domain - Error403: - type: object - required: - - message - - status - - code - properties: - status: - type: integer - enum: - - 403 - description: HTTP status code - code: - type: string - description: | - | Error Code | Description | - |------------|-------------| - | FORBIDDEN | Insufficient permissions | - | USER_NOT_READY | Customer exists but is not ready for operation | - | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | - | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | - enum: - - FORBIDDEN - - USER_NOT_READY - - COUNTERPARTY_NOT_ALLOWED - - VELOCITY_LIMIT_EXCEEDED - message: - type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true SandboxSendRequest: type: object required: diff --git a/openapi/components/schemas/customers/Customer.yaml b/openapi/components/schemas/customers/Customer.yaml index f416046a2..63a206965 100644 --- a/openapi/components/schemas/customers/Customer.yaml +++ b/openapi/components/schemas/customers/Customer.yaml @@ -3,7 +3,6 @@ required: - umaAddress - platformCustomerId - customerType - - hasAcceptedEndUserTerms properties: id: type: string @@ -16,14 +15,12 @@ properties: example: 9f84e0c2a72c4fa customerType: $ref: ./CustomerType.yaml - hasAcceptedEndUserTerms: - type: boolean + endUserTermsConsent: + $ref: ./EndUserTermsConsent.yaml readOnly: true description: >- - Whether Grid has recorded the customer's acceptance of the End User Terms. - For platforms where acceptance is required, a value of `false` means the - customer cannot open an account until consent is recorded. - example: true + The customer's recorded acceptance of the End User Terms. Omitted until + acceptance has been recorded. region: type: string description: >- diff --git a/openapi/components/schemas/customers/CustomerUpdateRequest.yaml b/openapi/components/schemas/customers/CustomerUpdateRequest.yaml index 7f3c56a58..5b1292e15 100644 --- a/openapi/components/schemas/customers/CustomerUpdateRequest.yaml +++ b/openapi/components/schemas/customers/CustomerUpdateRequest.yaml @@ -49,3 +49,5 @@ properties: Optional UMA address identifier. If provided, the customer's UMA address will be updated. This is an optional identifier to route payments to the customer. example: $john.doe@uma.domain.com + endUserTermsConsent: + $ref: ./EndUserTermsConsentRequest.yaml diff --git a/openapi/components/schemas/customers/EndUserTermsConsent.yaml b/openapi/components/schemas/customers/EndUserTermsConsent.yaml index fe5a090d2..a80ca5cd9 100644 --- a/openapi/components/schemas/customers/EndUserTermsConsent.yaml +++ b/openapi/components/schemas/customers/EndUserTermsConsent.yaml @@ -1,9 +1,2 @@ allOf: - $ref: ./EndUserTermsConsentRequest.yaml - - type: object - required: - - customerId - properties: - customerId: - type: string - description: Unique Grid identifier for the customer. diff --git a/openapi/components/schemas/errors/Error403.yaml b/openapi/components/schemas/errors/Error403.yaml index c07ddfb47..d188da909 100644 --- a/openapi/components/schemas/errors/Error403.yaml +++ b/openapi/components/schemas/errors/Error403.yaml @@ -18,11 +18,13 @@ properties: | USER_NOT_READY | Customer exists but is not ready for operation | | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | + | END_USER_TERMS_NOT_ACCEPTED | Customer has not accepted the End User Terms | enum: - FORBIDDEN - USER_NOT_READY - COUNTERPARTY_NOT_ALLOWED - VELOCITY_LIMIT_EXCEEDED + - END_USER_TERMS_NOT_ACCEPTED message: type: string description: Error message diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index aeb83db8b..b6143351f 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}/end-user-terms-consent: - $ref: paths/customers/customers_{customerId}_end-user-terms-consent.yaml /customers/end-user-terms: $ref: paths/customers/customers_end-user-terms.yaml /customers/{customerId}/kyc-link: diff --git a/openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml b/openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml deleted file mode 100644 index c491e3de3..000000000 --- a/openapi/paths/customers/customers_{customerId}_end-user-terms-consent.yaml +++ /dev/null @@ -1,80 +0,0 @@ -get: - summary: Get a customer's End User Terms consent - description: Retrieve the End User Terms acceptance recorded for one customer. - operationId: getCustomerEndUserTermsConsent - tags: - - Customers - security: - - BasicAuth: [] - parameters: - - name: customerId - in: path - required: true - description: Unique Grid identifier for the customer. - schema: - type: string - responses: - '200': - description: End User Terms consent retrieved successfully - content: - application/json: - schema: - $ref: ../../components/schemas/customers/EndUserTermsConsent.yaml - '401': - description: Unauthorized - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error401.yaml - '404': - description: Customer or consent record not found - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error404.yaml -patch: - summary: Update a customer's End User Terms consent - description: Record or replace the End User Terms acceptance for one customer. - operationId: updateCustomerEndUserTermsConsent - tags: - - Customers - security: - - BasicAuth: [] - parameters: - - name: customerId - in: path - required: true - description: Unique Grid identifier for the customer. - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: ../../components/schemas/customers/EndUserTermsConsentRequest.yaml - responses: - '200': - description: End User Terms consent updated successfully - content: - application/json: - schema: - $ref: ../../components/schemas/customers/EndUserTermsConsent.yaml - '400': - description: Invalid input or unsupported terms version - 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 diff --git a/openapi/paths/quotes/quotes.yaml b/openapi/paths/quotes/quotes.yaml index 9fbfa63f2..84da3101a 100644 --- a/openapi/paths/quotes/quotes.yaml +++ b/openapi/paths/quotes/quotes.yaml @@ -140,6 +140,12 @@ post: application/json: schema: $ref: ../../components/schemas/errors/Error401.yaml + '403': + description: Customer has not accepted the End User Terms + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error403.yaml '412': description: Counterparty doesn't support UMA version content: diff --git a/openapi/webhooks/customer-update.yaml b/openapi/webhooks/customer-update.yaml index d8032e96a..bd000a915 100644 --- a/openapi/webhooks/customer-update.yaml +++ b/openapi/webhooks/customer-update.yaml @@ -47,7 +47,6 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000001 platformCustomerId: 9f84e0c2a72c4fa customerType: INDIVIDUAL - hasAcceptedEndUserTerms: false region: US currencies: - USD @@ -77,7 +76,11 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000002 platformCustomerId: 4b7c1e9d3f5a8e2 customerType: INDIVIDUAL - hasAcceptedEndUserTerms: true + endUserTermsConsent: + acceptedAt: '2025-07-21T17:30:00Z' + ipAddress: 203.0.113.42 + termsVersion: '2025-10-13' + acceptanceMethod: CHECKBOX region: US currencies: - USD @@ -100,7 +103,11 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000003 platformCustomerId: 7a2f9d4e1b8c3f5 customerType: BUSINESS - hasAcceptedEndUserTerms: true + endUserTermsConsent: + acceptedAt: '2025-07-21T17:30:00Z' + ipAddress: 203.0.113.42 + termsVersion: '2025-10-13' + acceptanceMethod: CHECKBOX region: US currencies: - USD @@ -131,7 +138,6 @@ post: id: Customer:019542f5-b3e7-1d02-0000-000000000004 platformCustomerId: 3c8e5f2a9d1b7e4 customerType: BUSINESS - hasAcceptedEndUserTerms: false region: US currencies: - USD From 18965e9f7138a1ead3dbea157420b2a6c3649162 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 5 Aug 2026 00:10:10 +0000 Subject: [PATCH 4/4] docs: Clarify customer consent requirement Co-Authored-By: bsiaotickchong --- mintlify/openapi.yaml | 2 ++ openapi.yaml | 2 ++ .../components/schemas/customers/CustomerCreateRequest.yaml | 5 +++++ .../components/schemas/customers/CustomerUpdateRequest.yaml | 4 ++++ 4 files changed, 13 insertions(+) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 6823c2d1e..a7214bfd8 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -12946,6 +12946,7 @@ components: example: $john.doe@uma.domain.com endUserTermsConsent: $ref: '#/components/schemas/EndUserTermsConsentRequest' + description: Evidence that the customer accepted the Grid End User Terms. Unregulated platforms must provide this before initiating customer-scoped transactions; those transactions fail until consent is recorded. This can be supplied during customer creation or in a later customer update. IndividualCustomerCreateRequest: title: Individual Customer Create Request allOf: @@ -13237,6 +13238,7 @@ components: example: $john.doe@uma.domain.com endUserTermsConsent: $ref: '#/components/schemas/EndUserTermsConsentRequest' + description: Evidence that the customer accepted the Grid End User Terms. Unregulated platforms must provide this before initiating customer-scoped transactions; those transactions fail until consent is recorded. IndividualCustomerUpdateRequest: title: Individual Customer Update Request allOf: diff --git a/openapi.yaml b/openapi.yaml index 6823c2d1e..a7214bfd8 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -12946,6 +12946,7 @@ components: example: $john.doe@uma.domain.com endUserTermsConsent: $ref: '#/components/schemas/EndUserTermsConsentRequest' + description: Evidence that the customer accepted the Grid End User Terms. Unregulated platforms must provide this before initiating customer-scoped transactions; those transactions fail until consent is recorded. This can be supplied during customer creation or in a later customer update. IndividualCustomerCreateRequest: title: Individual Customer Create Request allOf: @@ -13237,6 +13238,7 @@ components: example: $john.doe@uma.domain.com endUserTermsConsent: $ref: '#/components/schemas/EndUserTermsConsentRequest' + description: Evidence that the customer accepted the Grid End User Terms. Unregulated platforms must provide this before initiating customer-scoped transactions; those transactions fail until consent is recorded. IndividualCustomerUpdateRequest: title: Individual Customer Update Request allOf: diff --git a/openapi/components/schemas/customers/CustomerCreateRequest.yaml b/openapi/components/schemas/customers/CustomerCreateRequest.yaml index a82792e34..a3764774f 100644 --- a/openapi/components/schemas/customers/CustomerCreateRequest.yaml +++ b/openapi/components/schemas/customers/CustomerCreateRequest.yaml @@ -56,3 +56,8 @@ properties: example: $john.doe@uma.domain.com endUserTermsConsent: $ref: ./EndUserTermsConsentRequest.yaml + description: >- + Evidence that the customer accepted the Grid End User Terms. Unregulated + platforms must provide this before initiating customer-scoped + transactions; those transactions fail until consent is recorded. This + can be supplied during customer creation or in a later customer update. diff --git a/openapi/components/schemas/customers/CustomerUpdateRequest.yaml b/openapi/components/schemas/customers/CustomerUpdateRequest.yaml index 5b1292e15..12df32e28 100644 --- a/openapi/components/schemas/customers/CustomerUpdateRequest.yaml +++ b/openapi/components/schemas/customers/CustomerUpdateRequest.yaml @@ -51,3 +51,7 @@ properties: example: $john.doe@uma.domain.com endUserTermsConsent: $ref: ./EndUserTermsConsentRequest.yaml + description: >- + Evidence that the customer accepted the Grid End User Terms. Unregulated + platforms must provide this before initiating customer-scoped + transactions; those transactions fail until consent is recorded.