Customer export
GET /customers/export sends the customers matching the same search and filters
as GET /customers as a CSV file. With no filters it sends every customer. The
office’s Export button on Customers uses it.
Asking
Section titled “Asking”GET /customers/export?purpose=marketing&kind=domesticAuthorization: Bearer btl_…| Parameter | What it is |
|---|---|
purpose |
all (the default) for every detail, or marketing for only the customers who granted channel. |
channel |
For marketing: email (the default), sms, phone or post. |
q |
Optional. Only customers whose name contains this. |
kind |
Optional. commercial (trade) or domestic (consumer). |
owing |
Optional. true for only customers with unpaid invoices. |
rateSet |
Optional. A price list’s id, or none for customers on no price list. |
marketing |
Optional. Only customers who granted this channel, as on GET /customers. |
includeArchived |
Optional. true to include archived customers. |
tenantId |
Optional. For a plain browser link, which cannot send X-Tenant-Id. Membership is checked the same way. |
Erased customers and customers merged into another are never in it.
Permission and limits
Section titled “Permission and limits”It needs customers:read, like GET /customers. Owners and admins have it;
drivers do not. An API key or connection needs it granted.
Each export reads every matching customer, so it counts against the business’s
allowance for heavy requests, and a business can start at most 5 exports a
minute. Past either, the answer is 429 with Retry-After in seconds.
Bottle staff looking at a business for support cannot export its customers
(403).
The file
Section titled “The file”UTF-8 with a byte order mark, so Excel shows accented names correctly, with
CRLF line ends and a header row. It is streamed a page of 500 customers at a
time, so a long list starts downloading straight away. The name is
customers-<business>-<date>.csv.
Any text cell starting with =, +, -, @, a tab or a carriage return has a
' put in front, so a spreadsheet shows it as text and never runs it as a
formula. A phone number written +44 … therefore arrives as '+44 ….
Amounts are in pounds and pence (12.50), not pence, and dates are UK calendar
days (2026-10-04).
purpose=all has these columns: Name, Legal name, Email, Phone, Address line 1,
Address line 2, Town or city, Postcode (their first delivery address in use),
Trade or consumer, Payment terms, Owed (£), Overdue (£), Email marketing, Text
message marketing, Phone call marketing, Post marketing (each Agreed, Withdrawn
or Not asked), Customer since, Last order, Orders. Orders counts the ones not
cancelled.
purpose=marketing has Name, Legal name, then only the contact the channel
needs (Email; Phone for sms and phone; the address lines and postcode for
post), Trade or consumer, Agreed on, How they agreed, Customer since, Last
order and Orders. A customer who cannot be reached that way is left out: no
email or one that bounced, no phone number, no address. The file is named
customers-for-<channel>-marketing-<business>-<date>.csv.
Consent comes from the customer’s marketing consent, the record the office and the shop both change.
The end of the file
Section titled “The end of the file”The last line of a complete file is End of file and the number of customers
in it. The response is streamed, so its status is sent before the first row;
if an error stops the export part way, the file ends with a line saying it is
not complete instead, and has no End of file line.
The record
Section titled “The record”Every export is written down as it starts: who made it (the person, or the key
or connection and its name), when, the purpose and the filters. A search is
kept only as having been used, never its words, which are often someone’s
name. When it ends the row gets the number of rows and how it ended:
finished, failed (stopped by an error) or cancelled (the download was
dropped).