Tactill API v0 (v0)

Download OpenAPI specification:

API Integration Support: hello@tactill.com URL: https://tactill.com License: Tactill Terms of Service

Introduction

The Tactill API is an HTTP REST API for POS, catalog, sales, and inventory automation. It uses predictable resource URLs, standard HTTP status codes, and JSON in both request and response bodies.

Most actions in the Tactill Backoffice are exposed through this API so that you can automate any workflow you need. This reference documents every public resource currently shipped on v0.

Use any HTTP client in your language of choice, or the Tactill TypeScript SDK published on npm as @tactill/api-v5.

Quickstart

Make your first call in 30 seconds. Replace sk_test_… with a key issued from the Tactill Backoffice.

curl https://api.tactill.com/pos/v0/products \
  -H "X-Api-Key: sk_test_xxxxxxxxxxxxxxxxxxxxxxxx"

The response is a JSON object with items and a next_token for pagination. From here:

  1. Authenticate every request with your X-Api-Key header — see Authentication.
  2. Pick an environment — test keys hit test data, live keys hit live data. See Environments.
  3. Paginate list endpoints with next_token until it is null. See Pagination.
  4. Handle errors with the standard envelope. See Errors.

Authentication

Tactill uses API keys. Each key is scoped to a single organization and grants the permissions configured at issue time.

Getting your API key (temporary)

⚠️ Temporary — manual key creation. Self-serve API-key management in the Tactill Backoffice (v5.tactill.com) is not available yet. Until it ships, create a key with the GraphQL call below, or email hello@tactill.com to have one issued for you.

Step 1 — Get your JWT and companyID. Log in to v5.tactill.com, open your browser DevTools (F12) → Network, filter on graphql, and click any request:

  • Request URL — the GraphQL endpoint (copy it; the production value is the one used below).
  • Request Headers → Authorization — your JWT (starts with eyJ…; short-lived, so re-copy it if you get a 401).
  • Payload — the companyID variable is your company identifier.

Step 2 — Create the key. Replace $JWT and YOUR_COMPANY_ID, then run:

curl -X POST https://uc3tlcffqnbtfet5fle7rjy3mm.appsync-api.eu-west-1.amazonaws.com/graphql \
  -H "Authorization: $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation Create($input: CreateExternalApiCredentialInput!) { createExternalApiCredential(input: $input) { rawKey externalApiCredential { id label scopes test } } }",
    "variables": { "input": {
      "companyID": "YOUR_COMPANY_ID",
      "label": "My integration (test)",
      "test": true,
      "scopes": ["catalog:read", "catalog:write", "sale:read"]
    }}
  }'
  • test: true issues an sk_test_… key; test: false issues an sk_live_… key. This field is required.
  • scopes — request only what you need (:write implies :read). Every available scope, for easy copy-paste:
["catalog:read","catalog:write","settings:read","settings:write","customer:read","customer:write","inventory:read","inventory:write","sale:read","sale:write","payment:read","payment:write","cashbook:read","cashbook:write"]

Step 3 — Save rawKey. The response contains rawKey (e.g. sk_test_…). It is returned once and never stored — copy it into your secrets manager immediately, then send it as your X-Api-Key. Prefer a GUI? Download the Postman collection to explore every REST endpoint once you have a key.

Using your key

Send your key in the X-Api-Key header on every request:

X-Api-Key: sk_test_xxxxxxxxxxxxxxxxxxxxxxxx

Key formats

Prefix Environment Use for
sk_test_ Test Development, staging, automated tests
sk_live_ Live (production) Production traffic only

Keys are secrets. Never embed them in client-side code, mobile apps, or commit them to source control. If a key leaks, revoke it from the Backoffice and issue a new one — old keys are invalidated immediately.

Scopes

Each key carries one or more scopes in the form <domain>:<read|write>. Available domains:

catalog, customer, inventory, sale, payment, cashbook

A :write scope automatically grants :read on the same domain. Calling an endpoint without the required scope returns 403 Forbidden.

Environments

Every resource lives in either test or live mode. The mode is bound to the API key — it is not a request-body parameter.

  • A test key reads and writes test data only; live data is invisible to it.
  • A live key reads and writes live data only; test data is invisible to it.

Switching environments means switching keys. Contact hello@tactill.com to provision a test key alongside your live key.

Each resource response carries a test boolean so you can confirm which environment a record belongs to.

Conventions

Used consistently across every endpoint:

Convention Format Example
Dates ISO 8601 UTC 2026-01-15T10:00:00Z
Money Integer minor units 1200 = €12.00
Tax rates Basis points 2000 = 20%, 550 = 5.5%
Identifiers UUID v4 7f4d6c8e-3a2b-4f5d-9c1e-8b0a4d3f2e1c
Request bodies JSON Content-Type: application/json
Response bodies JSON UTF-8

Pagination

List endpoints are token-paginated. Responses include:

{
  "items": [ /* up to N records */ ],
  "next_token": "eyJpZCI6ICIuLi4ifQ=="
}

To fetch the next page, pass next_token back as a query parameter:

curl "https://api.tactill.com/pos/v0/products?next_token=eyJpZCI6..." \
  -H "X-Api-Key: sk_test_xxxxxxxxxxxx"

When next_token is null you have reached the last page. Never assume a single call returns every record — always loop until next_token is null.

Errors

Every error response uses the same envelope:

{
  "status_code": 404,
  "error": "Not Found",
  "message": "product id does not exist"
}

The error field is always Title Case and matches the HTTP reason phrase.

Status When What to do
400 Bad Request Body fails schema validation Inspect message, fix payload
401 Unauthorized Missing, malformed, or revoked API key Check the X-Api-Key header
403 Forbidden Key lacks scope, or business rule blocks the action (e.g. deleting a tax still in use) Adjust the call or escalate the key's scopes
404 Not Found Resource ID does not exist in the current environment Confirm the ID and the env (test vs live)
409 Conflict Resource state forbids the operation (e.g. closing an already-closed cashbook) Reload the resource and retry
422 Unprocessable Entity Body is structurally valid but rejected by a business invariant Read message, adjust inputs
429 Too Many Requests Rate limit exceeded Back off — see Rate limits
5xx Unexpected server-side failure Retry with exponential backoff

Your client must tolerate additional fields on the envelope. Diagnostic fields may be added without bumping the API version.

Rate limits

Limits are applied per organization. Sandbox keys are limited to 3000 non-GET requests per 10 minutes. Live limits are sized for typical business workloads.

Every response carries:

  • X-RateLimit-Limit — the cap for the current window.
  • X-RateLimit-Remaining — requests remaining in the current window.
  • X-RateLimit-Retry-After — UTC timestamp of the next reset, present only when the limit is hit.

When the limit is exceeded the response is 429 Too Many Requests. Retry no earlier than X-RateLimit-Retry-After, with jitter.

Integration tips

Rules that keep an integration healthy:

  • Pin the version in your base URL — always /pos/v0/… (or future /pos/vN/…). Never call the API without an explicit version segment.
  • IdempotencyGET retries are always safe. For mutations, design your callers to deduplicate by your own external reference rather than relying on retries.
  • Pagination — never assume a list endpoint returns every record in one call. Loop on next_token.
  • Backoff — on 429 and 5xx, retry with exponential backoff and jitter. Respect X-RateLimit-Retry-After when present.
  • Environment binding — mirror the test/live split in your own configuration. Never share a single key across environments.
  • Forward-compat — tolerate unknown fields in responses. We may add fields without a version bump.

API Versioning

URI versioning: every endpoint is prefixed with /pos/v<N>/.

Current version

v0 is live and still evolving. It is not frozen: fields can be removed or renamed, request shapes can change, and endpoints can gain required fields.

What we commit to instead:

  • Every change is written up in the changelog, with the action it requires from you.
  • Breaking changes are announced before they reach production, not after.
  • We coordinate directly with each integration currently in build.

Pin the behaviour you depend on with contract tests rather than assuming a field will outlive a release, and read the changelog before upgrading.

Breaking changes

Breaking changes ship on v0. Deliberately: while the API is young, correcting a wrong contract is worth more than preserving it.

A future v1 will be introduced once the surface is stable and integrations are numerous enough that coordinating a change one-to-one stops being realistic. At that point v0 gets a deprecation window and a Sunset header on every response. That has not happened yet.

The @tactill/api-v5 npm package tracks the latest release.

SDKs

Tactill publishes an official TypeScript SDK on npm as @tactill/api-v5. It is generated from this OpenAPI document and tracks every release.

npm install @tactill/api-v5

No SDK is required — every endpoint is reachable from any HTTP client.

Postman collection

A Postman collection is generated from this OpenAPI document and ships with each release.

Download: Tactill API Postman Collection

Support

To request access, provision a test key, or discuss an integration, contact hello@tactill.com.

Filters

Filters describe how searching works. Every POST /<resource>/request endpoint takes the same envelope, so once you can search one resource you can search all of them. Which fields a given resource accepts is listed in that resource's own request schema.

The envelope

{
  "filter": { "name": { "contains": "shorts" } },
  "sort":   { "field": "created_at", "direction": "desc" },
  "limit":  20,
  "next_token": null
}

Every key is optional. Omit filter to retrieve everything.

Operators by field type

Each criterion is an object keyed by operator, never a bare value. {"name": "shorts"} is rejected; {"name": {"eq": "shorts"}} is correct.

  • Texteq, ne, contains, not_contains, starts_with, ends_with, regexp, lt, lte, gt, gte, exists
  • Dateseq, ne, lt, lte, gt, gte, exists. ISO 8601, e.g. 2024-01-31T23:59:59Z
  • Numberseq, ne, lt, lte, gt, gte, exists. Amounts are integers in minor units; see currency_decimals on the company
  • Booleanseq, ne, exists
  • Identifierseq, ne, exists
  • Enumerationseq, ne, exists, with the accepted values listed on the resource

Several criteria in one object are combined with AND:

{ "filter": { "state": { "eq": "CLOSED" }, "total": { "gte": 1000 } } }

Combining criteria

and, or and not take plain filters:

{
  "filter": {
    "state": { "eq": "CLOSED" },
    "or": [
      { "total": { "gte": 10000 } },
      { "source_name": { "contains": "web" } }
    ]
  }
}

and — every criterion must match

Redundant at the top level, since criteria there already AND together. It earns its place when you need two conditions on the same field:

{
  "filter": {
    "and": [
      { "created_at": { "gte": "2024-06-01T00:00:00Z" } },
      { "created_at": { "lt": "2024-07-01T00:00:00Z" } }
    ]
  }
}

or — at least one criterion must match

{
  "filter": {
    "or": [
      { "state": { "eq": "CLOSED" } },
      { "state": { "eq": "PENDING" } }
    ]
  }
}

not — the criterion must not match

{
  "filter": {
    "not": { "source_name": { "contains": "test" } }
  }
}

Combining them

Operators sit alongside ordinary criteria, and everything at the same level ANDs together. Read the example below as: closed and (over 100.00 € or from the web) and not a test source.

{
  "filter": {
    "state": { "eq": "CLOSED" },
    "or": [
      { "total": { "gte": 10000 } },
      { "source_name": { "contains": "web" } }
    ],
    "not": { "source_name": { "contains": "test" } }
  }
}

Combination is one level deep. The filters inside and, or and not are plain criteria — they cannot themselves contain and, or or not. A nested combination is rejected with 400. This is a deliberate limit: it keeps every filterable field visible in this documentation and in the generated SDK. If your query genuinely needs deeper nesting, tell us what you are trying to express.

Unknown criteria are rejected

Sending a field the resource does not accept returns 400 Bad Request. A misspelled criterion is reported rather than ignored, so a filter can never silently widen your result set.

Worked examples

Sales closed in January over 100.00 €, most recent first:

{
  "filter": {
    "state": { "eq": "CLOSED" },
    "closed_at": { "gte": "2024-01-01T00:00:00Z", "lte": "2024-01-31T23:59:59Z" },
    "total": { "gte": 10000 }
  },
  "sort": { "field": "closed_at", "direction": "desc" },
  "limit": 50
}

Products in one of two categories, excluding a tag:

{
  "filter": {
    "or": [
      { "category_id": { "eq": "ea9f3f98-6f35-41e3-8c47-92fc313be733" } },
      { "category_id": { "eq": "7c1b0a52-3f19-4f0e-9a44-1d3e5c8b7a20" } }
    ],
    "not": { "name": { "contains": "sample" } }
  }
}

Customers with an email recorded, created this year:

{
  "filter": {
    "email": { "exists": true },
    "created_at": { "gte": "2024-01-01T00:00:00Z" }
  }
}

Walking every page:

{ "filter": { "state": { "eq": "CLOSED" } }, "limit": 100 }

Repeat with next_token set to the value from the previous response until it comes back null. total stays constant across pages — it counts everything matching the filter, not the page.

Common mistakes

  • {"name": "shorts"} — a criterion is always an object: {"name": {"eq": "shorts"}}.
  • Nesting a combination inside and / or / not. One level only.
  • Filtering on a field the resource does not expose. Check the request schema; unknown criteria return 400.
  • Assuming amounts are decimal. They are integers in minor units — 10000 is 100.00 € when currency_decimals is 2.

Sorting and pagination

sort takes one field from the resource's sortable list, with direction set to asc or desc (default asc).

limit caps the page at 1 to 100 items. Responses carry items, total — the number of records matching your filter, not the page size — and next_token. Pass next_token back to fetch the next page; null means there are no more.

Account

Account exposes the API key you are calling with, and the company it belongs to. It is the entry point of any integration: call it first to discover your company_id and confirm which permissions and mode your key actually has.

Environment: the endpoint itself is mode-agnostic — it describes the key, and reports the mode in the test field.

Field semantics

  • id — identifier of the API key itself, not of the company or of a user.
  • company_id — the company every other endpoint operates on. It is derived from the key, never sent by the client.
  • scopes — permissions granted when the key was issued. A :write scope implies the matching :read.
  • statusactive. A revoked key never authenticates, so no other value is observable here.
  • testtrue for sk_test_ keys, false for sk_live_ keys. The mode is fixed at issuance and cannot be switched per request.

Scopes

None. Every authenticated key can read its own identity, whatever its scopes — otherwise a key could not discover what it is allowed to do.

Constraints

  • This resource exposes GET /me only. The key is read-only through the API: issuing, rotating and revoking keys happen in the back office.
  • The secret itself is never returned, by this or any other endpoint. It is shown once, at issuance. A lost key must be rotated.

Get the current API key

Returns the API key making the call and the company it belongs to. Available to every authenticated key, whatever its scopes.

Authorizations:
apiKey

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "company_id": "223e4567-e89b-12d3-a456-426614174000",
  • "label": "Partner integration",
  • "scopes": [
    ],
  • "status": "active",
  • "test": false,
  • "created_at": "2025-01-15T10:30:00.000Z",
  • "updated_at": "2025-01-15T10:30:00.000Z"
}

Company

Company is the account every other resource belongs to. Read it once at start-up to learn how to format amounts: every monetary value in the API is an integer in minor units, and currency_decimals tells you where the decimal point goes.

Environment: the company is shared between test and production modes — it is not duplicated per mode.

Field semantics

  • currency / currency_decimals1050 with currency_decimals: 2 is 10.50 EUR. Some currencies use 0 decimals, in which case 1050 is 1050.
  • locale — drives formatting and the language of printed documents.
  • name — the trading name. Registered legal names live on each shop, under legal_name.

Scopes

None. Every authenticated key can read its own company, whatever its scopes.

Constraints

  • This resource exposes GET /company only. The company is derived from the API key, so it takes no identifier and a key can never read another company.
  • The company is read-only through the API.

Get the company

Returns the company the API key belongs to. The company is derived from the key, so no identifier is needed. Available to every authenticated key, whatever its scopes.

Authorizations:
apiKey

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Ma Boutique",
  • "country": "FR",
  • "currency": "EUR",
  • "currency_decimals": 2,
  • "locale": "fr-FR",
  • "business_line": "RETAIL",
  • "business_type": "FASHION"
}

Shop

Shops are the points of sale of the company. Their identifiers are required throughout the API: shop_id is mandatory when recording a sale, a cashbook movement or an inventory movement, so listing shops is normally the second call an integration makes, right after reading the company.

Environment: shops are shared between test and production modes — the same shops are returned whichever key you use.

Field semantics

  • name — internal name, used to tell shops apart in the back office. brand_name is the customer-facing name printed on receipts.
  • siret / vat — identify the shop itself as an establishment.
  • legal_name, business_name, siren, naf — describe the legal entity operating the shop. Several shops may share one legal entity, in which case these fields repeat. They are null while no legal entity is attached to the shop.
  • footnote and logo — printed on the shop's receipts.

Scopes

None. Every authenticated key can read the company's shops, whatever its scopes — an integration cannot record a sale without a shop_id.

Filtering

POST /shop/request takes limit and next_token only — there are no filter criteria on this resource. See Filters for the pagination rules.

Constraints

  • This resource exposes GET /shop/:id and POST /shop/request only. Shops are read-only through the API; they are created and edited in the back office.
  • POST /shop/request returns every shop of the company in one response, and total is the real count. next_token is null except for companies with more than 1000 shops, where it resumes the listing.
  • Requesting a shop belonging to another company answers 404 Not Found rather than 403, so the API never reveals whether an identifier exists elsewhere.

Get a shop by ID

Retrieves a shop by its unique identifier, including the legal details of the entity operating it. Available to every authenticated key, whatever its scopes.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 123e4567-e89b-12d3-a456-426614174000

Unique identifier of the shop

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Boutique Opéra",
  • "brand_name": "Ma Boutique",
  • "address": {
    },
  • "phone": "+33123456789",
  • "email": "opera@maboutique.fr",
  • "website_url": "https://maboutique.fr",
  • "footnote": "Merci de votre visite",
  • "siret": "81234567800012",
  • "vat": "FR12812345678",
  • "legal_name": "MA BOUTIQUE SAS",
  • "business_name": "Ma Boutique",
  • "siren": "812345678",
  • "naf": "4771Z"
}

Request shops

Retrieves every shop of the company. Available to every authenticated key, whatever its scopes.

Authorizations:
apiKey
Request Body schema: application/json
required
limit
integer [ 1 .. 100 ]

Maximum number of shops to read per underlying page

next_token
string

Cursor returned by a previous call, to resume from

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Product

Products are the items sold from the cash register. Each product belongs to a category, has an associated tax rate, and may carry options, tags, custom fields, and variations.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • buy_price, sell_price — integer minor units (cents). 1200 is €12.00.
  • category and tax — references to existing resources; both are required at creation.
  • tags, options, custom_fields — arrays of references; each can also be detached individually via the nested DELETE routes.
  • variations — managed through dedicated PATCH /product/:id/variation/... routes; price adjustments are applied per variation, not on the parent product.

Scopes

  • catalog:readGET /product/:id, POST /product/request.
  • catalog:writePOST /product, PATCH /product, DELETE /product/:id, all nested detach and variation routes.

Filtering

POST /product/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • A product cannot be deleted while it is referenced by one or more packs. Detach or delete the parent packs first.
  • Detaching a tag, option, or custom field uses dedicated routes:
    • DELETE /product/:id/tag/:tagId
    • DELETE /product/:id/option/:optionId
    • DELETE /product/:id/custom-field/:customFieldId
  • Variation updates target a single variation by name:
    • PATCH /product/:id/variation/:variationName
    • PATCH /product/:id/variation/:variationName/option/:optionValue

Create a product

Creates a new product in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Product creation payload

name
required
string

Display name of the product as shown to customers

buy_price
required
number

Cost price paid by the merchant to acquire the product (in cents) - used for profit calculations

sell_price
required
number

Retail price charged to customers (in cents) - this is the base price before taxes or discounts

required
object or string
required
object or string
Array of objects or strings
Default: []

List of tags for product organization and filtering - helps customers find related products

options
Array of strings
Default: []

List of product variant options (size, color, etc.) that customers can select with potential price adjustments

Array of objects
Default: []

Additional custom data fields specific to your business needs (e.g. warehouse codes, supplier info)

photo
string

URL of the main product image displayed to customers in the catalog

Responses

Request samples

Content type
application/json
{
  • "name": "Blue shorts",
  • "buy_price": 1000,
  • "sell_price": 1200,
  • "category": {
    },
  • "tax": {
    },
  • "tags": [
    ],
  • "options": [
    ],
  • "custom_fields": [
    ],
}

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Blue shorts",
  • "color": "BLUE",
  • "icon_text": "BS",
  • "category_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "tax_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "bulk_type": "string",
  • "buy_price": 1000,
  • "sell_price": 1200,
  • "barcode": "MY_BARCODE",
  • "reference": "MY_REFERENCE",
  • "variations": [
    ],
  • "variants_count": 0,
  • "tax": {
    },
  • "category": {
    },
  • "tags": [
    ],
  • "custom_fields": [
    ],
  • "options": [
    ],
}

Update a product

Updates an existing product with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Product update payload

id
required
string
name
string

Product name

buy_price
number

Product buy price (in cents)

sell_price
number

Product sell price (in cents)

barcode
string or null

Product barcode

reference
string or null

Product reference

category_id
string

Category ID

tax_id
string

Tax ID

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "name": "Updated Blue Shorts",
  • "buy_price": 1100,
  • "sell_price": 1300,
  • "barcode": "1234567890123",
  • "reference": "REF-001",
  • "category_id": "ea9f3f98-6f35-41e3-8c47-92fc313be733",
  • "tax_id": "dcc2a3cf-7357-40ab-8a3b-adc43d93afb0"
}

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Blue shorts",
  • "color": "BLUE",
  • "icon_text": "BS",
  • "category_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "tax_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "bulk_type": "string",
  • "buy_price": 1000,
  • "sell_price": 1200,
  • "barcode": "MY_BARCODE",
  • "reference": "MY_REFERENCE",
  • "variations": [
    ],
  • "variants_count": 0,
  • "tax": {
    },
  • "category": {
    },
  • "tags": [
    ],
  • "custom_fields": [
    ],
  • "options": [
    ],
}

Request products with filtering

Retrieves a list of products based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Product request payload with filters

object (ProductFilter)

Criteria for Product. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Get a product by ID

Retrieves a product by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Blue shorts",
  • "color": "BLUE",
  • "icon_text": "BS",
  • "category_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "tax_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "bulk_type": "string",
  • "buy_price": 1000,
  • "sell_price": 1200,
  • "barcode": "MY_BARCODE",
  • "reference": "MY_REFERENCE",
  • "variations": [
    ],
  • "variants_count": 0,
  • "tax": {
    },
  • "category": {
    },
  • "tags": [
    ],
  • "custom_fields": [
    ],
  • "options": [
    ],
}

Delete a product

Deletes a product by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Blue shorts",
  • "color": "BLUE",
  • "icon_text": "BS",
  • "category_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "tax_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "bulk_type": "string",
  • "buy_price": 1000,
  • "sell_price": 1200,
  • "barcode": "MY_BARCODE",
  • "reference": "MY_REFERENCE",
  • "variations": [
    ],
  • "variants_count": 0,
}

Remove a custom field from a product

Deletes the connection between a product and a custom field.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the product

custom_field_id
required
string
Example: ba19240a-0442-4bd9-8c15-01b8409e1346__product_champpersotexte1

Unique identifier of the custom field to remove from the product

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d"
}

Remove a tag from a product

Deletes the connection between a product and a tag.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the product

tag_id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the tag to remove from the product

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d"
}

Remove an option from a product

Deletes the connection between a product and an option.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the product

option_id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the option to remove from the product

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d"
}

Update a product variation name

Updates an existing product variation name with the provided data.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 74112fef-687b-469e-a6ca-74fcf456ca42

Unique identifier of the product

variation_name
required
string non-empty
Example: couleur

Current name of the variation to update

Request Body schema: application/json
required

Product variation name update payload

new_name
required
string non-empty

New name for the product variation

Responses

Request samples

Content type
application/json
{
  • "new_name": "couleurs"
}

Response samples

Content type
application/json
{
  • "product_id": "74112fef-687b-469e-a6ca-74fcf456ca42",
  • "product": {
    },
  • "variations": [
    ],
  • "insertions": [
    ],
  • "modifications": [
    ],
  • "deletions": [
    ]
}

Update a product variation option value

Updates an existing product variation option value with the provided data.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 74112fef-687b-469e-a6ca-74fcf456ca42

Unique identifier of the product

variation_name
required
string non-empty
Example: couleur

Name of the variation containing the option to update

option_value
required
string non-empty
Example: rouge

Current value of the option to update

Request Body schema: application/json
required

Product variation option value update payload

new_value
required
string non-empty

New value for the product variation option

Responses

Request samples

Content type
application/json
{
  • "new_value": "red"
}

Response samples

Content type
application/json
{
  • "product_id": "74112fef-687b-469e-a6ca-74fcf456ca42",
  • "product": {
    },
  • "variations": [
    ],
  • "insertions": [
    ],
  • "modifications": [
    ],
  • "deletions": [
    ]
}

Product Variant

Product Variants are the concrete sellable forms of a product (a specific size/colour/flavour combination). A variant carries its own pricing, barcode, and stock-keeping fields while inheriting the catalog metadata of its parent product.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • buy_price, sell_price — integer minor units (cents).
  • Variant routes are addressed by composite path :productId/:variantId, not under /product/:id/....

Scopes

  • catalog:readGET /productvariant/:productId/:variantId.
  • catalog:writePOST /productvariant, PATCH /productvariant, DELETE /productvariant/:productId/:variantId.

Constraints

  • A variant cannot be deleted while it is referenced by an open sale, a pack variation, or any other active record. Detach the references first.

Create a product variant

Creates a new product variant in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Product variant creation payload

product_id
required
string (Parent Product ID)

The unique identifier of the parent product to which this variant belongs

variant_id
string (Variant ID)

An optional unique identifier for the variant, if not provided it will be generated automatically

required
Array of objects (Variation Options)

An array of variation options that define the specific characteristics of this product variant

tax_id
required
string (Tax Rate ID)

The unique identifier of the tax rate that will be applied to this product variant during sales transactions

buy_price
number (Buy Price)

The cost price that the merchant pays to acquire this product variant, expressed in cents (e.g., 1500 = $15.00)

sell_price
number (Sell Price)

The retail price that customers pay to purchase this product variant, expressed in cents (e.g., 2000 = $20.00)

barcode
string or null (Barcode)

The barcode identifier used for inventory management and point-of-sale scanning of this specific product variant

reference
string or null (Reference Code)

An internal reference code used for inventory tracking and variant identification within the merchant system

Responses

Request samples

Content type
application/json
{
  • "product_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "variant_id": "var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "options": [
    ],
  • "tax_id": "dcc2a3cf-7357-40ab-8a3b-adc43d93afb0",
  • "buy_price": 1500,
  • "sell_price": 2000,
  • "barcode": "1234567890123",
  • "reference": "SHIRT-L-BLUE"
}

Response samples

Content type
application/json
{
  • "id": "7c5b8017-c28b-4e89-b056-5287f88d0a3d__20572f85-6236-4645-a65e-32dc1126dd99",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "product_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "variant_id": "var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "options": [
    ],
  • "order": 1,
  • "tax_id": "dcc2a3cf-7357-40ab-8a3b-adc43d93afb0",
  • "tax": {
    },
  • "buy_price": 1500,
  • "sell_price": 2000,
  • "barcode": "1234567890123",
  • "reference": "SHIRT-L-BLUE",
  • "is_selected": false
}

Update a product variant

Updates an existing product variant with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Product variant update payload

product_id
required
string (Parent Product ID)

The unique identifier of the parent product to which this variant belongs

variant_id
required
string (Variant ID)

The unique identifier of the variant being updated

Array of objects (Updated Variation Options)

The updated array of variation options that define the characteristics of this product variant

tax_id
string (Updated Tax ID)

The updated unique identifier of the tax rate to be applied to this product variant

buy_price
number (Updated Buy Price)

The updated cost price in cents that the business pays to acquire this product variant

sell_price
number (Updated Sell Price)

The updated retail price in cents that customers pay to purchase this product variant

barcode
string or null (Updated Barcode)

The updated barcode identifier for inventory management and point-of-sale scanning

reference
string or null (Updated Reference Code)

The updated internal reference code for inventory tracking and variant identification

Responses

Request samples

Content type
application/json
{
  • "product_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "variant_id": "var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "options": [
    ],
  • "tax_id": "dcc2a3cf-7357-40ab-8a3b-adc43d93afb0",
  • "buy_price": 1600,
  • "sell_price": 2100,
  • "barcode": "9876543210987",
  • "reference": "SHIRT-L-RED"
}

Response samples

Content type
application/json
{
  • "id": "7c5b8017-c28b-4e89-b056-5287f88d0a3d__20572f85-6236-4645-a65e-32dc1126dd99",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "product_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "variant_id": "var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "options": [
    ],
  • "order": 1,
  • "tax_id": "dcc2a3cf-7357-40ab-8a3b-adc43d93afb0",
  • "tax": {
    },
  • "buy_price": 1500,
  • "sell_price": 2000,
  • "barcode": "1234567890123",
  • "reference": "SHIRT-L-BLUE",
  • "is_selected": false
}

Get a product variant by ID

Retrieves a product variant by its unique identifier.

Authorizations:
apiKey
path Parameters
product_id
required
string <uuid> (Product ID)
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

The unique identifier of the parent product in UUID format

variant_id
required
string (Variant ID)
Example: var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d

The unique identifier of the specific product variant

Responses

Response samples

Content type
application/json
{
  • "id": "7c5b8017-c28b-4e89-b056-5287f88d0a3d__20572f85-6236-4645-a65e-32dc1126dd99",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "product_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "variant_id": "var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "options": [
    ],
  • "order": 1,
  • "tax_id": "dcc2a3cf-7357-40ab-8a3b-adc43d93afb0",
  • "tax": {
    },
  • "buy_price": 1500,
  • "sell_price": 2000,
  • "barcode": "1234567890123",
  • "reference": "SHIRT-L-BLUE",
  • "is_selected": false
}

Delete a product variant

Deletes a product variant by its unique identifier.

Authorizations:
apiKey
path Parameters
product_id
required
string <uuid> (Product ID)
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

The unique identifier of the parent product in UUID format

variant_id
required
string (Variant ID)
Example: var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d

The unique identifier of the specific product variant

Responses

Response samples

Content type
application/json
{
  • "id": "7c5b8017-c28b-4e89-b056-5287f88d0a3d__20572f85-6236-4645-a65e-32dc1126dd99",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "product_id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "variant_id": "var_cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "options": [
    ],
  • "order": 1,
  • "tax_id": "dcc2a3cf-7357-40ab-8a3b-adc43d93afb0",
  • "buy_price": 1500,
  • "sell_price": 2000,
  • "barcode": "1234567890123",
  • "reference": "SHIRT-L-BLUE",
  • "is_selected": false
}

Pack

Packs are bundles of products sold as a single line item. A pack groups one or more product variations with quantities and per-variation price adjustments — typical use cases are menus, kits, or combo offers.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • sell_price — integer minor units (cents). The pack's sell_price overrides the sum of its components' prices on the line item.
  • pack_variations[].options[].additional_price — integer minor units (cents); fine adjustments per included variation.
  • custom_fields — arrays of { custom_field_id, value }; values are typed by the referenced custom field (TEXT, NUMBER, or BOOLEAN).

Scopes

  • catalog:readGET /pack/:id, POST /pack/request.
  • catalog:writePOST /pack, PATCH /pack, DELETE /pack/:id, DELETE /pack/:id/custom-field/:customFieldId.

Filtering

POST /pack/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • A product referenced by a pack cannot be deleted until the pack is removed or the reference is dropped (see Product).
  • Detaching a single custom field from a pack uses DELETE /pack/:id/custom-field/:customFieldId; the custom-field definition is not deleted.

Create a pack

Creates a new pack in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Pack creation payload

name
required
string

Display name of the product bundle shown to customers

color
string
Enum: "GREEN" "LIME" "RED" "BLUE" "YELLOW" "ORANGE" "PINK" "PURPLE" "TURQUOISE" "GREY" "BROWN" "BLACK"

Visual color theme for the pack in the user interface

icon_text
string

Short text (usually initials) displayed as pack icon in the interface

photo
string

URL of the main pack image displayed to customers

barcode
string

Barcode number for the complete pack for inventory and scanning

reference
string

Internal reference code for the pack used for identification and inventory

sell_price
number

Total retail price for the complete pack in cents (overrides individual product pricing)

required
Array of objects non-empty

Different combinations of products that can be included in this pack bundle

Array of objects
Default: []

Additional custom data fields specific to your business needs for pack management

Responses

Request samples

Content type
application/json
{
  • "name": "Summer Pack",
  • "color": "BLUE",
  • "icon_text": "SP",
  • "barcode": "1234567890",
  • "reference": "PACK-001",
  • "sell_price": 2500,
  • "pack_variations": [
    ],
  • "custom_fields": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Summer Pack",
  • "color": "BLUE",
  • "icon_text": "SP",
  • "barcode": "1234567890",
  • "reference": "PACK-001",
  • "sell_price": 2500,
  • "pack_variations": [
    ],
  • "custom_fields": [
    ]
}

Update a pack

Updates an existing pack with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Pack update payload

id
required
string
name
string
barcode
string or null
reference
string or null
sell_price
number

Pack sell price (in cents)

Array of objects

Pack variations

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "name": "Updated Combo Pack",
  • "barcode": "1234567890123",
  • "reference": "PACK-001",
  • "sell_price": 2500,
  • "pack_variations": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Summer Pack",
  • "color": "BLUE",
  • "icon_text": "SP",
  • "barcode": "1234567890",
  • "reference": "PACK-001",
  • "sell_price": 2500,
  • "pack_variations": [
    ],
  • "custom_fields": [
    ]
}

Get a pack by ID

Retrieves a pack by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string
Example: ed18750a-0442-4be9-8c15-034e409ef225

Responses

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Summer Pack",
  • "color": "BLUE",
  • "icon_text": "SP",
  • "barcode": "1234567890",
  • "reference": "PACK-001",
  • "sell_price": 2500,
  • "pack_variations": [
    ],
  • "custom_fields": [
    ]
}

Delete a pack

Deletes a pack by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string
Example: ed18750a-0442-4be9-8c15-034e409ef225

Responses

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Summer Pack",
  • "color": "BLUE",
  • "icon_text": "SP",
  • "barcode": "1234567890",
  • "reference": "PACK-001",
  • "sell_price": 2500,
  • "pack_variations": [
    ],
  • "custom_fields": [
    ]
}

Remove a custom field from a pack

Deletes the connection between a pack and a custom field.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the parent resource

custom_field_id
required
string
Example: ba19240a-0442-4bd9-8c15-01b8409e1346__category_champpersotexte1

Unique identifier of the custom field to remove

Responses

Response samples

Content type
application/json
{
  • "id": "string"
}

Request packs with filtering

Retrieves a list of packs based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Pack request payload with filters

object (PackFilter)

Criteria for Pack. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Category

Categories group products in the catalog. Each product must belong to exactly one category. Categories drive cash-register navigation and segmented reporting.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • custom_fields — arrays of { custom_field_id, value }; values are typed by the referenced custom field (TEXT, NUMBER, or BOOLEAN).
  • image_upload — accepts either a base64 payload or a URL; not exposed on the response.

Scopes

  • catalog:readGET /category/:id, POST /category/request.
  • catalog:writePOST /category, PATCH /category, DELETE /category/:id, DELETE /category/:id/custom-field/:customFieldId.

Filtering

POST /category/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • A category cannot be deleted while it still contains products. Reassign or delete the products first; the API responds 403 Forbidden while the category is in use.
  • Detaching a single custom field uses DELETE /category/:id/custom-field/:customFieldId; the custom-field definition is not deleted.

Create a category

Creates a new category in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Category creation payload

id
string or null

Unique identifier of the category (auto-generated if not provided)

created_at
string or null

ISO 8601 timestamp when the category was created

updated_at
string or null

ISO 8601 timestamp when the category was last modified

name
required
string

Display name of the category used for product organization and navigation

color
string or null

Visual color theme for the category in the user interface

icon_text
string or null

Short text (1-2 characters) or emoji displayed as category icon

Array of objects
Default: []

Additional custom data fields specific to your business needs for category management

Responses

Request samples

Content type
application/json
{
  • "id": "cat_123",
  • "created_at": "2024-01-01T00:00:00Z",
  • "updated_at": "2024-01-02T00:00:00Z",
  • "name": "Beverages",
  • "color": "#FF0000",
  • "icon_text": "🍹",
  • "custom_fields": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "ea9f3f98-6f35-41e3-8c47-92fc313be733",
  • "name": "Ma catégorie 1",
  • "color": "BLUE",
  • "icon_text": "C",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "custom_fields": [
    ]
}

Update a category

Updates an existing category with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Category update payload

id
required
string
name
string
color
string
icon_text
string

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "name": "Updated Beverages",
  • "color": "#FF0000",
  • "icon_text": "🍹"
}

Response samples

Content type
application/json
{
  • "id": "ea9f3f98-6f35-41e3-8c47-92fc313be733",
  • "name": "Ma catégorie 1",
  • "color": "BLUE",
  • "icon_text": "C",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "custom_fields": [
    ]
}

Request categorys with filtering

Retrieves a list of categorys based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Category request payload with filters

object (CategoryFilter)

Criteria for Category. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Get a category by ID

Retrieves a category by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "ea9f3f98-6f35-41e3-8c47-92fc313be733",
  • "name": "Ma catégorie 1",
  • "color": "BLUE",
  • "icon_text": "C",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "custom_fields": [
    ]
}

Delete a category

Deletes a category by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "ea9f3f98-6f35-41e3-8c47-92fc313be733",
  • "name": "Ma catégorie 1",
  • "color": "BLUE",
  • "icon_text": "C",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Remove a custom field from a category

Deletes the connection between a category and a custom field.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the parent resource

custom_field_id
required
string
Example: ba19240a-0442-4bd9-8c15-01b8409e1346__category_champpersotexte1

Unique identifier of the custom field to remove

Responses

Response samples

Content type
application/json
{
  • "id": "string"
}

Tag

Tags are cross-cutting labels attached to products. They support search, filtering, and ad-hoc reporting groups (origin, seasonality, allergens, campaign, etc.) without forcing a category change.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Scopes

  • catalog:readGET /tag/:id, POST /tag/request.
  • catalog:writePOST /tag, PATCH /tag, DELETE /tag/:id.

Filtering

POST /tag/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • A tag cannot be deleted while it is still attached to one or more products. Detach the tag with DELETE /product/:id/tag/:tagId first; the API responds 403 Forbidden while the tag is in use.

Create a tag

Creates a new tag in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Tag creation payload

name
required
string [ 1 .. 100 ] characters

Name of the tag used for product organization and filtering

Responses

Request samples

Content type
application/json
{
  • "name": "Premium"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "name": "Premium",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Update a tag

Updates an existing tag with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Tag update payload

id
required
string
name
string

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "name": "Updated Tag"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "name": "Premium",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Get a tag by ID

Retrieves a tag by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "name": "Premium",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Delete a tag

Deletes a tag by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "name": "Premium",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Request tags with filtering

Retrieves a list of tags based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Tag request payload with filters

object (TagFilter)

Criteria for Tag. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Option

Options define the variants a product can take (size, colour, ingredient, supplement, etc.). Each option carries a list of values; each value can apply a price adjustment when selected.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • values[].additional_price — integer minor units (cents). Positive values raise the line total when the option is selected; negative values lower it.
  • An option must declare at least one value at creation.

Scopes

  • catalog:readGET /option/:id, POST /option/request.
  • catalog:writePOST /option, PATCH /option, DELETE /option/:id.

Filtering

POST /option/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • Detaching an option from a product is done from the product side: DELETE /product/:id/option/:optionId.

Create a option

Creates a new option in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Option creation payload

name
required
string

Name of the option category (e.g., "Size", "Color", "Material")

required
Array of objects non-empty

Available choices for this option, each with its own pricing

Responses

Request samples

Content type
application/json
{
  • "name": "Size",
  • "values": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "0dd7eeee-3f87-4bd7-a950-b1f1b7fb8726",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Size",
  • "values": [
    ]
}

Update a option

Updates an existing option with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Option update payload

id
required
string
name
string
Array of objects

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "name": "Updated Size",
  • "values": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "0dd7eeee-3f87-4bd7-a950-b1f1b7fb8726",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Size",
  • "values": [
    ]
}

Request options with filtering

Retrieves a list of options based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Option request payload with filters

object (OptionFilter)

Criteria for Option. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Get an option by ID

Retrieves an option by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 0dd7eeee-3f87-4bd7-a950-b1f1b7fb8726

Responses

Response samples

Content type
application/json
{
  • "id": "0dd7eeee-3f87-4bd7-a950-b1f1b7fb8726",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Size",
  • "values": [
    ]
}

Delete a option

Deletes a option by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 0dd7eeee-3f87-4bd7-a950-b1f1b7fb8726

Responses

Response samples

Content type
application/json
{
  • "id": "0dd7eeee-3f87-4bd7-a950-b1f1b7fb8726",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "name": "Size",
  • "values": [
    ]
}

Discount

Discounts are commercial reductions applied to sales. A discount is either percentage-based or a fixed amount, and is referenced by sales for reporting and reconciliation.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • type — enum: PERCENTAGE or NUMERIC.
  • rate:
    • When type = PERCENTAGE, an integer between 0 and 100 (whole percent points). 25 means a 25 % discount.
    • When type = NUMERIC, an integer in minor units (cents). 500 means €5.00 off.

Scopes

  • catalog:readGET /discount/:id, POST /discount/request.
  • catalog:writePOST /discount, PATCH /discount, DELETE /discount/:id.

Filtering

POST /discount/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • Discount references on past sales are preserved when the discount is deleted; deletion does not rewrite history.

Create a discount

Creates a new discount in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Discount creation payload

name
required
string

Display name of the discount shown to staff and customers

type
required
string
Enum: "PERCENTAGE" "NUMERIC"

Type of discount calculation: PERCENTAGE for percentage-based discounts or NUMERIC for fixed amount discounts

rate
required
number >= 0

Discount value - for PERCENTAGE type: percentage value (0-100), for NUMERIC type: amount in cents

Responses

Request samples

Content type
application/json
{
  • "name": "Black Friday",
  • "type": "PERCENTAGE",
  • "rate": 10
}

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "name": "Black Friday",
  • "type": "PERCENTAGE",
  • "rate": 10,
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Update a discount

Updates an existing discount with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Discount update payload

id
required
string
name
string
type
string
Enum: "PERCENTAGE" "NUMERIC"
rate
number >= 0

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "name": "Updated Black Friday",
  • "type": "PERCENTAGE",
  • "rate": 15
}

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "name": "Black Friday",
  • "type": "PERCENTAGE",
  • "rate": 10,
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Request discounts with filtering

Retrieves a list of discounts based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Discount request payload with filters

object (DiscountFilter)

Criteria for Discount. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Get a discount by ID

Retrieves a discount by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "name": "Black Friday",
  • "type": "PERCENTAGE",
  • "rate": 10,
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Delete a discount

Deletes a discount by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "name": "Black Friday",
  • "type": "PERCENTAGE",
  • "rate": 10,
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "updated_at": "2025-07-07T08:52:01.492Z"
}

Tax

Taxes declare the tax rates applied to products and packs. Every product must reference a tax for tax-inclusive pricing and tax reports.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • rate — basis points. 2000 is 20 %, 1900 is 19 %, 550 is 5.5 %. Valid range: 0 to 10000.

Scopes

  • settings:readGET /tax/:id.
  • settings:writePOST /tax, PATCH /tax, DELETE /tax/:id.

Taxes moved from catalog:* to settings:*. A key holding only catalog:* now receives 403 Forbidden; reissue it with settings:*.

Constraints

  • This resource exposes POST, GET /:id, PATCH, DELETE /:id only. There is no /request filter endpoint.
  • A tax rate cannot be deleted while any product still references it. Reassign affected products to another rate first; the API responds 403 Forbidden while the rate is in use.
  • During a regulation change, prefer creating a new tax rate over mutating an existing one — past sales reference the original tax record.

Create a tax

Creates a new tax in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Tax creation payload

rate
required
number [ 0 .. 10000 ]

Tax rate in basis points where 1 basis point = 0.01% (e.g., 1900 for 19% VAT, 2000 for 20% sales tax)

Responses

Request samples

Content type
application/json
{
  • "rate": 1900
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "rate": 1900,
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Update a tax

Updates an existing tax with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Tax update payload

id
required
string

Tax unique identifier

rate
number >= 0

Tax rate (in basis points, e.g. 2000 = 20%)

Responses

Request samples

Content type
application/json
{
  • "id": "tax_123",
  • "rate": 2100
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "rate": 1900,
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Get a tax by ID

Retrieves a tax by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 123e4567-e89b-12d3-a456-426614174000

Unique identifier of the tax rate configuration

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "rate": 1900,
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Delete a tax

Deletes a tax by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 123e4567-e89b-12d3-a456-426614174000

Unique identifier of the tax rate configuration

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "rate": 1900,
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Custom Field

Custom Fields extend the built-in resources (products, categories, packs, customers, cashbooks) with values specific to your business. A custom-field definition declares a key and a value type; instances of that field are then attached to records of the supported resources.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • type — enum: TEXT, NUMBER, BOOLEAN. The type controls the shape of every value attached to this field.
  • key — stable system identifier used by integrations; treat it as immutable once assigned.

Scopes

  • settings:readGET /custom-field/:id.
  • settings:writePOST /custom-field, PATCH /custom-field, DELETE /custom-field/:id.

Custom fields moved from catalog:* to settings:*. A key holding only catalog:* now receives 403 Forbidden; reissue it with settings:*.

Constraints

  • This resource exposes POST, GET /:id, DELETE /:id only. There is no PATCH and no /request filter endpoint — definitions are immutable once created and there is no public list operation.
  • A custom-field definition cannot be deleted while any record still references it. Detach the field from every record first using the resource-specific routes (for example DELETE /product/:id/custom-field/:customFieldId).

Create a custom field

Creates a new custom field in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Custom field creation payload

name
required
string [ 1 .. 100 ] characters

Human-readable name of the custom field displayed in the user interface

object_type
required
string
Enum: "PRODUCT" "PACK" "CATEGORY" "CASHBOOK" "CUSTOMER"

Type of object this custom field applies to (PRODUCT for products, CATEGORY for categories, CUSTOMER for customers, etc.)

value_type
required
string
Enum: "TEXT" "DATE" "NUMBER"

Data type of the custom field value (TEXT for text strings, NUMBER for numeric values, BOOLEAN for true/false, etc.)

key
required
string non-empty

Internal unique key used to identify this custom field in the system (must be unique within the object type)

Responses

Request samples

Content type
application/json
{
  • "name": "Brand",
  • "object_type": "PRODUCT",
  • "value_type": "TEXT",
  • "key": "brand_field"
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Brand",
  • "object_type": "PRODUCT",
  • "value_type": "TEXT",
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Update a custom field

Updates an existing custom field with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Custom field update payload

id
required
string

Custom field unique identifier

name
string [ 1 .. 100 ] characters

Human-readable name displayed in the user interface

Responses

Request samples

Content type
application/json
{
  • "id": "company_123__product_brand",
  • "name": "Marque"
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Brand",
  • "object_type": "PRODUCT",
  • "value_type": "TEXT",
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Get a custom field by ID

Retrieves a custom field by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string
Example: 123e4567-e89b-12d3-a456-426614174000

Unique identifier of the custom field definition

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Brand",
  • "object_type": "PRODUCT",
  • "value_type": "TEXT",
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Delete a custom field

Deletes a custom field by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string
Example: 123e4567-e89b-12d3-a456-426614174000

Unique identifier of the custom field definition

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Brand",
  • "object_type": "PRODUCT",
  • "value_type": "TEXT",
  • "created_at": "2023-01-01T00:00:00Z",
  • "updated_at": "2023-01-01T00:00:00Z"
}

Payment Method

Payment methods are the ways a customer can pay. Their identifiers are mandatory when recording a sale payment or a cashbook cash fund, so list them before posting any transaction.

Environment: bound to the API key's mode (test vs production); test and production payment methods are not visible across modes.

Field semantics

  • typeCASH, CREDIT_CARD, STRIPE or CUSTOM. Fixed at creation and cannot be changed afterwards; create a new payment method instead.
  • change_type — how change is handled when a customer overpays. CASH gives change from the drawer, NONE gives none.
  • opens_cash_drawer — whether accepting this payment opens the physical drawer.
  • enabled — whether the payment method can be selected on the till. Disabling is the safe alternative to deleting one that past sales reference.

Scopes

  • settings:readGET /payment-method/:id, POST /payment-method/request.
  • settings:writePOST /payment-method, PATCH /payment-method, DELETE /payment-method/:id.

Filtering

POST /payment-method/request takes limit and next_token only — there are no filter criteria on this resource. See Filters for the pagination rules.

Constraints

  • A sale payment and a cashbook cash fund both require payment_method_id, payment_method_name and payment_method_type. Read them here rather than hard-coding identifiers, which differ per company and per mode.
  • POST /payment-method/request returns every payment method of the company in one response, and total is the real count.
  • Past sales keep their own copy of the payment method name and type, so renaming one never rewrites history. Prefer disabling over deleting.

Create a payment method

Creates a new payment method in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Payment method creation payload

name
required
string non-empty
type
required
string
Enum: "CUSTOM" "CASH" "CREDIT_CARD" "STRIPE"
color
required
string
Enum: "GREEN" "LIME" "RED" "BLUE" "YELLOW" "ORANGE" "PINK" "PURPLE" "TURQUOISE"
change_type
string
Enum: "NONE" "CASH"
opens_cash_drawer
required
boolean
enabled
required
boolean

Responses

Request samples

Content type
application/json
{
  • "name": "Carte bancaire",
  • "type": "CREDIT_CARD",
  • "color": "BLUE",
  • "change_type": "NONE",
  • "opens_cash_drawer": false,
  • "enabled": true
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Carte bancaire",
  • "type": "CREDIT_CARD",
  • "color": "BLUE",
  • "change_type": "NONE",
  • "opens_cash_drawer": false,
  • "enabled": true
}

Update a payment method

Updates an existing payment method with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Payment method update payload

id
required
string
name
string non-empty
color
string
Enum: "GREEN" "LIME" "RED" "BLUE" "YELLOW" "ORANGE" "PINK" "PURPLE" "TURQUOISE"
change_type
string
Enum: "NONE" "CASH"
opens_cash_drawer
boolean
enabled
boolean

Responses

Request samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "enabled": false
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Carte bancaire",
  • "type": "CREDIT_CARD",
  • "color": "BLUE",
  • "change_type": "NONE",
  • "opens_cash_drawer": false,
  • "enabled": true
}

Get a payment method by ID

Retrieves a payment method by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 123e4567-e89b-12d3-a456-426614174000

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Carte bancaire",
  • "type": "CREDIT_CARD",
  • "color": "BLUE",
  • "change_type": "NONE",
  • "opens_cash_drawer": false,
  • "enabled": true
}

Delete a payment method

Deletes a payment method by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: 123e4567-e89b-12d3-a456-426614174000

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "name": "Carte bancaire",
  • "type": "CREDIT_CARD",
  • "color": "BLUE",
  • "change_type": "NONE",
  • "opens_cash_drawer": false,
  • "enabled": true
}

Request payment methods with filtering

Retrieves a list of payment methods based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Payment method request payload with filters

limit
integer [ 1 .. 100 ]
next_token
string

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Customer

Customers are the people or companies your sales are attributed to. They support named sales, deferred billing through customer accounts, and loyalty programmes.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • email, phone — both optional individually; at least one is recommended for contact.
  • address — structured object; postal code and country follow standard formats.
  • custom_fields — arrays of { custom_field_id, value }; values are typed by the referenced custom field (TEXT, NUMBER, or BOOLEAN).

Scopes

  • customer:readGET /customer/:id, POST /customer/request.
  • customer:writePOST /customer, PATCH /customer, DELETE /customer/:id, DELETE /customer/:id/custom-field/:customFieldId.

Filtering

POST /customer/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • Detaching a single custom field from a customer uses DELETE /customer/:id/custom-field/:customFieldId. The custom-field definition itself is not deleted.

Create a customer

Creates a new customer in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Customer creation payload

original_id
string or null

External customer ID from your existing system or third-party integrations

first_name
string or null

Customer's first name or given name

last_name
string or null

Customer's last name or family name

email
string or null

Customer's email address for communication and marketing

phone
string or null

Complete phone number including country code

phone_code
string or null

International dialing code for the phone number (e.g., +33 for France)

company_name
string or null

Name of the company or organization the customer represents

color
string or null
Enum: "GREEN" "LIME" "RED" "BLUE" "YELLOW" "ORANGE" "PINK" "PURPLE" "TURQUOISE" "GREY" "BROWN" "BLACK"

Visual color theme for the customer profile in the user interface

icon_text
string or null

Short text (usually initials) displayed as customer avatar in the interface

object or null
note
string or null

Internal notes or comments about the customer for staff reference

fidelity_card_number
string or null

Loyalty program card number or membership ID for rewards and points tracking

Array of objects
Default: []

Additional custom data fields specific to your business needs for customer management

Responses

Request samples

Content type
application/json
{
  • "original_id": "4r5Ty67",
  • "first_name": "John",
  • "last_name": "Doe",
  • "email": "john.doe@example.com",
  • "phone": "+33123456789",
  • "phone_code": "+33",
  • "company_name": "Acme Corp",
  • "color": "BLUE",
  • "icon_text": "JD",
  • "address": {
    },
  • "note": "VIP customer",
  • "fidelity_card_number": "FIDELITY123",
  • "custom_fields": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "original_id": "4r5Ty67",
  • "first_name": "John",
  • "last_name": "Doe",
  • "email": "john.doe@example.com",
  • "phone": "+33123456789",
  • "company_name": "Acme Corp",
  • "color": "BLUE",
  • "icon_text": "JD",
  • "address": {
    },
  • "note": "VIP customer",
  • "fidelity_card_number": "FIDELITY123",
  • "custom_fields": [
    ]
}

Update a customer

Updates an existing customer with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Customer update payload

id
required
string
first_name
string

Customer first name

last_name
string

Customer last name

email
string <email>

Customer email

phone
string

Customer phone

object

Customer address

company_name
string

Customer company name

company_vat_number
string

Customer company VAT number

Responses

Request samples

Content type
application/json
{
  • "id": "string",
  • "first_name": "John",
  • "last_name": "Doe",
  • "email": "john.doe@example.com",
  • "phone": "+1234567890",
  • "address": {
    },
  • "company_name": "ACME Corp",
  • "company_vat_number": "VAT123456789"
}

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "original_id": "4r5Ty67",
  • "first_name": "John",
  • "last_name": "Doe",
  • "email": "john.doe@example.com",
  • "phone": "+33123456789",
  • "company_name": "Acme Corp",
  • "color": "BLUE",
  • "icon_text": "JD",
  • "address": {
    },
  • "note": "VIP customer",
  • "fidelity_card_number": "FIDELITY123",
  • "custom_fields": [
    ]
}

Get a customer by ID

Retrieves a customer by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "original_id": "4r5Ty67",
  • "first_name": "John",
  • "last_name": "Doe",
  • "email": "john.doe@example.com",
  • "phone": "+33123456789",
  • "company_name": "Acme Corp",
  • "color": "BLUE",
  • "icon_text": "JD",
  • "address": {
    },
  • "note": "VIP customer",
  • "fidelity_card_number": "FIDELITY123",
  • "custom_fields": [
    ]
}

Delete a customer

Deletes a customer by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "ed18750a-0442-4be9-8c15-034e409ef225",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "original_id": "4r5Ty67",
  • "first_name": "John",
  • "last_name": "Doe",
  • "email": "john.doe@example.com",
  • "phone": "+33123456789",
  • "company_name": "Acme Corp",
  • "color": "BLUE",
  • "icon_text": "JD",
  • "address": {
    },
  • "note": "VIP customer",
  • "fidelity_card_number": "FIDELITY123"
}

Delete a customer custom field

Deletes a customer custom field by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the parent resource

custom_field_id
required
string
Example: ba19240a-0442-4bd9-8c15-01b8409e1346__category_champpersotexte1

Unique identifier of the custom field to remove

Responses

Response samples

Content type
application/json
{
  • "id": "string"
}

Request customers with filtering

Retrieves a list of customers based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Customer request payload with filters

object (CustomerFilter)

Criteria for Customer. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Sale

Sales are the commercial transactions recorded at the point of sale. A sale carries the items sold (products, packs, variations), discount and tax breakdown, the resulting payments, and the metadata needed for accounting and reporting.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • state — enum: OPEN, AVAILABLE, CLOSED, DELETED.
  • lines[].state — per-line enum: OK, REFUNDED. A sale can carry a mix of fulfilled and refunded lines.
  • Money fields (total, total_tax, total_tax_free, partial_totals[], line-level totals) — integer minor units (cents).
  • Dates (created_at, updated_at, line dates) — ISO 8601 UTC timestamps.
  • customer_id — optional UUID; named sale when present.

Lifecycle

  • OPEN — created with POST /sale. The cart can still be edited.
  • AVAILABLE — server-side intermediate state once the cart is finalised but before close.
  • CLOSED — terminal state for a settled sale; corresponding payments and cashbook movements have been recorded.
  • DELETED — soft-deleted; preserved for history.

Scopes

  • sale:readGET /sale/:id, POST /sale/request.
  • sale:writePOST /sale, PATCH /sale.

Filtering

POST /sale/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • This resource exposes POST, GET /:id, PATCH, POST /request. There is no DELETE — sales are never hard-deleted; use the DELETED state where needed.
  • Refunds operate at the line level via lines[].state = REFUNDED; partial refunds are first-class.
  • Once a sale is CLOSED, the lines and totals are immutable.

Create a sale

Creates a new sale in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Sale creation payload

original_id
string

Original sale identifier if this is a copy or migration from another system - used for data traceability and audit purposes

shop_id
required
string

Unique identifier of the shop where the sale is taking place - determines inventory, pricing, and tax rules

source_id
required
string

Unique identifier of the source system or device creating the sale - used for tracking transaction origins

source_name
required
string

Human-readable name of the source system or device - helps staff identify which terminal processed the sale

cashbook_id
string

Unique identifier of the cashbook associated with this sale - determines cash flow tracking and reporting

name
string

Custom name or description for the sale transaction - useful for restaurant table management or special orders

number
number

Sequential number assigned to the sale for reference - used for receipt numbering and record keeping

state
required
string
Enum: "OPEN" "AVAILABLE" "CLOSED" "DELETED"

Current state of the sale (OPEN for in-progress, AVAILABLE for ready to pay, CLOSED for completed, DELETED for cancelled)

refund_status
required
string
Enum: "NONE" "PARTIAL" "FULL"

Status of refund processing (NONE for no refunds, PARTIAL for some items refunded, FULL for completely refunded)

refunded_status
required
string
Enum: "NONE" "PARTIAL" "FULL"

Status indicating if this sale has been refunded (NONE for original sale, PARTIAL/FULL for refunds of other sales)

payment_status
required
string
Enum: "NONE" "PARTIAL" "FULL"

Status of payment processing (NONE for unpaid, PARTIAL for partially paid, FULL for completely paid)

note
string

Additional notes or comments about the sale - used for special instructions or customer preferences

target_id
string

Identifier of the target sale for refund or return operations - links this refund to the original sale

opened_at
required
string

ISO 8601 timestamp when the sale was opened - marks the beginning of the transaction

closed_at
string

ISO 8601 timestamp when the sale was closed - marks the completion of the transaction

pending_at
string

ISO 8601 timestamp when the sale was set to pending status - used for payment processing workflows

customer_id
string

Unique identifier of the customer associated with this sale - enables loyalty programs and customer history

seller_id
string

Unique identifier of the seller or employee handling the sale - used for commission tracking and performance analytics

Array of objects

List of sale line items containing products, quantities, and prices - represents the actual items being purchased

Array of objects

List of discounts applied to the sale - includes percentage discounts, fixed amount discounts, and promotional codes

Array of objects

List of payments made for this sale - supports multiple payment methods like cash, card, and digital payments

total
required
number

Total amount of the sale including all taxes and discounts - this is the final amount the customer pays

total_discount
required
number

Total discount amount applied to the sale - sum of all discounts before tax calculations

total_tax_free
required
number

Total amount of the sale excluding taxes - used for tax reporting and accounting purposes

total_tax
required
number

Total tax amount applied to the sale - sum of all taxes calculated on the sale items

total_rest
required
number

Remaining amount to be paid for the sale - becomes 0 when sale is fully paid

Responses

Request samples

Content type
application/json
{
  • "original_id": "SALE-001",
  • "shop_id": "123e4567-e89b-12d3-a456-426614174000",
  • "source_id": "123e4567-e89b-12d3-a456-426614174001",
  • "source_name": "POS Terminal 1",
  • "cashbook_id": "123e4567-e89b-12d3-a456-426614174002",
  • "name": "Table 5 - Lunch Service",
  • "number": 1001,
  • "state": "OPEN",
  • "refund_status": "NONE",
  • "refunded_status": "NONE",
  • "payment_status": "NONE",
  • "note": "Customer requested extra napkins",
  • "target_id": "123e4567-e89b-12d3-a456-426614174003",
  • "opened_at": "2024-01-15T10:00:00Z",
  • "closed_at": "2024-01-15T10:30:00Z",
  • "pending_at": "2024-01-15T10:25:00Z",
  • "customer_id": "123e4567-e89b-12d3-a456-426614174000",
  • "seller_id": "123e4567-e89b-12d3-a456-426614174000",
  • "lines": [
    ],
  • "discounts": [
    ],
  • "payments": [
    ],
  • "total": 125.5,
  • "total_discount": 12.5,
  • "total_tax_free": 104.17,
  • "total_tax": 21.33,
  • "total_rest": 0
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "original_id": "SALE-001",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "shop_id": "123e4567-e89b-12d3-a456-426614174000",
  • "source_id": "123e4567-e89b-12d3-a456-426614174001",
  • "source_name": "POS Terminal 1",
  • "cashbook_id": "123e4567-e89b-12d3-a456-426614174002",
  • "name": "Table 5 - Lunch Service",
  • "number": 1001,
  • "state": "OPEN",
  • "refund_status": "NONE",
  • "refunded_status": "NONE",
  • "payment_status": "NONE",
  • "note": "Customer requested extra napkins",
  • "target_id": "123e4567-e89b-12d3-a456-426614174003",
  • "opened_at": "2024-01-15T10:00:00Z",
  • "closed_at": "2024-01-15T10:30:00Z",
  • "pending_at": "2024-01-15T10:25:00Z",
  • "customer_id": "123e4567-e89b-12d3-a456-426614174004",
  • "seller_id": "123e4567-e89b-12d3-a456-426614174005",
  • "total": 125.5,
  • "total_discount": 12.5,
  • "total_tax_free": 104.17,
  • "total_tax": 21.33,
  • "total_rest": 0,
  • "cashbook": {
    },
  • "customer": {
    },
  • "seller": {
    },
  • "target_sale": {
    },
  • "refund_sales": {
    },
  • "lines": [
    ],
  • "discounts": [
    ],
  • "payments": [
    ],
  • "stats": {
    }
}

Update a sale

Updates an existing sale with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Sale update payload

id
required
string (Sale Identifier)

Unique identifier of the sale to update - this field is required to specify which sale transaction should be modified

source_id
string (Source System Identifier)

Unique identifier of the source system or device - update to change which system is credited with processing the sale

source_name
string (Source System Name)

Human-readable name of the source system or device - useful for updating terminal assignments or corrections

cashbook_id
string (Cashbook Identifier)

Unique identifier of the cashbook to associate with this sale - change to move sale between cashbooks for accounting purposes

name
string (Sale Name)

Custom name or description for the sale transaction - update for table reassignments or order clarifications

number
number (Sale Number)

Sequential number assigned to the sale for reference - update for receipt numbering corrections or adjustments

state
string (Sale State)
Enum: "OPEN" "AVAILABLE" "CLOSED" "DELETED"

Current state of the sale transaction - update to progress sale through workflow (OPEN → AVAILABLE → CLOSED) or cancel (DELETED)

refund_status
string (Refund Processing Status)
Enum: "NONE" "PARTIAL" "FULL"

Status of refund processing for this sale - update when processing refunds (NONE → PARTIAL → FULL)

refunded_status
string (Refunded Transaction Status)
Enum: "NONE" "PARTIAL" "FULL"

Status indicating if this sale has been refunded by other transactions - system typically manages this automatically

payment_status
string (Payment Processing Status)
Enum: "NONE" "PARTIAL" "FULL"

Status of payment processing for this sale - update when payments are processed (NONE → PARTIAL → FULL)

note
string (Sale Notes)

Additional notes or comments about the sale - update to add special instructions, customer preferences, or staff communications

target_id
string (Target Sale Identifier)

Identifier of the target sale for refund operations - set when converting a sale to a refund or linking refund transactions

closed_at
string (Sale Closed Timestamp)

ISO 8601 timestamp when the sale was closed - set when finalizing the transaction and completing payment

pending_at
string (Sale Pending Timestamp)

ISO 8601 timestamp when the sale was set to pending status - set during payment processing workflows or approval processes

customer_id
string (Customer Identifier)

Unique identifier of the customer - update to assign or change customer association for loyalty programs and history tracking

seller_id
string (Seller Identifier)

Unique identifier of the seller or employee - update to reassign commission credit or correct staff assignments

Array of objects (Sale Line Items)

List of sale line items containing products, quantities, and prices - update to add, remove, or modify items in the sale

Array of objects (Applied Discounts)

List of discounts applied to the sale - update to add promotional codes, loyalty discounts, or remove invalid discounts

Array of objects (Payment Transactions)

List of payments made for this sale - update to process new payments, add payment methods, or handle refunds

total
number (Sale Total Amount)

Total amount of the sale including all taxes and discounts - typically calculated automatically but can be overridden for adjustments

total_discount
number (Total Discount Amount)

Total discount amount applied to the sale - update when applying additional discounts or correcting discount calculations

total_tax_free
number (Tax-Free Total Amount)

Total amount of the sale excluding taxes - typically calculated automatically for tax reporting compliance

total_tax
number (Total Tax Amount)

Total tax amount applied to the sale - update when tax rates change or tax exemptions are applied

total_rest
number (Remaining Amount)

Remaining amount to be paid for the sale - update when processing partial payments or adjusting payment amounts

Responses

Request samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "source_id": "123e4567-e89b-12d3-a456-426614174001",
  • "source_name": "POS Terminal 2",
  • "cashbook_id": "123e4567-e89b-12d3-a456-426614174002",
  • "name": "Table 7 - Dinner Service",
  • "number": 1002,
  • "state": "CLOSED",
  • "refund_status": "PARTIAL",
  • "refunded_status": "NONE",
  • "payment_status": "FULL",
  • "note": "Customer paid with cash - change given",
  • "target_id": "123e4567-e89b-12d3-a456-426614174003",
  • "closed_at": "2024-01-15T11:00:00Z",
  • "pending_at": "2024-01-15T10:55:00Z",
  • "customer_id": "123e4567-e89b-12d3-a456-426614174004",
  • "seller_id": "123e4567-e89b-12d3-a456-426614174005",
  • "lines": [
    ],
  • "discounts": [
    ],
  • "payments": [
    ],
  • "total": 135.75,
  • "total_discount": 15.25,
  • "total_tax_free": 113.13,
  • "total_tax": 22.62,
  • "total_rest": 0
}

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "original_id": "SALE-001",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "shop_id": "123e4567-e89b-12d3-a456-426614174000",
  • "source_id": "123e4567-e89b-12d3-a456-426614174001",
  • "source_name": "POS Terminal 1",
  • "cashbook_id": "123e4567-e89b-12d3-a456-426614174002",
  • "name": "Table 5 - Lunch Service",
  • "number": 1001,
  • "state": "OPEN",
  • "refund_status": "NONE",
  • "refunded_status": "NONE",
  • "payment_status": "NONE",
  • "note": "Customer requested extra napkins",
  • "target_id": "123e4567-e89b-12d3-a456-426614174003",
  • "opened_at": "2024-01-15T10:00:00Z",
  • "closed_at": "2024-01-15T10:30:00Z",
  • "pending_at": "2024-01-15T10:25:00Z",
  • "customer_id": "123e4567-e89b-12d3-a456-426614174004",
  • "seller_id": "123e4567-e89b-12d3-a456-426614174005",
  • "total": 125.5,
  • "total_discount": 12.5,
  • "total_tax_free": 104.17,
  • "total_tax": 21.33,
  • "total_rest": 0,
  • "cashbook": {
    },
  • "customer": {
    },
  • "seller": {
    },
  • "target_sale": {
    },
  • "refund_sales": {
    },
  • "lines": [
    ],
  • "discounts": [
    ],
  • "payments": [
    ],
  • "stats": {
    }
}

Get a sale by ID

Retrieves a sale by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string (Sale Identifier)
Example: 123e4567-e89b-12d3-a456-426614174000

Unique identifier of the sale to perform operations on - used in URL path parameters to specify which sale to retrieve, update, or delete

Responses

Response samples

Content type
application/json
{
  • "id": "123e4567-e89b-12d3-a456-426614174000",
  • "original_id": "SALE-001",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "shop_id": "123e4567-e89b-12d3-a456-426614174000",
  • "source_id": "123e4567-e89b-12d3-a456-426614174001",
  • "source_name": "POS Terminal 1",
  • "cashbook_id": "123e4567-e89b-12d3-a456-426614174002",
  • "name": "Table 5 - Lunch Service",
  • "number": 1001,
  • "state": "OPEN",
  • "refund_status": "NONE",
  • "refunded_status": "NONE",
  • "payment_status": "NONE",
  • "note": "Customer requested extra napkins",
  • "target_id": "123e4567-e89b-12d3-a456-426614174003",
  • "opened_at": "2024-01-15T10:00:00Z",
  • "closed_at": "2024-01-15T10:30:00Z",
  • "pending_at": "2024-01-15T10:25:00Z",
  • "customer_id": "123e4567-e89b-12d3-a456-426614174004",
  • "seller_id": "123e4567-e89b-12d3-a456-426614174005",
  • "total": 125.5,
  • "total_discount": 12.5,
  • "total_tax_free": 104.17,
  • "total_tax": 21.33,
  • "total_rest": 0,
  • "cashbook": {
    },
  • "customer": {
    },
  • "seller": {
    },
  • "target_sale": {
    },
  • "refund_sales": {
    },
  • "lines": [
    ],
  • "discounts": [
    ],
  • "payments": [
    ],
  • "stats": {
    }
}

Request sales with filtering

Retrieves a list of sales based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Sale request payload with filters

object (SaleFilter)

Criteria for Sale. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  • "total": 1523
}

Payment

Payments record financial transactions tied to sales — cash, card, voucher, refund, and so on. Each payment is bound to a parent sale and to a payment method, and contributes to cashbook reconciliation.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • state — enum: VALID, DELETED.
  • amount, total_tax, total_tax_free — integer minor units (cents).
  • date, created_at, updated_at — ISO 8601 UTC timestamps.
  • sale_id, cashbook_id, payment_method_id — UUID references; mandatory at issue time.

Scopes

  • payment:readGET /payment/:id, POST /payment/request.

Filtering

POST /payment/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • This resource is read-only over the public API. It exposes GET /payment/:id and POST /payment/request only — there is no POST, PATCH, or DELETE. Payments are created server-side as part of the sale flow.

Get a payment by ID

Retrieves a payment by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890

Unique UUID identifier of the payment to retrieve or modify

Responses

Response samples

Content type
application/json
{
  • "id": "pay_123456789",
  • "original_id": "orig_987654321",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "shop_id": "shop_xyz789uvw012",
  • "sale_id": "sale_456789abc123",
  • "source_id": "src_pos_terminal_01",
  • "source_name": "POS Terminal #1",
  • "state": "VALID",
  • "type": "IN",
  • "date": "2024-01-01T10:00:00Z",
  • "number": 1001,
  • "payment_method_id": "pm_cash_001",
  • "payment_method_name": "Cash",
  • "payment_method_type": "CASH",
  • "source_payment_id": "sp_external_123456",
  • "customer_movement_id": "cm_abc123def456",
  • "cashbook_id": "cb_main_register",
  • "amount": 1200,
  • "total_tax_free": 1000,
  • "total_tax": 200,
  • "integration_payment_id": "stripe_pi_1234567890",
  • "integration_refund_id": "stripe_re_0987654321",
  • "taxes": [
    ]
}

Request payments with filtering

Retrieves a list of payments based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Payment request payload with filters

object (PaymentFilter)

Criteria for Payment. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Cashbook

Cashbooks represent point-of-sale work sessions, from opening to closing. A cashbook groups every sale and payment recorded during the session, tracks the cash drawer counts, and produces the figures used for daily reconciliation.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • state — enum: OPEN, CLOSED.
  • opening_cash_fund, closing_cash_fund, total, total_expected, total_difference — integer minor units (cents).
  • opened_at, closed_at — ISO 8601 UTC timestamps.

Lifecycle

  • OPEN — created with POST /cashbook. Sales and payments accumulate against the open cashbook of the shop.
  • CLOSED — set via PATCH /cashbook/:id with closing counts. Once closed, the cashbook can no longer record new movements.

Scopes

  • cashbook:readGET /cashbook/:id, POST /cashbook/request.
  • cashbook:writePOST /cashbook, PATCH /cashbook/:id, DELETE /cashbook/:id.

Filtering

POST /cashbook/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • A cashbook can only transition OPEN → CLOSED. Attempts to close an already-closed cashbook are rejected.
  • Closure performs the reconciliation between expected and counted amounts; the difference is recorded on total_difference.

Create a cashbook

Creates a new cashbook in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Cashbook creation payload

shop_id
required
string

Unique identifier of the shop where this cashbook operates

source_id
required
string

Identifier of the POS terminal or system creating this cashbook

source_name
required
string

Human-readable name of the POS terminal or system for identification

number
required
number

Sequential number of this cashbook session for the day or period

state
required
string
Enum: "OPEN" "CLOSED"

Initial state of the cashbook - typically OPEN when creating a new session

total
number

Initial total sales amount for this cashbook session in cents

total_tax_free
number

Initial total amount excluding taxes for this session in cents

min_sale_number
number

Starting minimum sale number for this cashbook session

max_sale_number
number

Starting maximum sale number for this cashbook session

sales_count
number

Initial count of sales for this session

min_payment_number
number

Starting minimum payment number for this cashbook session

max_payment_number
number

Starting maximum payment number for this cashbook session

payments_count
number

Initial count of payments for this session

opened_at
required
string

ISO 8601 timestamp when the cashbook session is opened

closed_at
string

ISO 8601 timestamp when the cashbook session will be closed (optional at creation)

note
string

Optional notes or comments about this cashbook session for reference

opening_seller_id
string

Unique identifier of the seller opening this cashbook

closing_seller_id
string

Unique identifier of the seller who will close this cashbook (optional at creation)

total_expected
number

Expected total cash amount that should be in the drawer at closing in cents

total_difference
number

Difference between expected and actual cash amounts in cents (calculated at closing)

Array of objects

Initial cash movements (additions or removals) for this cashbook session

Array of objects

Starting cash amounts by payment method at the beginning of the cashbook session

Array of objects

Final cash amounts by payment method at the end of the cashbook session (optional at creation)

Array of objects

Additional custom data fields specific to your business needs for cashbook management

Responses

Request samples

Content type
application/json
{
  • "shop_id": "shop_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "source_id": "pos_terminal_001",
  • "source_name": "Main Register",
  • "number": 1,
  • "state": "OPEN",
  • "total": 0,
  • "total_tax_free": 0,
  • "min_sale_number": 1001,
  • "max_sale_number": 1000,
  • "sales_count": 0,
  • "min_payment_number": 2001,
  • "max_payment_number": 2000,
  • "payments_count": 0,
  • "opened_at": "2023-01-01T09:00:00Z",
  • "closed_at": "2023-01-01T18:00:00Z",
  • "note": "Starting new shift",
  • "opening_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "closing_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "total_expected": 15000,
  • "total_difference": 0,
  • "movements": [
    ],
  • "opening_cash_fund": [
    ],
  • "closing_cash_fund": [
    ],
  • "custom_fields": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "cb_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "original_id": "CB-2023-001",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "shop_id": "shop_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "source_id": "pos_terminal_001",
  • "source_name": "Main Register",
  • "number": 1,
  • "state": "OPEN",
  • "total": 45670,
  • "total_tax_free": 38000,
  • "min_sale_number": 1001,
  • "max_sale_number": 1045,
  • "sales_count": 45,
  • "min_payment_number": 2001,
  • "max_payment_number": 2087,
  • "payments_count": 87,
  • "opened_at": "2023-01-01T09:00:00Z",
  • "closed_at": "2023-01-01T18:00:00Z",
  • "opening_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "closing_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "note": "Busy Saturday shift",
  • "total_expected": 45000,
  • "total_difference": 670,
  • "opening_seller": {
    },
  • "closing_seller": {
    },
  • "movements": [
    ],
  • "opening_cash_fund": [
    ],
  • "closing_cash_fund": [
    ],
  • "custom_fields": [
    ],
  • "stats": {
    }
}

Get a cashbook by ID

Retrieves a cashbook by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

Responses

Response samples

Content type
application/json
{
  • "id": "cb_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "original_id": "CB-2023-001",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "shop_id": "shop_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "source_id": "pos_terminal_001",
  • "source_name": "Main Register",
  • "number": 1,
  • "state": "OPEN",
  • "total": 45670,
  • "total_tax_free": 38000,
  • "min_sale_number": 1001,
  • "max_sale_number": 1045,
  • "sales_count": 45,
  • "min_payment_number": 2001,
  • "max_payment_number": 2087,
  • "payments_count": 87,
  • "opened_at": "2023-01-01T09:00:00Z",
  • "closed_at": "2023-01-01T18:00:00Z",
  • "opening_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "closing_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "note": "Busy Saturday shift",
  • "total_expected": 45000,
  • "total_difference": 670,
  • "opening_seller": {
    },
  • "closing_seller": {
    },
  • "movements": [
    ],
  • "opening_cash_fund": [
    ],
  • "closing_cash_fund": [
    ],
  • "custom_fields": [
    ],
  • "stats": {
    }
}

Update a cashbook

Updates an existing cashbook with the provided data.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>

Cashbook ID

Request Body schema: application/json
required

Cashbook update payload

id
required
string <uuid>

Unique identifier of the cashbook

state
string
Enum: "OPEN" "CLOSED"

Updated state of the cashbook - use CLOSED to finalize the session

total
number

Updated total sales amount processed during this cashbook session in cents

total_tax_free
number

Updated total amount excluding taxes processed during this session in cents

min_sale_number
number

Updated lowest sale number recorded in this cashbook session

max_sale_number
number

Updated highest sale number recorded in this cashbook session

sales_count
number

Updated total number of sales processed in this session

min_payment_number
number

Updated lowest payment number recorded in this cashbook session

max_payment_number
number

Updated highest payment number recorded in this cashbook session

payments_count
number

Updated total number of payments processed in this session

closed_at
string

ISO 8601 timestamp when the cashbook session was closed

note
string

Updated notes or comments about this cashbook session for reference

closing_seller_id
string

Unique identifier of the seller closing this cashbook

total_expected
number

Updated expected total cash amount that should be in the drawer at closing in cents

total_difference
number

Updated difference between expected and actual cash amounts at closing in cents (positive = surplus, negative = shortage)

Array of objects

Updated list of cash movements (additions or removals) during this cashbook session

Array of objects

Updated final cash amounts by payment method at the end of the cashbook session

Array of objects

Updated custom data fields specific to your business needs for cashbook management

Responses

Request samples

Content type
application/json
{
  • "id": "0dd7eeee-3f87-4bd7-a950-b1f1b7fb8726",
  • "state": "CLOSED",
  • "total": 45670,
  • "total_tax_free": 38000,
  • "min_sale_number": 1001,
  • "max_sale_number": 1045,
  • "sales_count": 45,
  • "min_payment_number": 2001,
  • "max_payment_number": 2087,
  • "payments_count": 87,
  • "closed_at": "2023-01-01T18:00:00Z",
  • "note": "Successful busy day shift",
  • "closing_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "total_expected": 45000,
  • "total_difference": 670,
  • "movements": [
    ],
  • "closing_cash_fund": [
    ],
  • "custom_fields": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "cb_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "original_id": "CB-2023-001",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "shop_id": "shop_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "source_id": "pos_terminal_001",
  • "source_name": "Main Register",
  • "number": 1,
  • "state": "OPEN",
  • "total": 45670,
  • "total_tax_free": 38000,
  • "min_sale_number": 1001,
  • "max_sale_number": 1045,
  • "sales_count": 45,
  • "min_payment_number": 2001,
  • "max_payment_number": 2087,
  • "payments_count": 87,
  • "opened_at": "2023-01-01T09:00:00Z",
  • "closed_at": "2023-01-01T18:00:00Z",
  • "opening_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "closing_seller_id": "seller_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "note": "Busy Saturday shift",
  • "total_expected": 45000,
  • "total_difference": 670,
  • "opening_seller": {
    },
  • "closing_seller": {
    },
  • "movements": [
    ],
  • "opening_cash_fund": [
    ],
  • "closing_cash_fund": [
    ],
  • "custom_fields": [
    ],
  • "stats": {
    }
}

Delete a cashbook

Deletes a cashbook by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid>
Example: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

Responses

Response samples

Content type
application/json
{
  • "id": "cb_ba19240a-0442-4bd9-8c15-01b8409e1346",
  • "success": true
}

Request cashbooks with filtering

Retrieves a list of cashbooks based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Cashbook request payload with filters

object (CashbookFilter)

Criteria for Cashbook. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_token": "xxx.yyy.zzz",
  • "total": 10
}

Stock

Stock movements record on-hand changes for products and variants — receipts, transfers, write-offs, adjustments. A movement is the unit of audit for everything that touches the quantities tracked by the catalog.

Environment: bound to the API key's mode (test vs production); test and production data are not visible across modes.

Field semantics

  • state — enum: DRAFT, CLOSED, CANCELLED.
  • Money fields (line costs, totals) — integer minor units (cents).
  • Date fields — ISO 8601 UTC timestamps.

Lifecycle

  • DRAFT — created with POST /inventorymovement. The movement can still be edited.
  • CLOSED — terminal state once the movement is committed; the on-hand stock is updated. POST returns HTTP 200 (not 201) because the operation may also commit downstream stock changes.
  • CANCELLED — terminal state for an aborted movement; the stock is left unchanged.

Scopes

  • inventory:readGET /inventorymovement/:id, POST /inventorymovement/request.
  • inventory:writePOST /inventorymovement, PATCH /inventorymovement, DELETE /inventorymovement/:id.

Filtering

POST /inventorymovement/request uses the shared search contract: filter, sort, limit and next_token. The filterable fields are listed in the request schema above; the operators, how and / or / not combine, and the pagination rules are described once under Filters.

Unknown criteria are rejected with 400 rather than ignored.

Constraints

  • The optional update_prices flag on PATCH propagates the unit cost from the movement onto the underlying products/variants. Default is no propagation; pass true only when the movement should rewrite catalog pricing.
  • A movement in CLOSED or CANCELLED state cannot be edited; create a new corrective movement instead.

Create a inventory movement

Creates a new inventory movement in the desired company.

Authorizations:
apiKey
Request Body schema: application/json
required

Inventory movement creation payload

update_prices
boolean (Update Price)
Default: false

Whether to update the prices of the products in the inventory movement

state
required
string (State)
Enum: "DRAFT" "CLOSED" "CANCELLED"

Initial state of the inventory movement

motive
string (Motive)

Reason or motivation for the inventory movement operation

origin
string (Origin)
Enum: "SHOP" "SUPPLIER"

Source location type where inventory is being moved from

origin_id
string (Origin ID)

Unique identifier of the specific origin location

destination
string (Destination)
Enum: "SHOP" "TRASH"

Target location type where inventory is being moved to

destination_id
string (Destination ID)

Unique identifier of the specific destination location

Array of objects (Insertions)

Array of product line items to add to the inventory movement

Responses

Request samples

Content type
application/json
{
  • "update_prices": false,
  • "state": "DRAFT",
  • "motive": "Regular stock transfer between locations",
  • "origin": "SHOP",
  • "origin_id": "shop-a-001",
  • "destination": "SHOP",
  • "destination_id": "shop-b-002",
  • "insertions": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "state": "DRAFT",
  • "state_date": "2025-07-02T10:26:31.829Z",
  • "motive": "Stock transfer between shops",
  • "origin": "SHOP",
  • "origin_id": "shop-001",
  • "destination": "SHOP",
  • "destination_id": "shop-002",
  • "total_quantity": 500,
  • "number_of_products": 25,
  • "number_of_variants": 15,
  • "number_of_products_or_variants": 40,
  • "number_of_lines": 30,
  • "number_of_lines_with_price": 28,
  • "number_of_lines_with_quantity": 30
}

Update a inventory movement

Updates an existing inventory movement with the provided data.

Authorizations:
apiKey
Request Body schema: application/json
required

Inventory movement update payload

id
required
string <uuid> (ID)

Unique identifier of the inventory movement to update

state
string (State)
Enum: "DRAFT" "CLOSED" "CANCELLED"

Updated state of the inventory movement

name
string (Name)

New display name for the inventory movement

motive
string (Motive)

Updated reason for the inventory movement operation

origin
string (Origin)
Enum: "SHOP" "SUPPLIER"

Updated source location type for the inventory movement

origin_id
string (Origin ID)

Updated unique identifier of the origin location

destination
string (Destination)
Enum: "SHOP" "TRASH"

Updated target location type for the inventory movement

destination_id
string (Destination ID)

Updated unique identifier of the destination location

Array of objects (Insertions)

Array of product line items to add to the inventory movement

Array of objects (Deletions)

Array of product line items to delete from the inventory movement

Array of objects (Modifications)

Array of product line items to modify in the inventory movement

update_prices
required
boolean

Update prices of the products?

Responses

Request samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "state": "DRAFT",
  • "name": "Updated Stock Transfer Operation",
  • "motive": "Emergency stock rebalancing",
  • "origin": "SHOP",
  • "origin_id": "shop-main-001",
  • "destination": "SHOP",
  • "destination_id": "shop-branch-002",
  • "insertions": [
    ],
  • "deletions": [
    ],
  • "modifications": [
    ],
  • "update_prices": true
}

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "state": "DRAFT",
  • "state_date": "2025-07-02T10:26:31.829Z",
  • "motive": "Stock transfer between shops",
  • "origin": "SHOP",
  • "origin_id": "shop-001",
  • "destination": "SHOP",
  • "destination_id": "shop-002",
  • "total_quantity": 500,
  • "number_of_products": 25,
  • "number_of_variants": 15,
  • "number_of_products_or_variants": 40,
  • "number_of_lines": 30,
  • "number_of_lines_with_price": 28,
  • "number_of_lines_with_quantity": 30
}

Get a inventory movement by ID

Retrieves a inventory movement by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid> (ID)
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the inventory movement

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d",
  • "updated_at": "2025-07-07T08:52:01.492Z",
  • "created_at": "2025-06-30T15:32:27.290Z",
  • "deprecated": false,
  • "state": "DRAFT",
  • "state_date": "2025-07-02T10:26:31.829Z",
  • "motive": "Stock transfer between shops",
  • "origin": "SHOP",
  • "origin_id": "shop-001",
  • "destination": "SHOP",
  • "destination_id": "shop-002",
  • "total_quantity": 500,
  • "number_of_products": 25,
  • "number_of_variants": 15,
  • "number_of_products_or_variants": 40,
  • "number_of_lines": 30,
  • "number_of_lines_with_price": 28,
  • "number_of_lines_with_quantity": 30
}

Delete a inventory movement

Deletes a inventory movement by its unique identifier.

Authorizations:
apiKey
path Parameters
id
required
string <uuid> (ID)
Example: cb75a73d-0c3b-4b38-8064-56b6ec77c10d

Unique identifier of the inventory movement

Responses

Response samples

Content type
application/json
{
  • "id": "cb75a73d-0c3b-4b38-8064-56b6ec77c10d"
}

Request inventory movements with filtering

Retrieves a list of inventory movements based on the provided filters.

Authorizations:
apiKey
Request Body schema: application/json
required

Inventory movement request payload with filters

object (InventorymovementFilter)

Criteria for Inventorymovement. Operators combine one level deep: and, or and not take a plain filter, not another combination. Unknown criteria are rejected.

object
limit
integer [ 1 .. 100 ]

Maximum number of items to return (between 1 and 100)

next_token
string

Pagination cursor token returned from a previous request

Responses

Request samples

Content type
application/json
{
  • "filter": {
    },
  • "sort": {
    },
  • "limit": 20,
  • "next_token": "eyJpZCI6IjEyMyJ9"
}

Response samples

Content type
application/json
[
  • {
    }
]