Skip to content

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.

GET /customers/export?purpose=marketing&kind=domestic
Authorization: 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.

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).

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 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.

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).