Update customer by ID
Changed onUpdate a customer's metadata by their system-generated ID.
Most customer updates complete synchronously and return 200 with the updated customer. If the request changes email for a customer that has one or more tied Embedded Wallet internal accounts with EMAIL_OTP credentials, or changes phoneNumber for a customer that has one or more tied Embedded Wallet internal accounts with SMS_OTP credentials, the contact update uses the two-step signed-retry flow so the customer's wallet session authorizes the authentication credential update. On the signed retry, Grid updates the customer contact field and every tied matching OTP credential across all tied Embedded Wallets as one logical operation. If any tied credential cannot be updated, the customer contact field is not changed.
Update email and phoneNumber in separate PATCH calls. A request that includes both fields is rejected.
For an Embedded Wallet email or SMS auth phone update:
-
Call PATCH /customers/{customerId} with the full update body and no signature headers. Grid returns 202 with payloadToSign, requestId, and expiresAt. The pending challenge binds the submitted update fields and the set of tied Embedded Wallet OTP credentials that must be updated.
-
Use the session API keypair of a verified authentication credential on one of the customer's tied Embedded Wallets to build an API-key stamp over payloadToSign, then retry the same request with that full stamp as the Grid-Wallet-Signature header and the requestId echoed back as the Request-Id header. The retry body must carry the same update fields submitted in step 1. The signed retry returns 200 with the updated customer.
Request
- Base URL: https://api.lightspark.com/grid/2025-10-13
- URL: https://api.lightspark.com/grid/2025-10-13/customers/{customerId}
- Auth: HTTP basic
Headers
Full API-key stamp built over the prior payloadToSign with the session API keypair of a verified authentication credential on one of the customer's tied Embedded Wallets. Required on the signed retry for Embedded Wallet email or SMS auth phone updates; ignored on the initial call and on customer updates that complete synchronously.
The requestId returned in a prior 202 response, echoed back on the signed retry so the server can correlate it with the issued challenge. Required on the signed retry for Embedded Wallet email or SMS auth phone updates; must be paired with Grid-Wallet-Signature.
Request body
Example request
{
"customerType": "INDIVIDUAL",
"currencies": [
"USD",
"EUR",
"USDC"
],
"email": "john.doe@example.com",
"phoneNumber": "+14155551234",
"umaAddress": "$john.doe@uma.domain.com",
"endUserTermsConsent": {
"ipAddress": "198.51.100.24",
"termsVersion": "V1",
"acceptanceMethod": "CHECKBOX"
},
"agreementConsents": [
{
"type": "LIGHTSPARK_END_USER_TERMS",
"ipAddress": "198.51.100.24",
"termsVersion": "2025-10-13",
"acceptanceMethod": "CHECKBOX"
}
],
"kycStatus": "APPROVED",
"fullName": "John Michael Doe",
"birthDate": "1990-01-15",
"nationality": "US",
"address": {
"line1": "123 Main Street",
"line2": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"postalCode": "94105",
"country": "US"
},
"idType": "SSN",
"identifier": "123-45-6789",
"countryOfIssuance": "US",
"sourceOfFundsCategories": [
"SALARY"
],
"sourceOfFundsOtherDescription": "Contest winnings",
"sourceOfWealthCategories": [
"SALARY",
"INVESTMENTS"
],
"sourceOfWealthOtherDescription": "Royalty income from published works",
"purposeOfAccount": "CONTRACTOR_PAYOUTS",
"purposeOfAccountOtherDescription": "Household budgeting between spouses",
"expectedMonthlyTransactionCount": "COUNT_100_TO_500",
"expectedMonthlyTransactionVolume": "VOLUME_100K_TO_1M",
"annualIncomeRange": "RANGE_100K_250K",
"netWorthRange": "RANGE_500K_1M",
"pepStatus": "NONE"
}Response
Customer updated successfully. For Embedded Wallet email or SMS auth phone updates, this is returned only on the signed retry after the customer contact field and all tied matching OTP credentials have been updated.
Example response
{
"id": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"platformCustomerId": "9f84e0c2a72c4fa",
"customerType": "INDIVIDUAL",
"endUserTermsConsent": {
"ipAddress": "198.51.100.24",
"termsVersion": "V1",
"acceptanceMethod": "CHECKBOX"
},
"agreementConsents": [
{
"type": "LIGHTSPARK_END_USER_TERMS",
"ipAddress": "198.51.100.24",
"termsVersion": "2025-10-13",
"acceptanceMethod": "CHECKBOX"
}
],
"region": "US",
"currencies": [
"USD",
"USDC"
],
"email": "john.doe@example.com",
"phoneNumber": "+14155551234",
"umaAddress": "$john.doe@uma.domain.com",
"createdAt": "2025-07-21T17:32:28Z",
"updatedAt": "2025-07-21T17:32:28Z",
"contactVerification": {
"email": "VERIFIED",
"phone": "VERIFIED"
},
"kycStatus": "APPROVED",
"fullName": "John Michael Doe",
"birthDate": "1990-01-15",
"nationality": "US",
"address": {
"line1": "123 Main Street",
"line2": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"postalCode": "94105",
"country": "US"
},
"idType": "SSN",
"identifier": "123-45-6789",
"countryOfIssuance": "US",
"sourceOfFundsCategories": [
"SALARY"
],
"sourceOfFundsOtherDescription": "Contest winnings",
"sourceOfWealthCategories": [
"SALARY",
"INVESTMENTS"
],
"sourceOfWealthOtherDescription": "Royalty income from published works",
"purposeOfAccount": "CONTRACTOR_PAYOUTS",
"purposeOfAccountOtherDescription": "Household budgeting between spouses",
"expectedMonthlyTransactionCount": "COUNT_100_TO_500",
"expectedMonthlyTransactionVolume": "VOLUME_100K_TO_1M",
"annualIncomeRange": "RANGE_100K_250K",
"netWorthRange": "RANGE_500K_1M",
"pepStatus": "NONE"
}Changes
- breaking
added to the
//request propertyallOflist - breaking
added to the
//request propertyallOflist - breaking
the
//request property type changed fromobjectto no type - breaking
the
//request property type changed fromobjectto no type - warning
removed the request property
/// - warning
removed the request property
/// - warning
removed the request property
/// - warning
removed the request property
/// - warning
removed the request property
/// - warning
removed the request property
/// - warning
removed the request property
/// - warning
removed the request property
/// - info
added the new optional request property
// - info
added the new optional request property
// - info
request property
//deprecated - info
request property
//deprecated - info
added the optional property
/////to the response with the status - info
added the optional property
/////to the response with the status - info
the response optional property
/////became read-only for the status - info
the response optional property
/////became read-only for the status - info
added to the
/////response propertyallOflist for the response status - info
added to the
/////response propertyallOflist for the response status - info
removed from the
/////response propertyallOflist for the response status - info
removed from the
/////response propertyallOflist for the response status - info
response property
oneOf[subschema #1: Individual Customer]/allOf[Customer]/endUserTermsConsentdeprecated - info
response property
oneOf[subschema #2: Business Customer]/allOf[Customer]/endUserTermsConsentdeprecated
- breaking
- breaking
the
/////////request property's minItems was increased to1 - breaking
the
/////////request property's minItems was increased to1 - warning
the
/////////request property's maxLength was set to500 - warning
the
/////////request property's maxLength was set to500 - warning
the
/////////request property's maxLength was set to500 - warning
the
//////request property's maxLength was set to250 - warning
the
//////request property's maxLength was set to100 - warning
the
//request property's maxLength was set to255 - warning
the
///request property's maxLength was set to64 - warning
the
//////request property's maxLength was set to250 - warning
the
//////request property's maxLength was set to250 - warning
the
//////request property's maxLength was set to100 - warning
the
//////request property's maxLength was set to500 - warning
the
//////request property's maxLength was set to100 - warning
the
//request property's maxLength was set to255 - warning
the
///request property's maxLength was set to64
- breaking