Skip to content

The Tellfox API

The Tellfox API lets another system read and change a business’s customers, bookings, packages and loyalty, and be told when something happens. It is a yearly add-on on the Business and Pro plans (Plan & add-ons → Add-ons). Everything below is for the developer who builds the connection.

  • Base address: https://api.tellfox.app/v1
  • Format: JSON in and out, UTF-8. Times in UTC (ISO 8601). Money in satang: whole numbers, 1 baht = 100 satang.
  • Machine-readable spec: OpenAPI 3.1, made from the same table the API runs on.

An owner makes keys on Settings → API in the Tellfox owner pages. Each key has:

  • a name (“Shop POS”): the activity feed shows it on everything the key does (“Shop POS gave a stamp”);
  • a system name (pos, crm): your system’s own customer IDs are kept under it (external_id);
  • scopes: what it may do (customers:read, customers:write, bookings:read, packages:write, loyalty:write, payments:read, …). A write scope also reads. Every key can read the business, its branches, services and team;
  • optionally, branches: then it sees and changes only bookings, services and team of those branches.

The secret is shown once. Tellfox keeps only a hash of it. Send it in every call:

Terminal window
curl https://api.tellfox.app/v1/business \
-H "Authorization: Bearer tfx_live_…"

GET /v1/business answers the business, its branches and what the key may do: a good first call. A key that was revoked answers 401 key_revoked at once. When the add-on’s year ends, or the plan is no longer Business or Pro, every key answers 403 addon_required (nothing is deleted; the keys work again when it is renewed).

A test key (tfx_test_…) works on a test copy of the business, made with the first test key: its branches, opening hours, team, services, rooms, packages, tags and loyalty program, but no customers or bookings. Nothing is ever sent to anyone from the test copy (no LINE messages, no emails). Try every call there first; the owner can make the copy again from the business as it is now (Make it again on Settings → API). The same code then works with a live key.

A success answers {"data": …} (a list also has "meta": {"next_cursor": …}). A create answers 201. An error answers its status and:

{ "error": { "code": "invalid", "message": "Not a phone number.", "field": "query.phone", "request_id": "req_…" } }
Status code What to do
400 bad_request, idempotency_key_required Fix the request (send JSON; send an Idempotency-Key with a write)
401 unauthorized, key_revoked Check the key
403 addon_required, scope_required, branch_forbidden The add-on is off, or the key may not do this
404 not_found No such thing in this business
409 conflict, idempotency_in_progress Look at the state, or retry a little later
422 invalid, plan_limit, idempotency_key_reused A value is wrong (field names it), or the plan allows no more
429 rate_limited, daily_limit Wait for Retry-After seconds
500 server_error Retry with the same Idempotency-Key

Every answer has an X-Request-Id header: give it to Tellfox support when you ask about a call.

  • 60 calls a minute per key. Above it: 429 rate_limited with Retry-After.
  • 10,000 calls a day per business (UTC day; live and test keys are counted apart). Above it: 429 daily_limit until tomorrow.
  • Lists answer at most 200 at a time (50 by default).

Lists answer a page and meta.next_cursor. Send it back as cursor for the next page; null means there is no more.

Terminal window
curl "https://api.tellfox.app/v1/customers?limit=100" -H "Authorization: Bearer $KEY"
curl "https://api.tellfox.app/v1/customers?limit=100&cursor=WyIyMDI2…" -H "Authorization: Bearer $KEY"

GET /v1/customers and GET /v1/bookings?updated_since=… answer the oldest change first, with updated_at (UTC). To sync:

  1. Read every page once with updated_since=1970-01-01T00:00:00Z and keep the largest updated_at you saw. (Without updated_since, bookings are listed by start time from now on, which is for showing a calendar, not for a sync.)
  2. Every few minutes, call again with updated_since set to one minute before it, read every page, and keep the new largest updated_at. The minute covers a change that was being saved while you read.

A customer’s updated_at moves with any change to the customer, their phone numbers and emails, tags, consent or IDs (their visit numbers follow the bookings instead); a booking’s with any change to it. You may see a row twice; you never miss one.

A customer the business erased on request (PDPA) is either anonymised (still listed, anonymised: true, name and contact details gone) or, when they had nothing else, deleted: read GET /v1/customers/erased with the same updated_since and delete your copy of those IDs.

To find one customer, use phone (any format: 081-234-5678 finds +66812345678), email, or your own external_id.

Every write (POST, PATCH, DELETE) needs an Idempotency-Key header: text up to 255 characters that is unique for all time, for example a UUID, or the date with your own sale number. Sending the same request again with the same key does nothing twice and answers the first answer (with the header Idempotent-Replayed: true); the key is kept 24 hours. The same key with a different request answers 422 idempotency_key_reused.

Writes go through the same rules as the owner pages: the plan’s limits, a key limited to some branches, and the messages customers usually get. Amounts always come from Tellfox’s own prices, never from the request.

Sending LINE messages and broadcasts, confirming and refunding payments, deleting customers, and changing the plan, team, opening hours, prices and settings are done in the owner pages, where a person decides.