Customer identity
Customer Data
Access and manage customer-related data including e-wallet balances, bulk imports, PDF tickets, and custom metadata.
E-Wallet & Balance
Retrieve e-wallet automatic reload configuration and balance history for a customer. Balance history tracks all e-wallet transactions (credits, debits, refunds).
GET/customers/{customerId}/ewallet_automatic_reloadGet E-Wallet Auto-Reload Config
Retrieve the automatic e-wallet reload configuration for a customer.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| customerId | integer | Yes | The unique identifier of the customer. |
Response
{
"status": 200,
"code": "customer_ewallet_automatic_reload_succeed",
"message": "Configuration retrieved successfully.",
"data": {
"automaticEwalletReloadActive": true,
"automaticEwalletReloadMinBalance": 500,
"automaticEwalletReloadAmount": 2000,
"automaticEwalletReloadCardId": 12345
}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customer_ewallet_automatic_reload_succeed" | Machine-readable application code for the result. |
| message | string | "Configuration retrieved successfully." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |
| data.automaticEwalletReloadActive | boolean | true | The automatic ewallet reload active value. |
| data.automaticEwalletReloadMinBalance | integer | 500 | The automatic ewallet reload min balance value. |
| data.automaticEwalletReloadAmount | integer | 2000 | The automatic ewallet reload amount value. |
| data.automaticEwalletReloadCardId | integer | 12345 | Identifier of the associated automatic ewallet reload card. |
Balance History
The full reference for GET /customers/{customerId}/balance_history (parameters, includes, and response schema) lives in the E-Wallet Balance & Transactions section.
In addition to the parameters documented there, the endpoint supports include=order and a date-range filter using unix timestamps: applyDate[gte]=1700000000&applyDate[lte]=1710000000.
GET/customers/{customerId}/balance_history/countGet Balance History Count
Retrieve the total number of balance history entries for a customer. Useful for pagination.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| customerId | integer | Yes | The unique identifier of the customer. |
Response
{
"status": 200,
"code": "balance_count_succeed",
"message": "Balance count retrieved.",
"data": {
"total": 142
}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "balance_count_succeed" | Machine-readable application code for the result. |
| message | string | "Balance count retrieved." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |
| data.total | integer | 142 | Total number of matching records. |
Customer Import
Bulk import customers from a file. The endpoint accepts a file upload and processes it asynchronously, streaming progress updates back to the client via chunked transfer encoding.
Streaming Response
This endpoint uses Transfer-Encoding: chunked to stream progress updates during the import. The final chunk contains the standard JSON response with import results (customers created, updated, and unchanged).
POST/customers/importImport Customers from File
Upload a CSV/Excel file to bulk import customers for a brand. Requires a file in multipart/form-data format.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | Yes | The brand ID to import customers into. |
| isMultiBadge | boolean | No | If true, the file format supports multiple badges per customer. |
| autoImportGuestHierarchy | boolean | No | If true, automatically creates guest group hierarchy from the file data. |
Request Body
multipart/form-data with a 'file' field containing the CSV or Excel file.Response
{
"status": 200,
"code": "customers_import_create_succeed",
"message": "Import completed successfully.",
"data": {
"customersCreated": 15,
"customersUpdated": 3,
"customersUnchanged": 82
}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customers_import_create_succeed" | Machine-readable application code for the result. |
| message | string | "Import completed successfully." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |
| data.customersCreated | integer | 15 | The customers created value. |
| data.customersUpdated | integer | 3 | The customers updated value. |
| data.customersUnchanged | integer | 82 | The customers unchanged value. |
POST/customers/import_phoenixImport Phoenix Customer File
Upload a Phoenix-formatted customer file for a brand. The endpoint streams text progress chunks and ends with the standard JSON result payload.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | Yes | Brand that owns the imported customers. |
Request Body
file=[binary]Request Body Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Required | Example | Description |
|---|---|---|---|---|
| file | binary | Yes | [binary] | Phoenix-formatted customer file uploaded as multipart/form-data. |
Response
{
"status": 200,
"code": "customers_import_create_succeed",
"message": "Customers have been imported successfully.",
"data": {
"customersCreated": 15,
"customersUpdated": 3,
"customersUnchanged": 82,
"customersError": [
{
"line": 7,
"email": "invalid@example.com",
"invalidFields": [
"email"
]
}
],
"customersWarn": [
{
"line": 8,
"email": "duplicate@example.com",
"invalidFields": [
"email"
]
}
],
"otherWarnings": [
{
"type": "pricingRule",
"list": [
"UNKNOWN-RULE"
]
}
],
"validationErrors": []
}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customers_import_create_succeed" | Machine-readable application code for the result. |
| message | string | "Customers have been imported successfully." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |
| data.customersCreated | integer | 15 | The customers created value. |
| data.customersUpdated | integer | 3 | The customers updated value. |
| data.customersUnchanged | integer | 82 | The customers unchanged value. |
| data.customersError | array | […] | List of customers error entries. |
| data.customersError[] | object | {…} | Object containing customers error fields. |
| data.customersError[].line | integer | 7 | The line value. |
| data.customersError[].email | string | "invalid@example.com" | Email address. |
| data.customersError[].invalidFields | array | […] | List of invalid fields entries. |
| data.customersError[].invalidFields[] | string | "email" | The invalid fields value. |
| data.customersWarn | array | […] | List of customers warn entries. |
| data.customersWarn[] | object | {…} | Object containing customers warn fields. |
| data.customersWarn[].line | integer | 8 | The line value. |
| data.customersWarn[].email | string | "duplicate@example.com" | Email address. |
| data.customersWarn[].invalidFields | array | […] | List of invalid fields entries. |
| data.customersWarn[].invalidFields[] | string | "email" | The invalid fields value. |
| data.otherWarnings | array | […] | List of other warnings entries. |
| data.otherWarnings[] | object | {…} | Object containing other warnings fields. |
| data.otherWarnings[].type | string | "pricingRule" | The type value. |
| data.otherWarnings[].list | array | […] | List of list entries. |
| data.otherWarnings[].list[] | string | "UNKNOWN-RULE" | The list value. |
| data.validationErrors | array | [] | List of validation errors entries. |
Customer Base Export
Export a filtered customer base directly as CSV or XLSX. If a large export cannot complete within the synchronous request window, request the asynchronous report instead and retrieve it from report generation.
GET/customers/exportExport Customer Base File
Returns a CSV or XLSX attachment. The export is scoped to the requested brand and supports the same filters as the customer list.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | Yes | Brand whose customers are exported. |
| fileType | string | Yes | Output format: csv or xlsx. |
| restaurantIds | string | No | Comma-separated restaurant IDs used to filter the export. |
| search | string | No | Free-text customer search filter. |
| groups | string | No | Comma-separated customer-group filters. |
| mustDisplayArchivedCustomers | boolean | No | Include archived customers when true. |
Response
Binary attachment. Content-Type is text/csv for csv or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet for xlsx; Content-Disposition contains the filename.GET/customers/export/asyncRequest Asynchronous Customer Base Export
Creates a report-generation request for the same export filters. Use this when the synchronous export times out or for large customer bases.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | Yes | Brand whose customers are exported. |
| fileType | string | Yes | Requested output format: csv or xlsx. |
| restaurantIds | string | No | Comma-separated restaurant IDs used to filter the export. |
| search | string | No | Free-text customer search filter. |
| groups | string | No | Comma-separated customer-group filters. |
| mustDisplayArchivedCustomers | boolean | No | Include archived customers when true. |
Response
{
"status": 200,
"code": "customer_base_export_request_created",
"message": "Customer base export request is created successfully."
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customer_base_export_request_created" | Machine-readable application code for the result. |
| message | string | "Customer base export request is created successfully." | Human-readable result message. Do not use this value for program logic. |
Retrieve Generated Reports
An asynchronous export is made available through report generation. Brand and restaurant users see only reports they created. Admin and brand-group users must provide brandId when they do not have a brand context, and can include impersonatedUserId to see reports created by that user.
GET/report_generationList Generated Reports
Lists generated report files in the caller scope. Customer-base export reports become expired after their retention window; use expired to avoid requesting an unavailable download.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | No | Brand context required for an admin or brand-group user who has no own brand. |
| impersonatedUserId | integer | No | Optional impersonated user whose reports are included for an authorized admin or brand-group caller. |
Response
{
"status": 200,
"code": "report_generations_succeed",
"message": "The list of report generations have been found.",
"data": [
{
"reportGenerationId": 812,
"name": "customer-base-export-3325-2026-07-11.xlsx",
"createdAt": "Fri Jul 11 2026 09:15:00 GMT+0000 (Coordinated Universal Time)",
"reportType": "customer_base_export",
"status": "succeed",
"expired": false
}
]
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "report_generations_succeed" | Machine-readable application code for the result. |
| message | string | "The list of report generations have been found." | Human-readable result message. Do not use this value for program logic. |
| data | array | […] | Endpoint-specific response payload. |
| data[] | object | {…} | Endpoint-specific response payload. |
| data[].reportGenerationId | integer | 812 | Identifier of the associated report generation. |
| data[].name | string | "customer-base-export-3325-2026-07-11.xlsx" | The name value. |
| data[].createdAt | string | "Fri Jul 11 2026 09:15:00 GMT+0000 (Coordinated Universal Time)" | Timestamp when this resource was created. |
| data[].reportType | string | "customer_base_export" | The report type value. |
| data[].status | string | "succeed" | HTTP status code returned by the API. |
| data[].expired | boolean | false | The expired value. |
GET/report_generation/{reportGenerationId}/signed-urlGet Generated Report Download URL
Returns a time-limited signed URL for a generated report after verifying that the report belongs to the requested brand and to the caller (or authorized impersonated user). Expired or missing files cannot be downloaded.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| reportGenerationId | integer | Yes | Generated report identifier returned by the list endpoint. |
| brandId | integer | No | Brand context required for an admin or brand-group user who has no own brand. |
| impersonatedUserId | integer | No | Optional impersonated user whose report is being downloaded by an authorized caller. |
Response
{
"status": 200,
"code": "report_generations_succeed",
"message": "The list of report generations have been found.",
"data": {
"url": "https://storage.googleapis.com/<signed-report-url>"
}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "report_generations_succeed" | Machine-readable application code for the result. |
| message | string | "The list of report generations have been found." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |
| data.url | string | "https://storage.googleapis.com/<signed-report-url>" | The url value. |
POST/customers/{customerId}/unarchiveUnarchive Customer
Restores an archived customer. Brand and brand-group users may only restore a customer in a brand they are authorized to manage.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| customerId | integer | Yes | Archived customer to restore. |
Response
{
"status": 200,
"code": "customer_unarchive_succeed",
"message": "Customer has been successfully unarchived.",
"data": {
"success": true
}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customer_unarchive_succeed" | Machine-readable application code for the result. |
| message | string | "Customer has been successfully unarchived." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |
| data.success | boolean | true | The success value. |
Customer Tickets
Generate PDF receipts for individual orders or export a customer's receipt history as a PDF. Bulk exports can be counted and paginated before downloading to keep large histories manageable.
Single Ticket PDF
GET/orders/tickets/{orderId}Get Ticket PDF
Generate and download a PDF receipt for a specific order. Returns the file directly as application/pdf.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| orderId | string | Yes | The unique identifier of the order. |
Response
Binary PDF file (Content-Type: application/pdf). The response is an attachment; read the filename from the Content-Disposition response header.Bulk PDF Export
First count the selected customer history, then request a PDF. For very large histories, uselimit and offset to retrieve bounded batches. A date range must include bothstartDate and endDate.
GET/orders/tickets/export/countCount Tickets Available for Export
Returns the number of customer tickets matching the optional inclusive ISO-date range.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| customerId | integer | Yes | Customer whose tickets are counted. |
| startDate | string | No | ISO 8601 start of the export range. Required together with endDate. |
| endDate | string | No | ISO 8601 end of the export range. Required together with startDate. |
Response
{
"count": 142
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| count | integer | 142 | Total number of matching records. |
POST/orders/tickets/exportDownload Customer Ticket History PDF
Generates a PDF attachment for the selected customer history. The X-Total-Count response header contains the total matching records before pagination; Content-Disposition contains the filename.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| customerId | integer | Yes | Customer whose tickets are exported. |
| startDate | string | No | ISO 8601 start of the export range. Required together with endDate. |
| endDate | string | No | ISO 8601 end of the export range. Required together with startDate. |
| limit | integer | No | Positive maximum number of tickets included in this PDF batch. |
| offset | integer | No | Zero-based number of matching tickets to skip before this batch. |
Response
Binary PDF file (Content-Type: application/pdf). Read the total matching ticket count from X-Total-Count and the filename from Content-Disposition.Customer Metadata
Store and retrieve arbitrary metadata for a customer within a specific brand context. Metadata is stored as a free-form string and can be organized by namespace.
Namespaces
The optional namespace field allows you to organize metadata into logical groups (e.g., "preferences", "loyalty", "external_ids"). When deleting, you can target a specific namespace or remove all metadata at once.
POST/brands/{brandId}/customers/{customerId}/metadataSave Customer Metadata
Create or update metadata for a customer. If metadata with the same namespace already exists, it will be overwritten.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | Yes | The brand ID. |
| customerId | integer | Yes | The unique identifier of the customer. |
Request Body
{
"data": "{\"preferredLanguage\":\"fr\",\"dietaryRestrictions\":[\"vegetarian\"]}",
"namespace": "preferences"
}Request Body Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| data | string | "{\"preferredLanguage\":\"fr\",\"dietaryRestrictions\":[\"vegetarian\"]}" | Endpoint-specific response payload. |
| namespace | string | "preferences" | The namespace value. |
Response
{
"status": 200,
"code": "customer_metadata_saved",
"message": "Metadata saved successfully.",
"data": {
"customerMetadataId": 1234,
"customerId": 5337578,
"brandId": 100,
"data": "{\"preferredLanguage\":\"fr\",\"dietaryRestrictions\":[\"vegetarian\"]}",
"namespace": "preferences"
}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customer_metadata_saved" | Machine-readable application code for the result. |
| message | string | "Metadata saved successfully." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |
| data.customerMetadataId | integer | 1234 | Identifier of the associated customer metadata. |
| data.customerId | integer | 5337578 | Identifier of the customer. |
| data.brandId | integer | 100 | Identifier of the brand. |
| data.data | string | "{\"preferredLanguage\":\"fr\",\"dietaryRestrictions\":[\"vegetarian\"]}" | Endpoint-specific response payload. |
| data.namespace | string | "preferences" | The namespace value. |
GET/brands/{brandId}/customers/{customerId}/metadataGet Customer Metadata
Retrieve all metadata entries for a customer within a brand.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | Yes | The brand ID. |
| customerId | integer | Yes | The unique identifier of the customer. |
Response
{
"status": 200,
"code": "customer_metadata_fetched",
"message": "Metadata retrieved successfully.",
"data": [
{
"customerMetadataId": 1234,
"customerId": 5337578,
"brandId": 100,
"data": "{\"preferredLanguage\":\"fr\",\"dietaryRestrictions\":[\"vegetarian\"]}",
"namespace": "preferences"
},
{
"customerMetadataId": 1235,
"customerId": 5337578,
"brandId": 100,
"data": "{\"externalId\":\"EXT-99887\"}",
"namespace": "external_ids"
}
]
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customer_metadata_fetched" | Machine-readable application code for the result. |
| message | string | "Metadata retrieved successfully." | Human-readable result message. Do not use this value for program logic. |
| data | array | […] | Endpoint-specific response payload. |
| data[] | object | {…} | Endpoint-specific response payload. |
| data[].customerMetadataId | integer | 1234 | Identifier of the associated customer metadata. |
| data[].customerId | integer | 5337578 | Identifier of the customer. |
| data[].brandId | integer | 100 | Identifier of the brand. |
| data[].data | string | "{\"preferredLanguage\":\"fr\",\"dietaryRestrictions\":[\"vegetarian\"]}" | Endpoint-specific response payload. |
| data[].namespace | string | "preferences" | The namespace value. |
DELETE/brands/{brandId}/customers/{customerId}/metadataDelete Customer Metadata
Delete metadata for a customer. Optionally filter by namespace to only delete a specific set.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brandId | integer | Yes | The brand ID. |
| customerId | integer | Yes | The unique identifier of the customer. |
| namespace | string | No | If provided, only metadata with this namespace will be deleted. If omitted, all metadata for the customer is deleted. |
Response
{
"status": 200,
"code": "customer_metadata_deleted",
"message": "Metadata deleted successfully.",
"data": {}
}Response Properties
Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.
| Property | Type | Example | Description |
|---|---|---|---|
| status | integer | 200 | HTTP status code returned by the API. |
| code | string | "customer_metadata_deleted" | Machine-readable application code for the result. |
| message | string | "Metadata deleted successfully." | Human-readable result message. Do not use this value for program logic. |
| data | object | {…} | Endpoint-specific response payload. |