Skip to content
StippaStippa
FeaturesPricingDemoFAQContact
Log inGet started

Getting started

  • Introduction
  • Authentication
  • Permissions

Core concepts

  • Errors
  • Pagination
  • Idempotency
  • Rate limits

Resources

  • Appointments
  • Customers
  • Services
  • Staff
  • Availability
  • Products
  • Payments
  • Webhooks

Recipes

  • Recipe: book from your own website
  • Recipe: sync the diary into a spreadsheet or BI tool
  • Recipe: a Slack message on every new booking

Reference

  • Changelog
  • OpenAPI 3.1 document

Products

Physical items sold alongside an appointment, and the module that has to be switched on first.

Last updated 1 August 2026

A product is a physical item sold alongside an appointment: shampoo at the till after a haircut. It is the only resource here that a business may not have at all.

Read-only. Products are added to an appointment through the appointment's own products field, not by writing to this resource.

MethodEndpointScopePlan
GET/api/v1/products

List products

Query: limitcursor

products:readGroei
GET/api/v1/product-categories

List product categories

Query: limitcursor

products:readGroei

The module gate

Products come from the product add-ons module, which is a feature a business switches on rather than something every tenant has. If it is off, both endpoints answer 403 FORBIDDEN for a key whose scopes are otherwise perfectly correct.

⚠️

403 FORBIDDEN on this resource is not a scope problem or a plan problem, so do not send anybody to edit a key or upgrade. It means the business has not enabled the module. Check GET /api/v1/me, whose activeModules array tells you before you make the request.

That is a different failure from the other two 403s, and the code field is what distinguishes them: INSUFFICIENT_SCOPE is fixed by editing the key, PLAN_UPGRADE_REQUIRED by changing plan, and FORBIDDEN by the owner switching a module on. See errors.

If your integration is generic rather than built for one salon, treat products as optional and degrade rather than failing: read activeModules once at startup and skip the whole feature when the module is absent.

What you get back

{
  "id": "c3ad47aa-7ddc-4cc4-8097-cf8b3f4e9d45",
  "name": "Shampoo",
  "description": "Milde dagelijkse shampoo",
  "priceCents": 1200,
  "categoryId": "6182b9e0-6686-420c-8411-b88e791bef52",
  "isActive": true,
  "position": 0,
  "createdAt": "2026-07-29T17:57:46.241Z"
}

Shorter than a service in one telling way: there is no durationMinutes and no updatedAt. A product occupies no time, which is the whole difference between the two resources, and it carries no modification timestamp, so there is no updatedSince on this endpoint and no way to sync incrementally. Re-read the list; it is small.

position is the order the business arranged the catalogue in and is what you sort by. priceCents is an integer in cents like every amount on this API.

Categories work exactly like service categories

GET /api/v1/product-categories returns the tree in one page, with the same parentId and position shape as service categories. It is a separate tree from the service one: "Verzorging" as a service category and "Verzorging" as a product category are two different rows with two different ids, and a product's categoryId never resolves against the service tree.

They are separate endpoints under separate scopes for that reason. Resolving a product's category needs products:read, not services:read.

Selling one with an appointment

Products reach an appointment through the create:

{
  "serviceId": "b50661da-7649-4c14-b748-91bbee8e9643",
  "startTime": "2026-08-20T09:00:00.000Z",
  "customer": { "email": "renee@voorbeeld.nl", "firstName": "Renee", "lastName": "de Vries" },
  "products": [{ "productId": "c3ad47aa-7ddc-4cc4-8097-cf8b3f4e9d45", "quantity": 1 }]
}

The prices are snapshotted at booking time and roll into the appointment's totalPriceCents, which is why that field can exceed the service's own priceCents. A product repriced afterwards does not change what an existing appointment charges.

Sending products on a business without the module is refused rather than ignored, so the same activeModules check applies to the create path and not only to reading the catalogue.

On this page

  • The module gate
  • What you get back
  • Categories work exactly like service categories
  • Selling one with an appointment
StippaStippa

Appointment scheduling, without the hassle.

For whom

  • For salons
  • Beauty salons
  • Physiotherapists
  • Coaches
  • Personal trainers

Features

  • Booking widget
  • Online payments
  • Reminders
  • No-show prevention
  • Online calendar
  • Client management

Product

  • Features
  • Pricing
  • FAQ
  • Contact
  • System status

Legal

  • Privacy policy
  • Terms of service
  • Data processing agreement

© 2026 Stippa. All rights reserved.

De Rechter Software · Molenwater 20, 4511 BN Breskens · KvK 98466402 · btw NL005332100B80

······