Skip to content
Get API key

API reference

Orders API

Send an order from your shop, kiosk or bot. Sansflow prices it from the outlet’s menu and the venue accepts it at the till; payment is collected at the counter.

Test mode: an sf_test_ key’s order is validated and priced like a live one and comes back with status: "test" and is_test: true. It never reaches the till, the kitchen, stock or reports, sends no webhooks, and is deleted after 24 hours.

Order status

One word everywhere: the create response, Retrieve an order, and the data of every order.* webhook.

statusMeaning
pending_confirmationSubmitted; waiting for the venue to accept it.
acceptedAccepted; no bill is open for it yet.
preparingOn an open bill: the kitchen has it.
readyThe bill is marked ready.
completedThe bill was closed (payment collected).
cancelledThe venue rejected it, it expired before anyone accepted it, or its bill was cancelled or voided.
awaiting_paymentWaiting for an online payment. API orders are paid at the counter, so v1 does not return it today.
testCreated with an sf_test_ key.

Create an order

POST/api-v1-orders-create
Idempotent
Idempotency-Key

Creates an unpaid order for one outlet. It waits for the venue to accept it (pending_confirmation), or is accepted straight away when the outlet sends orders to the kitchen automatically and a shift is open.

A live order nobody accepts within 20 minutes expires and becomes cancelled.

Idempotency: the same Idempotency-Key with the same body returns the original order with replay: true (and an empty items); the same key with a different body is 409 idempotency_key_conflict.

The body is checked before the Idempotency-Key header, so a bad body answers 422 even without the header.

Headers

NameTypeRequiredDescription
Idempotency-KeystringRequiredA unique key per order, usually a UUID.1-255 characters.

Request body

NameTypeRequiredDescription
location_iduuidRequiredThe outlet the order is for.
order_typestringRequireddine_in or takeaway.
table_refstring | nullOptionalA table label shown to staff.At most 24 characters.
external_refstring | nullOptionalYour own reference, returned on reads and webhooks.At most 255 characters.
customer.namestring | nullOptionalThe guest’s name.At most 120 characters.
customer.phonestring | nullOptionalThe guest’s phone.At most 32 characters.
items[]arrayRequiredThe lines.1-50 items.
items[].item_iduuidRequiredA product id from the menu.
items[].variant_iduuid | nullOptionalOne of the product’s variants.
items[].quantityintegerRequiredHow many.1-99.
items[].notesstring | nullOptionalA note for the kitchen.At most 240 characters.
items[].modifiers[]arrayOptional{ modifier_id } for each chosen option. Each group’s required, min and max rules apply.

Response fields (201)

NameTypeDescription
iduuidThe order. Keep it to read the order back.
statusstringThe order status; see the status table above.
queue_numberstring | nullThe bill number once the till has a bill for it.
external_refstring | nullYour reference, as you sent it.
is_testbooleantrue for an order made with an sf_test_ key.
totals.grossintegerThe order total in rupiah, priced by Sansflow.
items[]arrayEach line as priced: product_id, product_name (the variant’s name when a variant was chosen), variant_id, variant_name, quantity, unit_price (with modifiers), base_price, modifiers[] { modifier_id, modifier_name, price, group_id }, notes, line_total.
created_attimestampWhen it was created.
replaybooleantrue when this is the stored order for a repeated Idempotency-Key.

Errors

Every error answers { "error": { "code", "message", "request_id" } }. Branch on code; see Errors for retrying.

HTTPCodeWhen
400invalid_jsonThe POST body is not valid JSON.
422validation_failedThe body failed the schema, or one or more lines failed. error.details lists each problem with item_index and a code: item_unavailable, invalid_variant, invalid_modifiers, quantity_invalid, invalid_item, location_not_found, invalid_order_type or empty_cart.
400idempotency_key_requiredA POST without an Idempotency-Key header (1-255 characters).
401invalid_keyThe Authorization header is missing, malformed, or the key is revoked or inactive.
402payment_requiredThe business’s plan does not include API access (Sansflow Premium). The key itself is fine.
403insufficient_scopeThe key does not carry the scope this endpoint needs, or it is pinned to a different outlet.
429rate_limitedOver the key’s per-minute limit (60 for sf_test_, 300 for sf_live_). Wait the seconds in Retry-After.
409idempotency_key_conflictThe Idempotency-Key was already used with a different request.
405method_not_allowedAnything but POST.
500internal_errorSomething failed on our side. Quote the request_id when you report it.
Request
curl -X POST "https://ewpuclvmnygoddunkyrb.supabase.co/functions/v1/api-v1-orders-create" \
  -H "Authorization: Bearer $SANSFLOW_API_KEY" \
  -H "Idempotency-Key: 2b7e4c1a-9d3f-4a6b-8e5c-0f1a2b3c4d5e" \
  -H "Content-Type: application/json" \
  -d '{
    "location_id": "3f6c2a1e-8b4d-4c2a-9e51-7a0d2b6c9f10",
    "order_type": "dine_in",
    "table_ref": "T-4",
    "external_ref": "shop_order_1234",
    "customer": {
      "name": "Rina",
      "phone": "081200000000"
    },
    "items": [
      {
        "item_id": "f1b3d5a7-9c2e-4a6b-8d14-7e3c5a9b1d68",
        "variant_id": "6e8a0c2d-4f1b-4d5e-8a96-0c2e4a6b8d81",
        "quantity": 2,
        "notes": "less sugar",
        "modifiers": [
          {
            "modifier_id": "9b1d3f5a-7c2e-4a8b-8d49-3f5b7d9f1a03"
          }
        ]
      }
    ]
  }'
Response201 Created
{
  "id": "a9c1e3f5-7b2d-4f8a-9e63-5c0b4d6a8f57",
  "status": "pending_confirmation",
  "queue_number": null,
  "external_ref": "shop_order_1234",
  "is_test": false,
  "totals": {
    "gross": 60000
  },
  "items": [
    {
      "product_id": "f1b3d5a7-9c2e-4a6b-8d14-7e3c5a9b1d68",
      "product_name": "Iced",
      "variant_id": "6e8a0c2d-4f1b-4d5e-8a96-0c2e4a6b8d81",
      "variant_name": "Iced",
      "quantity": 2,
      "unit_price": 30000,
      "base_price": 25000,
      "modifiers": [
        {
          "modifier_id": "9b1d3f5a-7c2e-4a8b-8d49-3f5b7d9f1a03",
          "modifier_name": "Extra shot",
          "price": 3000,
          "group_id": "8a0c2e4f-6b1d-4f7a-9c38-2e4a6c8e0f92"
        }
      ],
      "notes": "less sugar",
      "line_total": 60000
    }
  ],
  "created_at": "2026-11-08T03:05:12.481+00:00",
  "replay": false,
  "request_id": "5d0c7e2a-91f4-4b3e-a8c6-0f2e4b6d8a1c"
}

Example values. Run replays this response here; nothing is sent.

Retrieve an order

GET/api-v1-orders-get/{order_id}

The status, queue number, totals and lines of an order created through the API. The same shape is the data of every order.* webhook.

Path parameters

NameTypeRequiredDescription
order_iduuidRequiredThe id the create call returned.

Response fields (200)

NameTypeDescription
iduuidThe order. Keep it to read the order back.
statusstringThe order status; see the status table above.
queue_numberstring | nullThe bill number once the till has a bill for it.
external_refstring | nullYour reference, as you sent it.
is_testbooleantrue for an order made with an sf_test_ key.
totals.grossintegerThe order total in rupiah, priced by Sansflow.
items[]arrayEach line as priced: product_id, product_name (the variant’s name when a variant was chosen), variant_id, variant_name, quantity, unit_price (with modifiers), base_price, modifiers[] { modifier_id, modifier_name, price, group_id }, notes, line_total.
created_attimestampWhen it was created.
order_typestringdine_in or takeaway.
table_refstring | nullThe table label you sent.
updated_attimestampLast change.

Errors

Every error answers { "error": { "code", "message", "request_id" } }. Branch on code; see Errors for retrying.

HTTPCodeWhen
400invalid_requestThe id in the path is not a UUID.
401invalid_keyThe Authorization header is missing, malformed, or the key is revoked or inactive.
402payment_requiredThe business’s plan does not include API access (Sansflow Premium). The key itself is fine.
403insufficient_scopeThe key does not carry the scope this endpoint needs, or it is pinned to a different outlet.
429rate_limitedOver the key’s per-minute limit (60 for sf_test_, 300 for sf_live_). Wait the seconds in Retry-After.
404order_not_foundNo order created through the API with this id for this key (test keys see only test orders, live keys only live ones).
405method_not_allowedAnything but GET.
500internal_errorSomething failed on our side. Quote the request_id when you report it.
Request
curl "https://ewpuclvmnygoddunkyrb.supabase.co/functions/v1/api-v1-orders-get/a9c1e3f5-7b2d-4f8a-9e63-5c0b4d6a8f57" \
  -H "Authorization: Bearer $SANSFLOW_API_KEY"
Response200 OK
{
  "id": "a9c1e3f5-7b2d-4f8a-9e63-5c0b4d6a8f57",
  "status": "preparing",
  "queue_number": "K-14",
  "external_ref": "shop_order_1234",
  "order_type": "dine_in",
  "table_ref": "T-4",
  "is_test": false,
  "totals": {
    "gross": 60000
  },
  "items": [
    {
      "product_id": "f1b3d5a7-9c2e-4a6b-8d14-7e3c5a9b1d68",
      "product_name": "Iced",
      "variant_id": "6e8a0c2d-4f1b-4d5e-8a96-0c2e4a6b8d81",
      "variant_name": "Iced",
      "quantity": 2,
      "unit_price": 30000,
      "base_price": 25000,
      "modifiers": [
        {
          "modifier_id": "9b1d3f5a-7c2e-4a8b-8d49-3f5b7d9f1a03",
          "modifier_name": "Extra shot",
          "price": 3000,
          "group_id": "8a0c2e4f-6b1d-4f7a-9c38-2e4a6c8e0f92"
        }
      ],
      "notes": "less sugar",
      "line_total": 60000
    }
  ],
  "created_at": "2026-11-08T03:05:12.481+00:00",
  "updated_at": "2026-11-08T03:06:40.102+00:00",
  "request_id": "5d0c7e2a-91f4-4b3e-a8c6-0f2e4b6d8a1c"
}

Example values. Run replays this response here; nothing is sent.

Base URL, keys and conventions: API reference overview.Events for this resource: Webhooks reference.

Stuck? Quote the request_id from the response and write toSansflow support.Checked against API v1 on .