The storeTilesPaymentsPricingIntegrations
Sign inBook a demo

Developers

Connect your store to anything

The TILED API lets your website, an ordering app or another register see your products and stock, take orders, and keep everything in step with your store. No more selling the last one twice.

Base URLhttps://api.tiledcommerce.com/v1
On this page

Guide

  • Start here
  • The basics
  • Permissions
  • Errors & limits
  • Keeping stock in sync
  • Webhooks

Reference

  • Your store
    • GETWho this key belongs to
    • GETList locations
  • Products & stock
    • GETList products
    • GETGet a product
    • GETList stock levels
    • POSTRecord a sale or return
  • Change feed
    • GETRead changes
    • GETGet the newest cursor
  • Menu
    • GETGet the menu
  • Customers & rewards
    • GETFind a customer
    • POSTAdd a customer
    • GETGet a customer
    • PATCHUpdate a customer
    • GETA customer's orders
    • GETA customer's rewards
    • POSTSign up for rewards
  • Gift cards
    • POSTCheck a gift card
  • Orders
    • POSTPrice an order
    • POSTPlace an order
    • GETList orders
    • GETGet an order
    • POSTCancel an order

Start here

You don't need to be a developer to connect an app. You make a key in TILED and hand it to whoever is building your website or app. They take it from there.

  1. Open Settings → Connected appsIn your store, under “Your store”. Don't see it? Ask us to turn the API on for your store.
  2. Add an app and pick what it's forGive it a name you'll recognise, like “Shopify store”, and choose one of the setups below.
  3. Copy the key and send it to your developerIt's shown once. Treat it like a password. If it ever leaks, turn the app off in the same screen and the key stops working straight away.
Website stock

A website or another register that shows your stock and tells TILED when something sells.

  • See products & stock
  • Update stock
Ordering app

An online ordering app or kiosk that sends orders to your kitchen and register.

  • See products & stock
  • Look up customers
  • Add & update customers
  • See orders
  • Place orders
Just looks

Anything that only needs to read your catalog and stock. It can't change anything.

  • See products & stock

A key can never edit your products, prices, staff or settings, and it never sees your costs or margins. You can also limit a key to one location, or to only the products you've marked “On website”.

The basics

Everything lives under https://api.tiledcommerce.com/v1. Send your key as a bearer token, from your server only; never put it in a web page or a mobile app where customers could read it.

bash
# 1. Check the key works
curl https://api.tiledcommerce.com/v1/store \
  -H "Authorization: Bearer $TILED_API_KEY"

# 2. Read the catalog with stock
curl "https://api.tiledcommerce.com/v1/inventory?limit=200" \
  -H "Authorization: Bearer $TILED_API_KEY"
Keys
Live keys start with tk_live_. Keys from a TILED test environment start with tk_test_, so a key pasted into the wrong place is easy to spot.
Money
Always whole cents: 24900 is $249.00.
Times
ISO 8601 in UTC on the way out. On the way in, any ISO 8601 time with an offset.
Lists
Return { "items": [...], "nextCursor": "..." }. Pass cursor back until nextCursor is null. Up to 200 per page.
Retries
Calls that take stock or place an order need an Idempotency-Key header: any unique string, like your own order number. Retry with the same key and you get the first answer back, so a dropped connection never sells something twice.

Permissions

Each key only does what the merchant ticked for it. Ask for something it wasn't given and you get a 403 naming the setting to turn on.

In SettingsScopeLets the app
See products & stockproducts:readProducts, prices, options, the menu and how many you have.
Update stockinventory:writeTake stock off (or put it back) when something sells somewhere else. Comes with: See products & stock.
Look up customerscustomers:readFind a customer by phone or email, and see their rewards.
Add & update customerscustomers:writeSign up new customers and enroll them in rewards. Comes with: Look up customers.
See ordersorders:readOrders and their status, as they move through the kitchen.
Place ordersorders:writePrice and place orders, check gift cards, cancel its own orders. Comes with: See orders, See products & stock.

Errors & limits

Errors come back with an HTTP status and the same shape every time. message is written so you can show it to a customer or a merchant as it is.

json
{
  "error": {
    "code": "CONFLICT",
    "message": "Gift card ••4821 only has $12.00.",
    "details": { "code": "GIFT_CARD_SHORT", "balanceCents": 1200 }
  }
}
401UNAUTHENTICATEDMissing key, wrong key, or the app was turned off.
403FORBIDDENThe key doesn't have that permission, or the API isn't on for this store.
404NOT_FOUNDNo such product, customer or order (for this key).
409CONFLICTCan't be done as asked. details.code says why, e.g. INSUFFICIENT_STOCK.
422VALIDATION_FAILEDThe input doesn't fit. details lists each field and what's wrong.
429RATE_LIMITEDToo many calls. Wait for retry-after seconds.

Each key can make 300 calls a minute, plenty for a full catalog sync. Every response carries x-ratelimit-remaining and x-ratelimit-reset.

Keeping stock in sync

The usual setup for a website that sells the same stock as your store:

  1. Copy everything once. Page through GET /products and GET /inventory, then call GET /changes/latest and save the cursor.
  2. Follow the changes. Either poll GET /changes every minute or so with the saved cursor, or add a webhook and TILED sends the same events to you.
  3. Tell TILED when it sells. When an order comes in on the website, call POST /inventory/adjustments with delta: -1 per item and your order number as the Idempotency-Key. If TILED sold the last one first, you get INSUFFICIENT_STOCK instead.

Webhooks

Add a webhook URL to an app in Settings → Connected apps and TILED posts changes to it within about a minute, along with a signing secret (whsec_…) shown once.

http
POST https://your-site.example/tiled
Content-Type: application/json
TILED-Signature: t=1761040000,v1=5f2c…

{ "events": [ { "id": 813, "type": "inventory.updated", "createdAt": "…", "data": { … } } ] }
  • Up to 100 events per delivery, the same objects the change feed returns.
  • Answer with any 2xx within 10 seconds. Otherwise TILED tries again after 1, 2, 4 … minutes (up to an hour apart), and pauses after a day of failures. The merchant sees why in Settings.
  • An event can arrive more than once. Skip any id you've already handled.

Checking the signature

v1 is an HMAC-SHA256 of {t}.{raw body}, keyed with your signing secret, in hex. Compare it against the raw body exactly as received, before parsing it.

js
import crypto from "node:crypto";

// Express: app.post("/tiled", express.raw({ type: "application/json" }), handler)
export function verifyTiled(rawBody, header, secret) {
  // header looks like: t=1761040000,v1=5f2c…
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto
    .createHmac("sha256", secret)              // your whsec_… signing secret
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 ?? ""));
}

Event types

TypedataSent when
inventory.updatedA stock levelStock changed: a sale, a return, a delivery, a count.
product.updatedA productA product was added or edited.
product.deleted{ id, sku }A product was deleted, or taken off the website for a website-only key.
order.createdAn orderAn order was placed, anywhere.
order.updatedAn orderAn order moved along, was paid, refunded or cancelled.
customer.updatedA customerA customer was added or edited.
customer.deleted{ id }A customer was erased or merged into another.

A key only gets events it's allowed to see: stock and products need “See products & stock”, orders need “See orders”, customers need “Look up customers”.

Reference

Your store

Check a key works, and see which store and locations it belongs to.

Who this key belongs to

GET/v1/store
Any key

The store's name and address slug, and what this key is allowed to do. A good first call to check a key is set up right.

Request
curl "https://api.tiledcommerce.com/v1/store" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "store": { "name": "Wildwood Trader", "slug": "wildwood-trader" },
  "key": {
    "name": "Shopify store",
    "scopes": ["products:read", "inventory:write"],
    "access": "read_write",
    "locationId": null,
    "products": "website"
  }
}

List locations

GET/v1/locations
Any key

The store's locations. A key limited to one location only sees that one.

Request
curl "https://api.tiledcommerce.com/v1/locations" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "items": [ { "id": "loc_main", "name": "Main showroom", "isDefault": true, "active": true } ],
  "nextCursor": null
}

Reference

Products & stock

Read the catalog and stock levels, and tell TILED when something sells somewhere else so it is never sold twice.

List products

GET/v1/products
Needs: See products & stock

Active products, oldest change first. To keep a copy in sync, remember the newest updatedAt you saw and pass it as updatedSince next time. A key set to “Website products only” only sees products marked On website. Cost is never included.

Query

  • updatedSinceISO 8601

    Only products changed at or after this time.

  • skustring

    Only the product with this SKU.

  • includeInactivetrue | false

    Include archived products. Default false.

  • limitinteger

    1–200. Default 50.

  • cursorstring

    The nextCursor from the previous page.

Request
curl "https://api.tiledcommerce.com/v1/products?updatedSince=2026-10-01T00:00:00Z&limit=100" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "items": [ {
    "id": "prd_8f2c1a",
    "sku": "CHAIR-OAK-1",
    "name": "Oak dining chair",
    "description": "Solid white oak, hand-rubbed oil finish.",
    "barcode": "0840012345678",
    "category": "Dining",
    "collections": ["Farmhouse"],
    "manufacturer": "Amish Oak Co.",
    "priceCents": 24900,
    "salePriceCents": null,
    "imageUrl": "https://files.tiledcommerce.com/…/chair.jpg",
    "active": true,
    "onWebsite": true,
    "variants": [
      { "key": "CHAIR-OAK-1-WAL", "sku": "CHAIR-OAK-1-WAL", "name": "Walnut stain",
        "priceCents": 26900, "imageUrl": null, "active": true }
    ],
    "updatedAt": "2026-10-20T15:04:11.000Z"
  } ],
  "nextCursor": "eyJzIjoxNzYxMDAwMDAwLCJpIjoicHJkXzhmMmMxYSJ9"
}

Get a product

GET/v1/products/{idOrSku}
Needs: See products & stock

One product by its TILED id or its SKU.

Errors

  • NOT_FOUND No product with that id or SKU (or it isn't on the website, for a website-only key).
Request
curl "https://api.tiledcommerce.com/v1/products/{idOrSku}" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "id": "prd_8f2c1a",
  "sku": "CHAIR-OAK-1",
  "name": "Oak dining chair",
  "description": "Solid white oak, hand-rubbed oil finish.",
  "barcode": "0840012345678",
  "category": "Dining",
  "collections": ["Farmhouse"],
  "manufacturer": "Amish Oak Co.",
  "priceCents": 24900,
  "salePriceCents": null,
  "imageUrl": "https://files.tiledcommerce.com/…/chair.jpg",
  "active": true,
  "onWebsite": true,
  "variants": [
    { "key": "CHAIR-OAK-1-WAL", "sku": "CHAIR-OAK-1-WAL", "name": "Walnut stain",
      "priceCents": 26900, "imageUrl": null, "active": true }
  ],
  "updatedAt": "2026-10-20T15:04:11.000Z"
}

List stock levels

GET/v1/inventory
Needs: See products & stock

One row per product (or variant) per location. available is what can be sold right now: showroom + warehouse. Stock held for a customer (reserved) is already outside those numbers.

Query

  • skustring

    A product SKU or a variant SKU.

  • productIdstring

    Every row for this product, variants included.

  • locationIdstring

    Only this location.

  • updatedSinceISO 8601

    Only rows changed at or after this time.

  • limitinteger

    1–200. Default 50.

  • cursorstring

    The nextCursor from the previous page.

Request
curl "https://api.tiledcommerce.com/v1/inventory?sku=CHAIR-OAK-1" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "items": [ {
    "productId": "prd_8f2c1a",
    "sku": "CHAIR-OAK-1",
    "productSku": "CHAIR-OAK-1",
    "variantKey": "",
    "variantName": null,
    "locationId": "loc_main",
    "available": 7,
    "showroom": 3,
    "warehouse": 4,
    "reserved": 1,
    "incoming": 12,
    "updatedAt": "2026-10-21T09:12:40.000Z"
  } ],
  "nextCursor": null
}

Record a sale or return

POST/v1/inventory/adjustments
Needs: Update stockIdempotency-Key required

Takes stock off when something sells on your website or another register (a negative delta), or puts it back on a return (positive). A sale comes out of the showroom first, then the warehouse, the same way the TILED register does it. It shows in the product's history as “API · <app name>”.

Body

  • skustring

    A product or variant SKU. Send this or productId.

  • productIdstring

    With variantKey for a variant without its own SKU.

  • variantKeystring

    Default "" (the product itself).

  • locationIdstring

    Default: the key's location, or the store's main one.

  • deltaintegerrequired

    -1 sold one, +1 one came back. Not 0.

  • reasonsale | return | adjustment

    Default sale.

  • referencestring

    Your order number, kept on the movement.

  • notestring

    Up to 500 characters.

  • allowNegativeboolean

    Record it even if TILED shows too little stock. Default false.

Errors

  • INSUFFICIENT_STOCK 409. TILED shows fewer than you asked for. details.available says how many.
  • IDEMPOTENCY_KEY_REQUIRED 400. The Idempotency-Key header is missing.
  • NOT_FOUND No product with that SKU.
Request
curl -X POST "https://api.tiledcommerce.com/v1/inventory/adjustments" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Idempotency-Key: web-order-1001-line-1" \
  -H "Content-Type: application/json" \
  -d '{ "sku": "CHAIR-OAK-1", "delta": -1, "reason": "sale", "reference": "#1001" }'
Response
{
  "productId": "prd_8f2c1a",
  "variantKey": "",
  "locationId": "loc_main",
  "delta": -1,
  "available": 6,
  "showroom": 2,
  "warehouse": 4
}

Reference

Change feed

Everything that changed, in order. Poll it instead of re-reading the whole catalog, or let webhooks push the same events to you.

Read changes

GET/v1/changes
Any key

Events after a cursor, oldest first, each carrying the current state of what changed. Several changes to one thing inside a page collapse into one event. You only get events your key may see. Changes are kept for 7 days.

Query

  • afterinteger

    The cursor from your last call. Start at 0.

  • limitinteger

    1–200. Default 100.

Request
curl "https://api.tiledcommerce.com/v1/changes?after=812" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "items": [
    { "id": 813, "type": "inventory.updated", "createdAt": "2026-10-21T09:12:40.000Z",
      "data": { "productId": "prd_8f2c1a", "sku": "CHAIR-OAK-1", "available": 6, "…": "…" } },
    { "id": 815, "type": "order.created", "createdAt": "2026-10-21T09:13:02.000Z",
      "data": { "id": "ord_c41d9e", "number": "1042", "stage": "received", "…": "…" } }
  ],
  "cursor": 815,
  "hasMore": false
}

Get the newest cursor

GET/v1/changes/latest
Any key

The newest cursor. After a full sync, start reading changes from here instead of from 0.

Request
curl "https://api.tiledcommerce.com/v1/changes/latest" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{ "cursor": 815 }

Reference

Menu

Everything an ordering app needs to show what can be ordered.

Get the menu

GET/v1/menu
Needs: See products & stock

Items with their variants, options and choices, and whether each can be made right now (available is false when an ingredient has run out). priceCents is already the sale price when there is one. A choice with included: true comes with the item; send its id in removed to leave it off. showWhen means an option or choice only applies when another option has one of those choices.

Query

  • categorystring

    Only this category.

Request
curl "https://api.tiledcommerce.com/v1/menu" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "items": [
    {
      "id": "prd_burger", "sku": "BURGER", "name": "Classic burger", "description": "",
      "category": "Burgers", "collections": [], "imageUrl": null,
      "priceCents": 999, "listPriceCents": 999, "available": true, "variants": [],
      "options": [
        { "id": "grp_cheese", "name": "Cheese", "kind": "choice", "selectType": "single",
          "required": false, "maxPicks": null, "priceDeltaCents": 0, "maxLength": null,
          "unit": null, "min": null, "max": null, "showWhen": null,
          "choices": [ { "id": "opt_cheddar", "name": "Cheddar", "priceDeltaCents": 100,
                         "included": false, "available": true, "showWhen": null } ] }
      ],
      "updatedAt": "2026-10-18T14:00:00.000Z"
    }
  ],
  "taxRatePct": 8,
  "nextCursor": null
}

Reference

Customers & rewards

Find the customer at checkout, sign up new ones, and show their rewards.

Find a customer

GET/v1/customers
Needs: Look up customers

Look a customer up by phone or email. Phones match however they're typed. Every lookup is logged in the store's audit trail.

Query

  • phonestring

    Send this or email.

  • emailstring

    Send this or phone.

Request
curl "https://api.tiledcommerce.com/v1/customers?phone=5550102000" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{ "items": [ {
    "id": "cus_51b0e2",
    "name": "Dana Ruiz",
    "firstName": "Dana",
    "lastName": "Ruiz",
    "email": "dana@example.com",
    "phone": "(555) 010-2000",
    "company": null,
    "marketing": { "email": true, "sms": false },
    "storeCreditCents": 0,
    "createdAt": "2026-03-02T18:20:00.000Z",
    "updatedAt": "2026-10-19T12:01:33.000Z"
  } ], "nextCursor": null }

Add a customer

POST/v1/customers
Needs: Add & update customersIdempotency-Key accepted

Adds a customer. Send at least a name, email or phone. marketing is the customer's own yes or no to emails and texts, recorded with the time they gave it.

Body

  • namestring

    Or firstName and lastName.

  • firstNamestring
  • lastNamestring
  • emailstring
  • phonestring
  • marketing{ email: boolean, sms: boolean }

    Their consent to marketing. Default no to both.

Errors

  • CUSTOMER_DUPLICATE 409. Someone already has that email or phone. details.customerId is who.
Request
curl -X POST "https://api.tiledcommerce.com/v1/customers" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ … }'
Response
{
  "id": "cus_51b0e2",
  "name": "Dana Ruiz",
  "firstName": "Dana",
  "lastName": "Ruiz",
  "email": "dana@example.com",
  "phone": "(555) 010-2000",
  "company": null,
  "marketing": { "email": true, "sms": false },
  "storeCreditCents": 0,
  "createdAt": "2026-03-02T18:20:00.000Z",
  "updatedAt": "2026-10-19T12:01:33.000Z"
}

Get a customer

GET/v1/customers/{id}
Needs: Look up customers

One customer by id.

Request
curl "https://api.tiledcommerce.com/v1/customers/{id}" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "id": "cus_51b0e2",
  "name": "Dana Ruiz",
  "firstName": "Dana",
  "lastName": "Ruiz",
  "email": "dana@example.com",
  "phone": "(555) 010-2000",
  "company": null,
  "marketing": { "email": true, "sms": false },
  "storeCreditCents": 0,
  "createdAt": "2026-03-02T18:20:00.000Z",
  "updatedAt": "2026-10-19T12:01:33.000Z"
}

Update a customer

PATCH/v1/customers/{id}
Needs: Add & update customers

Change any of the fields from Add a customer. Leave a field out to keep it. Send null to clear an email or phone.

Errors

  • CUSTOMER_DUPLICATE 409. Another customer already has that email or phone.
Request
curl -X PATCH "https://api.tiledcommerce.com/v1/customers/{id}" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ … }'
Response
{
  "id": "cus_51b0e2",
  "name": "Dana Ruiz",
  "firstName": "Dana",
  "lastName": "Ruiz",
  "email": "dana@example.com",
  "phone": "(555) 010-2000",
  "company": null,
  "marketing": { "email": true, "sms": false },
  "storeCreditCents": 0,
  "createdAt": "2026-03-02T18:20:00.000Z",
  "updatedAt": "2026-10-19T12:01:33.000Z"
}

A customer's orders

GET/v1/customers/{id}/orders
Needs: Look up customers + See orders

Their past orders, newest first. Good for a “reorder” button.

Query

  • limitinteger

    1–200. Default 50.

  • cursorstring

    The nextCursor from the previous page.

Request
curl "https://api.tiledcommerce.com/v1/customers/{id}/orders" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{ "items": [ { "id": "ord_c41d9e", "number": "1042", "…": "…" } ], "nextCursor": null }

A customer's rewards

GET/v1/customers/{id}/rewards
Needs: Look up customers

Their points and the rewards they can use. Pass a wallet reward, coupon or catalog reward to an order as { kind, id } in rewards. member is null when they haven't joined; enabled is false when the store has no rewards program.

Request
curl "https://api.tiledcommerce.com/v1/customers/{id}/rewards" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "enabled": true,
  "member": {
    "memberNumber": "40021",
    "points": 340,
    "lifetimePoints": 1220,
    "earnMode": "points",
    "wallet": [ { "kind": "wallet", "id": "rw_1", "title": "Free fries", "type": "free_item",
                  "value": 0, "productSku": "FRIES", "expiresAt": "2026-11-30T00:00:00.000Z" } ],
    "coupons": [],
    "catalog": [ { "kind": "catalog", "id": "rc_5", "title": "$5 off", "cost": 300, "type": "amount_off",
                   "value": 500, "productSku": null, "affordable": true } ]
  }
}

Sign up for rewards

POST/v1/customers/{id}/rewards/join
Needs: Add & update customers

Enrolls the customer in the store's rewards program.

Errors

  • REWARDS_OFF 409. The store's rewards program is switched off.
  • ALREADY_MEMBER 409. They've already joined.
Request
curl -X POST "https://api.tiledcommerce.com/v1/customers/{id}/rewards/join" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ … }'
Response
{ "joined": true }

Reference

Gift cards

Check a balance before the customer pays with it.

Check a gift card

POST/v1/gift-cards/check
Needs: Place orders

A card's balance and whether it can be used. To pay with it, put it in giftCards on the order; TILED takes the balance off when the order is placed.

Body

  • codestringrequired

    The number on the card.

Errors

  • NOT_FOUND No card with that number.
Request
curl -X POST "https://api.tiledcommerce.com/v1/gift-cards/check" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ … }'
Response
{ "card": "••4821", "balanceCents": 2500, "usable": true, "expiresAt": null }

Reference

Orders

Price an order, place it on the store's kitchen display and register, follow it, and cancel it if plans change.

Price an order

POST/v1/orders/quote
Needs: Place orders

Works out the total exactly as placing the order would: options, automatic promotions, discount codes, rewards, tax and gift cards. Nothing is booked. Show this total at checkout, then place the same body.

Request
curl -X POST "https://api.tiledcommerce.com/v1/orders/quote" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "lines": [ { "sku": "BURGER", "qty": 2 } ] }'
Response
{
  "lines": [ { "sku": "BURGER", "productId": "prd_burger", "name": "Classic burger", "variant": null,
               "qty": 2, "unitPriceCents": 999, "discountCents": 0, "lineTotalCents": 1998, "options": [] } ],
  "subtotalCents": 1998,
  "discounts": [],
  "discountCents": 0,
  "taxRatePct": 8,
  "taxCents": 160,
  "totalCents": 2158,
  "giftCards": [],
  "paidInAppCents": 0,
  "balanceDueCents": 2158
}

Place an order

POST/v1/orders
Needs: Place ordersIdempotency-Key required

Books the order in TILED and sends it to the kitchen display. If your app already charged the customer, send payment and it's recorded under your app's name; otherwise the balance is paid at pickup. With pickupAt, the kitchen gets it prepMinutes before (up to 14 days ahead). Retrying with the same Idempotency-Key returns the order you already placed (200) instead of placing a second one.

Body

  • linesarrayrequired

    1–100 of { sku or productId, variant?, qty, options?, removed?, note? }.

  • lines[].optionsarray

    { id, choices } for a pick-one or pick-several option, { id, value } for yes/no, text or number.

  • lines[].removedstring[]

    Ids of included choices to leave off (“No onion”).

  • customerIdstring

    Needed for rewards.

  • orderTypepickup | takeout | dine_in | delivery

    Default pickup.

  • namestring

    The name to call out.

  • tableNumberstring
  • deliveryAddressstring
  • notesstring

    For the kitchen and the receipt.

  • pickupAtISO 8601

    Ready by this time instead of now.

  • prepMinutesinteger

    0–240. Default 15.

  • sendToKitchenboolean

    Default true.

  • discountCodestring

    A code from Marketing → Discount codes.

  • rewardsarray

    Up to 5 { kind, id } from the customer's rewards.

  • giftCardsarray

    Up to 3 { code, amountCents? }. Each pays what it can.

  • paymentobject

    { amountCents, label?, reference?, tipCents? } when your app already charged them.

  • referencestring

    Your own order number.

Errors

  • ITEM_NOT_FOUND 409. A line's SKU isn't on the menu.
  • ITEM_UNAVAILABLE 409. An ingredient it needs has run out.
  • OPTION_REQUIRED 409. A required option wasn't answered. details.line and details.option say where.
  • CHOICE_UNAVAILABLE 409. A choice is out right now.
  • CODE_NOT_FOUND / CODE_NOT_VALID 409. The discount code can't be used.
  • GIFT_CARD_SHORT / GIFT_CARD_EMPTY 409. A gift card doesn't cover what you asked of it.
  • OVERPAID 400. payment is more than what's due.
Request
curl -X POST "https://api.tiledcommerce.com/v1/orders" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Idempotency-Key: app-order-7781" \
  -H "Content-Type: application/json" \
  -d '{ "customerId": "cus_51b0e2", "orderType": "pickup", "name": "Dana", "pickupAt": "2026-10-21T17:30:00-04:00", "lines": [ { "sku": "BURGER", "qty": 2, "options": [ { "id": "grp_cheese", "choices": ["opt_cheddar"] } ], "removed": ["opt_onion"] } ], "payment": { "amountCents": 2374, "label": "Apple Pay", "reference": "pi_3Q…" }, "reference": "APP-7781" }'
Response
{
  "id": "ord_c41d9e",
  "number": "1042",
  "stage": "received",
  "status": "ordered",
  "kitchenStatus": "new",
  "channel": "app",
  "source": "Corner Burger app",
  "reference": "APP-7781",
  "customerId": "cus_51b0e2",
  "orderType": "pickup",
  "name": "Dana",
  "tableNumber": null,
  "pickupAt": "2026-10-21T17:30:00.000Z",
  "notes": "",
  "lines": [
    {
      "sku": "BURGER", "productId": "prd_burger", "name": "Classic burger", "variant": null,
      "qty": 2, "unitPriceCents": 1099, "discountCents": 0, "lineTotalCents": 2198, "refundedQty": 0,
      "options": [ { "name": "Cheese", "choice": "Cheddar", "priceDeltaCents": 100 },
                   { "name": "Toppings", "choice": "No onion", "priceDeltaCents": 0 } ],
      "note": null
    }
  ],
  "subtotalCents": 2198,
  "discountCents": 0,
  "taxCents": 176,
  "totalCents": 2374,
  "paidCents": 2374,
  "refundedCents": 0,
  "balanceDueCents": 0,
  "payments": [ { "kind": "payment", "method": "custom", "label": "Apple Pay · Corner Burger app",
                  "amountCents": 2374, "at": "2026-10-21T16:58:02.000Z" } ],
  "isTest": false,
  "createdAt": "2026-10-21T16:58:02.000Z",
  "updatedAt": "2026-10-21T16:58:02.000Z"
}

List orders

GET/v1/orders
Needs: See orders

Orders, oldest change first. Remember the newest updatedAt you saw and pass it as updatedSince next time.

Query

  • updatedSinceISO 8601

    Only orders changed at or after this time.

  • customerIdstring

    Only this customer's orders.

  • minetrue | false

    Only orders this app placed. Default false.

  • limitinteger

    1–200. Default 50.

  • cursorstring

    The nextCursor from the previous page.

Request
curl "https://api.tiledcommerce.com/v1/orders" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{ "items": [ { "id": "ord_c41d9e", "number": "1042", "stage": "preparing", "…": "…" } ], "nextCursor": null }

Get an order

GET/v1/orders/{id}
Needs: See orders

One order. stage is the simple version for showing a customer: received → preparing → ready → completed, or cancelled.

Request
curl "https://api.tiledcommerce.com/v1/orders/{id}" \
  -H "Authorization: Bearer $TILED_API_KEY"
Response
{
  "id": "ord_c41d9e",
  "number": "1042",
  "stage": "received",
  "status": "ordered",
  "kitchenStatus": "new",
  "channel": "app",
  "source": "Corner Burger app",
  "reference": "APP-7781",
  "customerId": "cus_51b0e2",
  "orderType": "pickup",
  "name": "Dana",
  "tableNumber": null,
  "pickupAt": "2026-10-21T17:30:00.000Z",
  "notes": "",
  "lines": [
    {
      "sku": "BURGER", "productId": "prd_burger", "name": "Classic burger", "variant": null,
      "qty": 2, "unitPriceCents": 1099, "discountCents": 0, "lineTotalCents": 2198, "refundedQty": 0,
      "options": [ { "name": "Cheese", "choice": "Cheddar", "priceDeltaCents": 100 },
                   { "name": "Toppings", "choice": "No onion", "priceDeltaCents": 0 } ],
      "note": null
    }
  ],
  "subtotalCents": 2198,
  "discountCents": 0,
  "taxCents": 176,
  "totalCents": 2374,
  "paidCents": 2374,
  "refundedCents": 0,
  "balanceDueCents": 0,
  "payments": [ { "kind": "payment", "method": "custom", "label": "Apple Pay · Corner Burger app",
                  "amountCents": 2374, "at": "2026-10-21T16:58:02.000Z" } ],
  "isTest": false,
  "createdAt": "2026-10-21T16:58:02.000Z",
  "updatedAt": "2026-10-21T16:58:02.000Z"
}

Cancel an order

POST/v1/orders/{id}/cancel
Needs: Place ordersIdempotency-Key accepted

Cancels an order your app placed, as long as the kitchen hasn't started it. Stock, rewards and gift cards go back. Anything your app charged is marked refunded in TILED, and refundInAppCents is what you need to refund on your own payment processor. Once the kitchen has started, the store decides.

Body

  • reasonstring

    Shown on the order.

Errors

  • NOT_YOUR_ORDER 409. Another app or the register placed it.
  • ALREADY_STARTED 409. The kitchen has started or it's been handed over.
Request
curl -X POST "https://api.tiledcommerce.com/v1/orders/{id}/cancel" \
  -H "Authorization: Bearer $TILED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ … }'
Response
{ "order": { "id": "ord_c41d9e", "stage": "cancelled", "…": "…" }, "refundInAppCents": 2374 }

Building something for TILED stores?

Tell us what you're making. We'd like to hear about it, and we can help you test against a sample store.

Get in touch
© 2026 TILED. Point of sale and back office, and you only pay for the parts you use.
Who it’s forFurniture storesClothing boutiquesGift shopsQuick service restaurantsCoffee shops and cafésAntique and vendor mallsPaymentsPricingIntegrationsAPI docsFAQRelease notesBook a demoSign in to your storeLegalTerms of ServicePrivacy Policy