Get started
Getting started
Three steps: create a test key in Sansflow, call the API with it, and switch to a live key when your integration works.
Before you start
- The business you build for is on Sansflow Premium. The API, webhooks and MCP are part of it.
- Someone who can manage the API in that business (the owner, or a role with that permission) creates the key. Usually that is the owner, who then hands it to you.
- Any HTTP client works. The examples use cURL, JavaScript (
fetch, Node 18 or later) and Python (requests).
Create a test key
- Open Developers Log in at pos.sansflow.com/developers and open the API keys tab.
- Create a key in test mode Give it a name you will recognise later, tick the
business.readscope for this guide, and leave the outlet on all outlets. - Copy it now The key starts with
sf_test_and is shown once. Sansflow stores only its SHA-256 hash, so it cannot show it again. Put it in an environment variable, not in your code.
export SANSFLOW_API_KEY="sf_test_…"Make your first call
Ask for the outlets the key may read. Every request sends the key as a Bearer token; there is nothing else to set up.
curl https://ewpuclvmnygoddunkyrb.supabase.co/functions/v1/api-v1-locations \
-H "Authorization: Bearer $SANSFLOW_API_KEY"const res = await fetch("https://ewpuclvmnygoddunkyrb.supabase.co/functions/v1/api-v1-locations", {
headers: { Authorization: `Bearer ${process.env.SANSFLOW_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code} (request ${body.error.request_id})`);
console.log(body.data); // the outlets this key may readimport os, requests
res = requests.get(
"https://ewpuclvmnygoddunkyrb.supabase.co/functions/v1/api-v1-locations",
headers={"Authorization": f"Bearer {os.environ['SANSFLOW_API_KEY']}"},
timeout=10,
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']} (request {body['error']['request_id']})")
print(body["data"]) # the outlets this key may readA working key answers 200 with a data array and a request_id:
{
"data": [
{
"id": "6f1c2a4e-…",
"name": "Main",
"type": "storefront",
"is_default": true,
"is_active": true,
"address": null,
"phone": null,
"receipt_name": null,
"operating_hours": null,
"tax": { "enabled": false, "rate": null, "label": null }
}
],
"request_id": "…"
}If you get 401 invalid_key, the key was mistyped or revoked. 403 insufficient_scope means it lacks business.read. 402 payment_required means the business is not on Sansflow Premium. All codes are on Errors.
Try an order without touching the till
With a test key, POST /api-v1-orders-create validates and prices an order exactly like a live one, but stores it with status: "test". It never reaches the till, the kitchen, stock or reports, sends no webhooks, and is deleted after 24 hours. A test key reads back only test orders, and a live key only live ones. See Orders.
Go live
- Create a live key Same place, live mode. It starts with
sf_live_, sees real data and may make 300 requests a minute. - Give it only the scopes it needs An accounting sync needs
transactions.readandreports.read; a CRM sync needscustomers.read. See Scopes. - Pin it to an outlet if it serves one A key pinned to one outlet cannot read any other. See Authentication.
- Subscribe instead of polling Set up a webhook for order, booking and reservation changes.
Stuck? Quote the request_id from the response and write toSansflow support.Checked against API v1 on .