Developers
Your data is yours. Read and change it through the GraphQL API, and get a signed webhook when something happens.
API tokens
Create a token in Control panel under Data & integrations and choose what it may read or change. Send it as a bearer token to your business's /graphql endpoint. The full schema is at /graphql/schema.
curl https://your-business.appointier.com/graphql \
-H "Authorization: Bearer $APPOINTIER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ customers(first: 5) { edges { node { firstName lastName email } } } }"}'Scopes
A token carries the scopes you pick. Reports and settings are read-only; every other area has a read and a write scope. The role of the person who created the token still bounds what it can reach.
- read
- write
- customers.read
- customers.write
- appointments.read
- appointments.write
- catalog.read
- catalog.write
- packages.read
- packages.write
- sales.read
- sales.write
- invoices.read
- invoices.write
- reports.read
- settings.read
Webhooks
Every delivery carries an Appointier-Signature header with a timestamp and an HMAC-SHA256 of the timestamp and the raw body, keyed with your endpoint secret. Reject anything older than five minutes.
import crypto from "node:crypto";
export function verify(body, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
const age = Math.abs(Date.now() / 1000 - Number(parts.t));
if (age > toleranceSeconds) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${body}`)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Events
- appointment.created
- appointment.updated
- appointment.canceled
- appointment.completed
- appointment.no_show
- customer.created
- customer.updated
- sale.completed
- sale.voided
- package.sold
- package.redeemed
- package.reversed
- invoice.paid
A failed delivery is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours. After 10 consecutive failures the endpoint is paused and the owner gets an email. Any delivery can be replayed from the log.
Full export
Owners can request a ZIP with every table as CSV and JSON Lines, plus photos, signed forms, note PDFs and a manifest with row counts. The link arrives by email and works for 24 hours.
- customers
- appointments
- catalog
- staff
- locations
- packages
- memberships
- gift_cards
- forms
- notes
- products
- sales
- invoices
- payments
- notifications
- audits
The same ZIP can be delivered every day or every week to an Amazon S3 bucket, an S3-compatible store or an SFTP host.
Rate limits
Each token can make 600 requests a minute, and every response carries X-RateLimit-Limit and X-RateLimit-Remaining.