GET /v1/customers
List the store's customers live
| Key | Required. See Authentication. |
|---|---|
| Capability | customer-access |
| Scope | customers.read.all |
| Price | 1 credit, per page of 100 rows returned. How pricing works. |
| Estimate | Add estimate=true for a free quote. With estimate=true the 200 body is EstimateResponse (a priced quote for exactly this request), not the schema documented under responses.200; nothing is reserved or dispatched. |
| Paging | Follow nextCursor. See Paging. |
Example
curl -s "https://api.compudime.com/v1/customers" \
-H "Authorization: Bearer $PUBLIC_API_KEY"
Parameters
| Name | In | Type | Description |
|---|---|---|---|
fields | query | string | Comma-separated customers fields to include (see x-compudime-field-catalog), or * for every field the key may see. Omitted: a flat-priced endpoint returns every field; once IT prices the endpoint by field count (includedFields in x-compudime-pricing), an omitted fields returns the standard set at the base price and each field beyond the included count adds extraFieldCost. An unknown or denied field is a free 400 field_not_allowed. |
limit | query | integer | How many customers to return: any whole number of 1 or more; default 100 (one page). The store is read 200 at a time, so a larger limit is read from the store in several reads, one after another, and answered at once. One answer carries at most 10,000 (a safeguard on the size of one answer, not a limit on the listing); a larger limit ends with nextCursor. There is no time limit on reading: an answer that needs several reads keeps reading until it holds limit rows (at most 10,000) or the listing ends. While it reads, the response is already open: its body starts with spaces (legal JSON whitespace, sent every few seconds so no proxy closes an idle connection), and X-Credits-Charged and X-Credits-Remaining are not response headers but HTTP trailers, which reach HTTP/2 clients (on api.compudime.com and compudime-public-api.fly.dev alike) and are dropped over HTTP/1.1. The billing block in the body always says what the call cost (totalCredits per unit times quantity); /v1/usage/current gives the balance. When this API or the store is busy with other long answers, an answer may end after its first read with nextCursor instead. A page can hold fewer rows than limit while nextCursor is set: keep following nextCursor until it is empty. At access level own a page holds at most 25 customers whatever limit asks (x-compudime-access-level). Default: 100. At least 1. |
cursor | query | string | nextCursor from the previous page, verbatim. Omit for the first page; an empty nextCursor means the last page. At most 512 characters. Pattern: ^WyJ[A-Za-z0-9_-]{1,509}$ |
modifiedSince | query | string (date-time) | Only customers modified at or after this RFC3339 timestamp (incremental sync; compare with modifiedAt). A store whose POS keeps no customer modification time answers 422 modified_since_unsupported. |
estimate | query | boolean | When true, returns EstimateResponse instead of the normal body and never reserves credits: the request is authenticated, authorized and field-resolved exactly like a real call, then priced by billing (base cost plus extra-field credits for the resolved fields) and returned without dispatching to the store. Free of charge. Default: false. |
Responses
| Status | Description | Body |
|---|---|---|
200 | One live page of the store's customers in a stable order, with the cursor for the next page. At access level own, only the customers linked to this integration, in phone order. | CustomerListResponse |
400 | limit is not a whole number of 1 or more, cursor is not one a previous page issued (at this integration's access level), or modifiedSince is not an RFC3339 timestamp (code bad_request); or a requested field is not allowed, including account without the owner's grant (code field_not_allowed). Rejected before billing, except a cursor of the other access level, which is refused once read and released, never charged. | Problem |
401 | Public API key is missing, invalid, or revoked. | Problem |
402 | The request was blocked by billing policy: no_api_plan (no plan funds this meter), billing_card_missing, billing_card_failed, usage_exhausted, overage_cap_reached, subscription_paused, sandbox_exhausted, or billing_blocked. A key the store pays for under its approval gets grant_cap_exceeded (the store's monthly limit for your calls) or payer_billing_blocked (the store cannot be charged right now; ask the store owner) instead: what is wrong with the store's billing is not shown to it. | Problem |
403 | The API key is not enabled for this endpoint. | Problem |
405 | The requested method is not allowed for this endpoint. | Problem |
422 | The store cannot answer the request as asked: modified_since_unsupported (its POS keeps no customer modification time; list without modifiedSince) or account_unsupported (its POS has no customer account figures; request without account). The reservation is released, nothing is charged. | Problem |
429 | Too many requests from this API key (code rate_limited). Each key has its own request budget at the API edge, refilled continuously; it covers every authenticated endpoint, including the free ones, and is checked before anything is billed or sent to the store. Billed endpoints are also subject to the store plan's per-minute ceiling, which answers the same problem code. Wait at least Retry-After seconds before the next request with this key, then resume; if 429 answers again, back off exponentially (double the wait each time, up to a minute or so) and add random jitter so parallel workers do not retry in step. A 429 is never charged and reserves nothing. Header Retry-After: Whole seconds to wait before retrying with this key: the time until the key's next request token at the edge (never less than 1), or 60 when the store plan's per-minute ceiling refused the call. | Problem |
500 | The API edge encountered an internal error. | Problem |
502 | The store's POS could not complete the customer list (code store_error): the agent answered an error, its customer reads are not enabled, or the agent or relay build predates this operation. The reservation is released. | Problem |
503 | The store's POS agent is offline (code store_offline), or a Public API dependency is unavailable. The reservation is released. Also answered, with code endpoint_disabled, while CompuDime has temporarily switched the endpoint off: the whole API, the endpoint's family (x-compudime-family) or this endpoint alone; the detail says which and why. It is checked before anything is validated, reserved or sent to the store, so it is never charged; it is retryable and carries Retry-After. Header Retry-After: Sent with code endpoint_disabled: whole seconds to wait before asking again. A switch has no scheduled end, so this is a polling interval (60), not a promise. | Problem |
504 | The store did not answer inside the read ceiling (code store_timeout). The reservation is released. | Problem |
Error bodies are problem JSON; every code is listed there.
Fields
Choose with fields=; see Choosing fields.
| All fields | posCustomerId, firstName, lastName, company, addressLine1, addressLine2, city, state, postalCode, email, phones, custLevel, cat, tagList, matchedOn, modifiedAt |
|---|---|
| Standard set | posCustomerId, firstName, lastName, company, addressLine1, addressLine2, city, state, postalCode, email, phones, custLevel, cat, tagList, matchedOn, modifiedAt |
| Only when allowed | account. Sensitive: returned only when you name them and the store owner allowed them for your integration. |
Access level
What your integration's access level changes here.
| Level | Scope | Effect |
|---|---|---|
own | customers.read.self | Pages only the customers linked to this integration: the customers its own orders (POST /v1/orders) landed on in the store's POS, matched by the customer's main phone. They come in phone order, at most 25 a page whatever limit asks, and a page can hold fewer (even none) while nextCursor is set, when a linked customer is no longer on file. The cursor is this level's own; a cursor issued at the other level is a 400. modifiedSince keeps the linked customers modified at or after it, and every linked customer without a modifiedAt. An integration with no linked customer gets an empty page. |
all | customers.read.all | Pages the store's whole customer file. |