Skip to main content

Customers

A customer is the entity that purchases goods or services from a merchant. A customer may be a person or an organization. Every customer has a unique id referenced from other resources as customerId.

A customer is the main resource for most integrations — payment instruments, subscriptions, transactions, and invoices all hang off a customer.

Default payment instrument

A customer may have a default payment instrument. The default is used:

  • To automatically pay subscription renewals.
  • For transaction requests where no specific paymentInstrumentId or token is provided in paymentInstruction.

A customer can hold multiple payment instruments. Only one is the default at any time. Setting a new default does not deactivate the previous one — it stays attached and chargeable by its ID.

For how payment instruments are created and how their state changes, see Payment instruments and Payment instrument lifecycle.

Relation to other resources

ResourceRelation
Payment instrumentsA customer owns zero or more instruments. One can be default.
SubscriptionsA subscription always points at one customerId and one paymentInstrumentId.
TransactionsEvery transaction references a customerId.
InvoicesInvoices are addressed to a customerId.

Customer API

The Public API exposes five operations on the customer resource: POST to create, GET to retrieve one or list many, PATCH to update partial fields, and PUT to upsert.

Create a customer

curl -X POST \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/customers" \
-H 'Content-Type: application/json' \
-H "Authorization: ApiKey ${API_KEY}" \
-d '{
"firstName": "Jane",
"lastName": "Doe",
"email": "[email protected]",
"phoneNumber": "5550100",
"isEnhancedDueDiligenceRequired": false,
"primaryAddress": {
"customerAddress": {
"address1": "123 Main St",
"address2": "Apt 4B",
"country": "US",
"city": "Springfield",
"region": "IL",
"zip": "62701"
}
}
}'

All fields are optional.

FieldNotes
firstNameMax 45 characters.
lastNameMax 45 characters.
organizationMax 255 characters. The customer's employer or organization name (free-form). Not the same as the organizationId URL parameter.
emailStandard email format.
phoneNumberMax 10 characters. The phone number only — does not include a country/area code.
isEnhancedDueDiligenceRequiredBoolean, default false. Marks the customer as requiring Enhanced Due Diligence (EDD) for KYC/AML processing. See KYC overview.
primaryAddressObject with a single nested customerAddress field. See below.

primaryAddress.customerAddress

FieldNotes
address1Max 60 characters. Street line 1.
address2Max 60 characters. Street line 2 (apartment, suite, etc.).
countryMax 2 characters. ISO 3166-1 alpha-2 country code (US, DE, etc.).
cityMax 45 characters.
regionMax 45 characters. State or province.
zipMax 10 characters. Postal/ZIP code.

Returns 201 Created with the created Customer object. Store its id — every later operation against this customer references it.

Address field names differ across endpoints and operations. Create uses primaryAddress.customerAddress.{address1, ...}. Update (PATCH) uses a flat address.{address1, ...}. Upsert (PUT) uses a flat primaryAddress.{address1, ...}. The tokenization production endpoint uses billingAddress.{address, ...} with postalCode instead of zip. Map your billing form to the correct field names per endpoint — they are not interchangeable.

Retrieve a customer

curl -X GET \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/customers/${CUSTOMER_ID}?showTestData=false" \
-H "Authorization: ApiKey ${API_KEY}"
Query parameterNotes
showTestDataBoolean. Includes test data in the response when true.

Response shape:

{
"type": "object",
"data": {
"firstName": "Jane",
"lastName": "Doe",
"organization": "Acme Inc.",
"email": "[email protected]",
"phoneNumber": "5550100",
"isEnhancedDueDiligenceRequired": false,
"primaryAddress": {
"customerAddress": {
"address1": "123 Main St",
"address2": "Apt 4B",
"country": "US",
"city": "Springfield",
"region": "IL",
"zip": "62701"
}
}
}
}

List customers

curl -X GET \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/customers?limit=20&offset=0" \
-H "Authorization: ApiKey ${API_KEY}"
Query parameterTypeNotes
limitinteger 0–100, default 20Pagination page size.
offsetinteger ≥0Pagination offset.
searchstringFree-text search (for example, by email).
showTestDatabooleanIncludes test data in the response when true.
sortByenumOne of createdAt, email, name, country, lifetimeRevenue, lastPaymentTime.
sortDirectionenumasc or desc.
revenueMin / revenueMaxnumberFilter by lifetime revenue range (numeric monetary value).
createdFrom / createdTodate-timeFilter by creation date range.
lastPaymentFrom / lastPaymentTodate-timeFilter by last payment date range.
countriesarray of stringsISO country codes (for example, countries=US).
primaryPaymentInstrumentMethodsarray of PaymentMethodEnumFilter by the customer's primary payment instrument method (payment-card, ach, paypal, etc.).
isVipbooleanFilter to VIP customers only.

Response shape:

{
"type": "list",
"totalCount": 100,
"paginationMeta": {
"limit": 10,
"offset": 10
},
"data": [
{ "firstName": "Jane", "lastName": "Doe", "...": "..." }
]
}

Update a customer (PATCH)

Partial update — pass only the fields you want to change. All fields are optional.

curl -X PATCH \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/customers/${CUSTOMER_ID}" \
-H 'Content-Type: application/json' \
-H "Authorization: ApiKey ${API_KEY}" \
-d '{
"email": "[email protected]",
"phoneNumber": "5550199",
"tags": ["vip"],
"address": {
"country": "US",
"address1": "456 Oak Ave",
"city": "Chicago",
"region": "IL",
"zip": "60601"
},
"primaryPaymentInstrument": {
"method": "payment-card",
"id": "92dcc8b0-0872-4858-9f01-d6ecc724b4a9"
}
}'
FieldNotes
firstNameMax 45 characters.
lastNameMax 45 characters.
emailStandard email format.
phoneNumberMax 10 characters.
organizationMax 255 characters.
tagsArray of CustomerTag enum values: discounted, vip.
addressObject with flat structure: country, address1, address2, city, region, zip. Note: PATCH uses address at the top level, not the nested primaryAddress.customerAddress shape used by Create.
primaryPaymentInstrumentObject with method (PaymentMethodEnum) and id (UUID of the payment instrument). Sets which payment instrument is the customer's default.

Upsert a customer (PUT)

Create the customer at the given customerId if it does not exist, or replace the full resource if it does. Use PATCH for partial updates; use PUT only when you want to overwrite the full object.

curl -X PUT \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/customers/${CUSTOMER_ID}" \
-H 'Content-Type: application/json' \
-H "Authorization: ApiKey ${API_KEY}" \
-d '{
"firstName": "Jane",
"lastName": "Doe",
"email": "[email protected]",
"phoneNumber": "5550199",
"organization": "Acme Inc.",
"isEnhancedDueDiligenceRequired": false,
"primaryAddress": {
"address1": "456 Oak Ave",
"address2": "",
"country": "US",
"city": "Chicago",
"region": "IL",
"zip": "60601",
"dateOfBirth": "1990-04-12T00:00:00Z",
"jobTitle": "Engineer"
}
}'

Body fields are the same as Create, with two differences:

  • primaryAddress is flat (no customerAddress wrapper).
  • primaryAddress accepts two extra fields available only on PUT — they are not accepted by Create (POST) or Update (PATCH), and are not returned by Retrieve (GET):
FieldNotes
dateOfBirthISO 8601 date-time. The customer's date of birth.
jobTitleString. The customer's job title.

Returns 201 Created.

Custom fields on customers

You can attach merchant-specific structured data to a customer using custom fields. Define the schema once with POST /custom-fields (resource: customers), then populate per-customer values via the customer endpoint. See Custom fields.