---
title: "Endpoints"
description: "Sales (till receipts), orders, customers, catalog and gift cards, and the keyless public endpoints."
---

> Documentation Index
> Fetch the complete documentation index at: https://developer.unipage.be/llms.txt
> Use this file to discover all available pages before exploring further.

# Endpoints

All paths are relative to `https://api.unipage.eu/{business id}` and need
the [Core API key](/core/authentication/) in the `X-API-Key` header.

| Method and path | Returns |
|---|---|
| `GET /pos-tickets-by-date/{Ymd}` | the till's sales receipts of one day |
| `GET /orders/{Y-m-d}` | webshop, app, kiosk and delivery-platform orders of one day |
| `GET /customers` | every customer |
| `GET /customers/{id}` | one customer |
| `POST /customers` | create a customer |
| `POST /customers/{id}` | update a customer |
| `GET /linked-businesses` | the other locations of the same group |
| `GET /generic/categories`, `GET /generic/products` | the catalog |
| `GET /giftcards`, `GET /giftcards/check-code` | gift cards |

## Sales: `GET /pos-tickets-by-date/{Ymd}`

The VAT receipts the till made on one day, for example
`/pos-tickets-by-date/20261028`. The day runs from midnight to midnight in
the restaurant's timezone, by consumption date. Refund receipts are included
(`is_refund: true`).

| Query parameter | Effect |
|---|---|
| `synced_until` | Unix seconds: only receipts changed after this moment. Use it to fetch a day again cheaply. |
| `exclude_terminal` | leave out the receipts of one till (by terminal name) |

```json
{
  "tickets": [
    {
      "id": "k3m9a",
      "business_id": "x94d3",
      "order_id": null,
      "customer_id": "p8q2r",
      "ticket_id": "...",
      "type": "VAT",
      "is_refund": false,
      "operator_name": "Eva",
      "terminal_name": "Kassa 1",
      "consumption_date": "2026-10-28 12:41:07",
      "ticket_date": "2026-10-28 12:41:09",
      "ticket_lines": [
        {
          "product": "Broodje kaas",
          "category_reference": "Broodjes",
          "amount": 2,
          "unit_price_with_vat": 4.5,
          "vat_rate": 6,
          "total_price_without_vat": 8.49,
          "total_vat": 0.51,
          "total_price_with_vat": 9
        }
      ],
      "payment_lines": [
        { "payment_method": "CASH", "payment_name": "Cash", "amount": 9, "rounding": 0 }
      ]
    }
  ]
}
```

### The receipt fields

| Key | Meaning |
|---|---|
| `id`, `business_id` | ids |
| `order_id`, `customer_id` | the webshop order this receipt settles, and the customer it was booked on, or `null` |
| `ticket_id`, `ticket_source`, `pos_order_id`, `order_number` | the till's own identifiers |
| `type` | `VAT` for a sales receipt |
| `is_refund` | `true` for a refund receipt |
| `operator_name`, `terminal_name` | who made the sale, on which till |
| `consumption_date`, `ticket_date` | when it was consumed, when the receipt was made |
| `vat_type_reference`, `fdm_response`, `did_award_loyalty_points` | fiscal and loyalty details as the till sent them |
| `ticket_lines[]` | `id`, `business_id`, `type`, `product`, `category_reference`, `notes`, `price_type`, `unit_price_with_vat`, `amount`, `vat_rate`, `total_price_without_vat`, `total_vat`, `total_price_with_vat`, `course` |
| `discount_lines[]` | only in the [`pos.sale` webhook](/core/webhooks/): `id`, `ticket_line_id`, `name`, `type`, `vat_rate`, `total_price_without_vat`, `total_vat`, `total_price_with_vat` |
| `payment_lines[]` | `id`, `payment_method`, `payment_name`, `amount`, `rounding` |

> **Note**
>
> Discount amounts are signed: negative on a sale, positive when a discounted
> line is reversed. Add them up as they are; do not take absolute values, or
> reversals will no longer cancel out.

This shape is a contract: keys are added over time, never renamed or
removed.

## Orders: `GET /orders/{Y-m-d}`

The orders created on one day, for example `/orders/2026-10-28`, with a
successful status: webshop, app, kiosk and delivery-platform (Uber Eats,
Deliveroo) orders. Returned as an array.

> **Caution**
>
> Orders are returned for **every location of the group** (the locations
> sharing one catalog), not only the location in the URL. Receipts are per
> location. Use `business_id` on each order if you need one location.

The main keys: `id`, `created_at` and `updated_at` (Unix seconds),
`order_number_for_company`, `status`, `order_type`, `order_source`,
`payment_method`, `is_paid`, `total_price`, `delivery_cost`,
`service_cost`, `coupon_reduction`, `coupon_string`, `wallet_amount`,
customer fields (`user_firstname`, `user_lastname`, `user_email`,
`user_phone`, `user_id`), delivery fields, `takeout_delivery_timestamp`,
`order_notes`, platform fields (`display_id`, `delivery_type`,
`dropoff_notes`, `unmatched_items`), and `orderItems[]` with their options.

## Customers

### `GET /customers`

Every customer of the restaurant's organization, as `{"data": [...]}`.
Deleted customers are included, with `deleted_at` set, so you can remove
them on your side.

| Query parameter | Effect |
|---|---|
| `updated_after` | Unix seconds: only customers changed at or after this moment |

The list is cached for 15 seconds. Sync with `updated_after` instead of
downloading every customer each time.

### `GET /customers/{id}`

One customer, as `{"data": {...}}`.

The customer fields: `id`, `user_id`, `firstname`, `lastname`, `full_name`,
`email`, `phone`, address fields, `company_name`, `vat_number`, `notes`,
`nfc_uid`, `profile_picture_url`, `last_ordered_at`,
`did_give_marketing_consent`, `created_at`, `updated_at`, `memberships`,
`wallet`, `loyalty_wallet`, `metadata`, `deleted_at`.

### `POST /customers` and `POST /customers/{id}`

Create or update a customer. Answers `{"success": true, "customer": {...}}`.

| Field | Rule |
|---|---|
| `email` | required on create, unique in the organization |
| `nfc_uid` | optional, unique in the organization (a loyalty card or badge) |
| `firstname`, `lastname`, `company_name`, `vat_number`, `phone` | optional, at most 255 characters |
| `address_1`, `address_number`, `address_number_addition`, `address_postcode`, `address_city`, `address_country` | optional |
| `did_give_marketing_consent` | optional boolean, default `false` |
| `profile_picture_base64` | optional, a base64 PNG |

```sh
curl -X POST https://api.unipage.eu/x94d3/customers \
  -H "X-API-Key: $UNIPAGE_CORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "eva@example.com", "firstname": "Eva", "lastname": "Peeters"}'
```

## Other locations: `GET /linked-businesses`

`{"businesses": [{"id": "x94d3", "reference": "..."}]}`: every location of
the group, this one included. Each needs its own key.

## Catalog

`GET /generic/categories` and `GET /generic/products` return the catalog as
the till receives it, with prices, options and translations.
`GET /generic/products` accepts `updated_after` (Unix seconds) to fetch only
the products changed since your last sync, and `category_id` to limit it to
one category.

## Gift cards

| Endpoint | Returns |
|---|---|
| `GET /giftcards` | `{"giftcards": [...]}`: the most recent valid gift cards. `search` filters, `limit` sets how many (default 6, at most 50). |
| `GET /giftcards/check-code?code=...` | `{"available": true}` when no gift card uses that code yet |

A gift card has `id`, `code`, `name`, `amount`, `balance`,
`formatted_balance`, `is_valid`, `recipient_name`, `expires_at`,
`redeemed_at` and `created_at`.

## Without a key: `/public/{domain}`

What the public webshop already shows is also available without a key, by
the shop's domain (for example `myshop.unipage.eu`):

| Path | Returns |
|---|---|
| `GET /public/{domain}` | name, address, phone, e-mail and opening hours |
| `GET /public/{domain}/menu` | the webshop menu (the `Accept-Language` header, nl, fr, en or de, sets the language) |
| `GET /public/{domain}/categories`, `GET /public/{domain}/products` | categories and products with prices and translations |

For a custom ordering experience, use the [Storefront API](/storefront/)
instead: it also quotes carts and places orders.

Source: https://developer.unipage.be/core/endpoints/index.mdx
