Stippa is an appointment system for salons and small service businesses. This API is the same booking engine the product runs on, reachable from your own code: list what a business sells, work out when it is free, create an appointment, and receive an event when something changes.
Every endpoint is scoped to exactly one business. The API key is the tenant. No request names a business, and there is no parameter that could point at another one, which is also why there is nothing to configure beyond the key itself.
Status
v1 is not generally available yet. Nothing on this page is deployed to a public host, no key has ever authenticated a production request, and the stability promise below dates from the day v1 goes GA rather than from today. Read this as the published contract we intend to honour, not as a live service level.
Everything described here is implemented and tested against a real database. What has not happened is a release. When v1 does go GA, the changelog gets its first entry and the clock on the deprecation policy starts.
Base URL
https://stippa.nl/api/v1
One host, permanently. This documentation site may move one day; the base URL will not.
The machine-readable description of the whole surface is at
/api/v1/openapi.json. It is OpenAPI 3.1, it needs no
key, and it is generated from the same definitions the routes are built from, so it cannot
describe an endpoint that does not exist. Point a client generator at it rather than writing an
HTTP layer by hand.
Postman, Insomnia and client libraries
There is no Stippa SDK and no collection file to download. Use the OpenAPI document for both.
In an API client. Postman, Insomnia, Bruno and Hoppscotch all import OpenAPI 3.1 natively:
File > Import, paste https://stippa.nl/api/v1/openapi.json. You get every endpoint with its
parameters, examples and auth header already filled in.
As a client library. Point your language's generator at the same URL:
npx @openapitools/openapi-generator-cli generate \
-i https://stippa.nl/api/v1/openapi.json \
-g typescript-fetch \
-o ./stippa
Swap -g for php, python, csharp or any other supported generator.
Your first request
curl https://stippa.nl/api/v1/me \
-H "Authorization: Bearer stp_live_..."
GET /api/v1/me reports which business the key belongs to, which scopes it holds, and which
scopes the business's plan entitles. Call it first. The difference between those last two is the
difference between a 403 you fix by editing the key and a 403 you fix by talking to the owner
about a plan, and finding that out from /me is cheaper than finding it out from a failed
create at three in the morning.
Tiers
Reading needs the Groei plan. Writing and webhooks need Pro. The full per-scope table is
on the permissions page, and every operation in the OpenAPI
document carries x-stippa-scope, x-stippa-required-feature and x-stippa-required-plan so
the ladder is machine-readable too.
A business that downgrades keeps every key exactly as it is. The scopes its plan no longer entitles simply stop resolving, and an upgrade restores the integration with nothing to reconfigure.
Versioning
The version is in the path and nowhere else: no header, no query parameter, no content
negotiation. /api/v1 is the only version that exists.
Additive, and shipped without notice
You are expected to tolerate all of these:
- a new endpoint
- a new optional field on a response
- a new optional request field or query filter
- a new value in an enum documented as extensible
- a new webhook event type
Do not validate responses against a closed schema. The response schemas in our OpenAPI
document deliberately omit additionalProperties: false for this reason. If your generated
client rejects unknown fields, turn that off before you go live. An integration that crashes on
a field we added is an integration we can never improve around.
The same applies to enums. Handle a status you have not seen by ignoring it or by routing it to a default branch, never by throwing.
Breaking, and requires v2
Removing or renaming a field, changing a field's type, making an optional request field required, tightening validation, changing a status code, removing an endpoint, or changing what an existing field means.
None of those will happen to v1. They happen to /api/v2, which does not exist and is not
planned.
What happens if v2 ever ships
Dated from the v2 GA date, not from today:
- v1 and v2 run side by side for at least twelve months. Twelve is a floor, not a fixed term.
- v1 responses gain a
Deprecationheader and aSunsetheader (RFC 8594) carrying the retirement date. - Every business with a key used in the previous ninety days is emailed at v2 GA, at six months, at one month, and at one week.
- The changelog records the migration field by field.
Language
These pages are English only. Every owner-facing screen in the product is Dutch.