Developers · API and webhooks
Your data is not locked in a box. API, webhooks, calendars.
Workout OS and Workout Studio follow the same conventions: a key-authenticated REST API for reading and writing, signed webhooks, an event feed and ICS calendar feeds. Full access on every paid plan, read-only on the free plan. We do not keep the API for enterprise tiers.
REST API
Members or clients, memberships or packs, payments, classes and bookings, attendance. Cursor pagination, updated_since for incremental sync, amounts in minor units.
Signed webhooks
Per-event subscriptions, HMAC SHA-256 signatures, 7 delivery attempts, a dead-letter box and one-click resend.
Calendars (ICS)
Secret calendar URLs for trainers and members: classes and appointments appear in Google, Apple or Outlook calendars.
OpenAPI 3.1
A machine-readable spec served by the API itself without a key, generated from the same schemas the API validates with.
What each plan includes
The only difference between plans is the rate limit. Write scopes and webhooks are on every paid plan.
Moving back to the free plan deletes nothing: write keys keep reading, writes return 403 plan_read_only and webhooks pause.
Scopes
Create a key in Settings → Integrations. It is shown once and only a SHA-256 hash is stored. Send it as Authorization: Bearer; a key only ever sees its own business.
Workout OS (wosk_…)
read:members- Members, door access feed, member.* and success.* events
read:contact- Adds phone and email to members (never for privacy-restricted members)
read:memberships- Memberships and membership.* events
read:payments- Payments and membership amounts
read:classes- Class types, sessions, bookings and booking.* events
read:attendance- Check-ins and attendance.recorded events
write:members- Create and update members
write:payments- Record manual payments: cash, card (POS), transfer
write:bookings- Book and cancel classes
write:events- Door system entry events
Workout Studio (wstk_…)
read:clients- Clients (without contact details)
read:contact- Phone and email; look up clients by phone or email
read:packages- Packs and pack types
read:bookings- Services, trainers, sessions, bookings, workshops
read:payments- Payments; pack and ticket amounts
write:clients- Create and update clients
write:bookings- Create and cancel bookings
write:payments- Record manual payments: cash, card (POS), transfer
Health data (forms, answers, measurements), staff notes, birth dates and photos are never returned by the API.
Events
Every event is written in the same database transaction as the change (outbox), so a saved change never loses its event. Instead of webhooks you can poll the event feed (kept 30 days, on every plan).
Workout OS
member.createdmember.updatedmembership.createdmembership.renewedmembership.frozenmembership.expiredmembership.cancelledpayment.recordedbooking.createdbooking.cancelledattendance.recordedaccess.status_changedsuccess.case_opened
Workout Studio
client.createdclient.updatedpackage.soldpackage.renewedpackage.expiredbooking.createdbooking.cancelledbooking.attendedbooking.no_showpayment.recordedevent_ticket.createdevent_ticket.cancelledsuccess.case_opened
{
"id": "0b6f0a52-6a1e-4a8e-9f1e-3c4f0d3a2b11",
"type": "payment.recorded",
"created_at": "2026-10-23T14:02:00.000Z",
"tenant_id": "730c3ef8-…",
"api_version": "2026-10-23",
"data": { "payment": { "id": "…", "amountKurus": 50000, "currency": "TRY", "method": "cash" } }
}X-WorkoutOS-Event: payment.recorded
X-WorkoutOS-Delivery: <delivery uuid>
Idempotency-Key: <event id>
X-WorkoutOS-Signature: t=1761228120,v1=<hex>Verifying the signature
v1 = HMAC_SHA256(secret, "<t>.<raw body>") as lowercase hex. Verify on the raw body bytes with a constant-time comparison, and reject timestamps older than 5 minutes.
- The signing secret (whsec_…) is shown once and can be rotated at any time; during a rotation the header can carry more than one v1
- Idempotency-Key = the event id: identical for every endpoint and every retry, so de-duplicate on it
- Deliveries can arrive more than once and out of order: order by created_at
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, rawBody, header, toleranceSec = 300) {
const t = /(?:^|,)t=(\d+)/.exec(header ?? "")?.[1];
const sigs = [...(header ?? "").matchAll(/v1=([0-9a-f]{64})/g)].map((m) => Buffer.from(m[1], "hex"));
if (!t || sigs.length === 0 || Math.abs(Date.now() / 1000 - Number(t)) > toleranceSec) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
return sigs.some((s) => s.length === expected.length && timingSafeEqual(s, expected));
}Delivery guarantees
- No 2xx within 10 seconds? We retry after 1 min, 5 min, 30 min, 2 h, 6 h and 24 h (7 attempts)
- Then the delivery goes to the dead-letter box; resend one delivery or all failed ones in one click
- If an endpoint keeps failing for 1 hour the owner is alerted; after 3 days of continuous failure it is turned off automatically
- An integration health screen shows 24 h / 7 d success rates, pending and failed counts and the last error code
Idempotency-Key on writes
Every write needs an Idempotency-Key header (1–255 visible characters, for example your own order id). Keys are kept for 24 hours per business.
- Same key + same request: the first response is returned again with Idempotent-Replayed: true
- Same key + different body: 422 idempotency_key_reused
- Two concurrent requests with the same key: the second waits for the first, one record is written
- A failed request does not consume the key: fix it and retry with the same key
Rate limits
Every response carries the IETF RateLimit headers; over the limit you get 429 rate_limited with Retry-After.
RateLimit-Limit: 600
RateLimit-Remaining: 597
RateLimit-Reset: 41
RateLimit-Policy: 600;w=60Calendar feeds (ICS)
Trainers add their own classes and sessions, members and clients their own bookings, to any calendar app. On every plan.
- RFC 5545, times in UTC, the business time zone in X-WR-TIMEZONE
- Cancelled bookings as STATUS:CANCELLED, waitlist as TENTATIVE
- The last 30 days to the next 180 days
- The URL is secret; resetting it invalidates the old one at once
Door and turnstile systems (gyms)
We sell no hardware; a gym's existing door system connects at software level. Access status comes from the same rule as a manual check-in at the front desk.
- Access list: allowed, expired, frozen, debt, blocked
- Incremental changes and the access.status_changed webhook
- Write entry events from the door: they feed visit history, automations and reports
- An allowed-members CSV for manual upload
Documentation
The OpenAPI 3.1 spec is served without a key at /v1/external/openapi.json on your business's API address, shown in Settings → Integrations. Public developer documentation is being prepared; until then, write to us for example requests and setup help.
- Generate a client with Postman, Insomnia or openapi-generator
- Zapier and Make: connect through webhooks
- Error shape: { statusCode, code, message, fields? }, message in the business's language
FAQ
Which plans include the API?
Every paid plan has full access (read, write and webhooks). The free plan is read-only: you can read data and poll the event feed. The only other difference between plans is the rate limit.
Does the API cost extra?
No. The API, webhooks and calendar feeds are included in the plan price.
Can I connect my door or turnstile system?
Yes, at software level. Your door system reads the access list and changes through the API or webhooks and reports entries back. We do not sell or install hardware.
Does health data leave through the API?
No. Health forms, measurements, staff notes, birth dates and photos are never returned. Contact details need a separate scope.
What if a webhook cannot be delivered?
It is retried 7 times, then moves to the dead-letter box and can be resent from the panel. Events also stay in the event feed for 30 days.
Does it connect to my accounting software?
Not directly. Reports → Accounting exports a journal, a transaction list, or Xero and QuickBooks bank CSV files. It is not an e-invoicing integration.
Demo
See it with your own data.
Gym, studio or both? We will set up a 20-minute walkthrough using your own packs and client list. No commitment.