Customers endpoints

The customers endpoints cover reading and writing customer records over the API: list (with filters and search), fetch a single customer, create a new one, and update fields on an existing one.

Customers are the accounts that log in to your storefront and place orders. See Customers for the underlying data model.

GET /api/v1/customers

List customers in your company.

Required scope: customers:read

Query parameters

ParamTypeDefaultDescription
limitinteger50Page size, capped at 100. See Pagination.
cursorstringPagination cursor from a previous response.
statusACTIVE / BLOCKEDFilter by customer status.
searchstringCase-insensitive substring match on email and name.

Example

curl "https://distribu.app/api/v1/customers?status=ACTIVE&limit=50" \
  -H "Authorization: Bearer dk_..."

Response

{
  "data": [
    {
      "id": "clxxcustomer1...",
      "email": "buyer@acme.com",
      "name": "Acme Restaurant Group",
      "status": "ACTIVE",
      "notes": "Weekly delivery, dock B.",
      "creditLimit": 5000,
      "taxRateOverride": 0.08,
      "emailVerified": true,
      "createdAt": "2026-03-01T12:00:00.000Z",
      "updatedAt": "2026-04-10T09:30:00.000Z"
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  }
}

Sorted by createdAt descending.

Notes on fields

  • name — Nullable. Some customers register with only an email.
  • notes — Nullable. Your internal notes; never shown to the customer.
  • creditLimit — Nullable decimal. For your records — Distribu doesn't enforce it at order placement.
  • taxRateOverride — Nullable decimal fraction between 0 and 0.3. When set, overrides the company-wide tax rate for this customer. null means "use the company default."
  • emailVerifiedtrue for customers who completed email verification (self-registered or invited contacts). CSV-imported customers start false until they complete a password reset.
  • Password — Not returned, ever.
  • Shipping addresses — Not returned by this endpoint. Use the dashboard or the storefront APIs for per-address detail.

GET /api/v1/customers/{id}

Fetch a single customer by ID.

Required scope: customers:read

Example

curl https://distribu.app/api/v1/customers/clxxcustomer1... \
  -H "Authorization: Bearer dk_..."

Response

{
  "data": {
    "id": "clxxcustomer1...",
    "email": "buyer@acme.com",
    "name": "Acme Restaurant Group",
    "status": "ACTIVE",
    "notes": "Weekly delivery, dock B.",
    "creditLimit": 5000,
    "taxRateOverride": 0.08,
    "emailVerified": true,
    "createdAt": "2026-03-01T12:00:00.000Z",
    "updatedAt": "2026-04-10T09:30:00.000Z"
  }
}

Errors

  • 404Customer not found. — No customer with that ID in your company.

POST /api/v1/customers

Create a new customer.

Required scope: customers:write

Request body

{
  "email": "buyer@acme.com",
  "name": "Acme Restaurant Group",
  "notes": "Weekly delivery, dock B.",
  "creditLimit": 5000,
  "taxRateOverride": 0.08,
  "status": "ACTIVE"
}
FieldTypeRequiredNotes
emailstringyesMust be unique within your company.
namestring | nullno1–200 chars when set.
notesstring | nullno0–2000 chars.
creditLimitnumber | nullno0–100,000,000.
taxRateOverridenumber | nullnoFraction 0–0.3 (e.g., 0.08 = 8%).
statusstringnoACTIVE (default) or BLOCKED.

Example

curl -X POST https://distribu.app/api/v1/customers \
  -H "Authorization: Bearer dk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "buyer@acme.com",
    "name": "Acme Restaurant Group",
    "creditLimit": 5000
  }'

Response

201 Created with the new customer.

{
  "data": {
    "id": "clxxcustomer1...",
    "email": "buyer@acme.com",
    "name": "Acme Restaurant Group",
    "status": "ACTIVE",
    "notes": null,
    "creditLimit": 5000,
    "taxRateOverride": null,
    "emailVerified": false,
    "createdAt": "2026-04-17T14:22:00.000Z",
    "updatedAt": "2026-04-17T14:22:00.000Z"
  }
}

API-created customers:

  • Start with no password — they can't log in to the storefront until they reset one. Send them the password-reset URL for your store (/store/{slug}/reset) so they can set one themselves.
  • Start with emailVerified: false — verified once they complete the reset flow.
  • Are identical in every other way to a customer who registered themselves.

Errors

StatusMessage
400Invalid JSON body.
400Email is required.
400Invalid email address.
400Credit limit must be between 0 and 100000000.
400Tax rate override must be between 0 and 0.3.
409A customer with this email already exists.

PATCH /api/v1/customers/{id}

Update fields on an existing customer.

Required scope: customers:write

Request body

Every field is optional — send only what you want to change.

{
  "name": "Acme Restaurant Group (Downtown)",
  "notes": "Weekly delivery, dock B. Ring for access.",
  "creditLimit": 7500,
  "taxRateOverride": null,
  "status": "ACTIVE"
}
FieldTypeNotes
namestring | nullSet to null to clear.
notesstring | nullSet to null to clear.
creditLimitnumber | nullSet to null to clear.
taxRateOverridenumber | nullSet to null to use the company default.
statusstringACTIVE or BLOCKED. Blocked customers can't log in.

email is immutable over the API — changing a customer's email address isn't supported today. Ask them to use a new account, or do it from the dashboard.

Example

# Block a customer
curl -X PATCH https://distribu.app/api/v1/customers/clxxcustomer1... \
  -H "Authorization: Bearer dk_..." \
  -H "Content-Type: application/json" \
  -d '{ "status": "BLOCKED" }'

Response

The full updated customer, same shape as GET /api/v1/customers/{id}.

Errors

StatusMessage
400Invalid JSON body.
400Credit limit must be between 0 and 100000000.
400Tax rate override must be between 0 and 0.3.
400Invalid status.
404Customer not found.

What's not here (yet)

  • DELETE /api/v1/customers/{id} — Not exposed. Block instead (PATCH { status: "BLOCKED" }). Deleting a customer would cascade over their order history, which is usually not what you want.
  • Customer contacts — the sub-users on a customer account (see Customer contacts) aren't reachable over the API yet.
  • Shipping addresses — not exposed.
  • Price overrides — not exposed over the API; manage from the dashboard.

Next: Webhooks endpoints.