SK Calendar · Developers

Same rails as the whole suite.

Bearer keys, prefixed ULIDs, cursor pagination, idempotency on every mutation, signed webhooks. Learn it once for SK Calendar; it holds across all of Softknack.

01

How it fits together

Availability is a read; a booking is a conditional write. The database is the referee, so two requests for one slot resolve to exactly one winner — no application-level locking to get wrong.

fig · the shape of itcaller A.110caller B.11417:00 slotA commits firstB → 17:301 winthe database refuses to let the collision exist
02

Your first appointment in three steps

Get a test key, make one authenticated call, and listen for the webhook. The same three moves work for every endpoint in the suite.

1

Get a test key

Test and live keys are separate environments. Build against sk_test_ without touching a real customer.

2

Create a appointment

One authenticated POST with an idempotency key. Same key + same body always returns the same result.

3

Receive the webhook

A signed appointment.created event hits your endpoint — verify the HMAC, act on it, return 200.

Terminal
curl -X POST https://api.softknack.com/calendar/v1/appointments \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: 9f2c-4d1a-...-e7b3" \
  -H "Content-Type: application/json" \
  -d '{
    "slot_id": "slt_01J9X...",
    "contact_id": "ctc_01J9X...",
    "service": "ac_service"
  }'
03

Webhooks you can trust

Signed with HMAC-SHA256, delivered at-least-once, retried on a fixed schedule, and replayable from a dead-letter queue. You will never miss an event because a deploy was mid-flight.

EventWhen it fires
appointment.bookedCommitted atomically — agent, page, API or staff.
appointment.rescheduledOld slot released, new slot won, parties notified.
appointment.cancelledWith reason; slot returns to inventory instantly.
slot.releasedCapacity opened — your waitlist's moment.
appointment.reminder_sentA reminder went out via SK Notifications.
appointment.no_showFlagged for follow-up.
retry schedule
1s4s16s1m5m30m2hdead-letter
04

Guarantees, not vibes

The platform conventions every SK product obeys — learn them once, rely on them everywhere.

Idempotency, 24h

Every mutation takes an Idempotency-Key. Same key + body returns the original result; a conflicting body gets 409.

Prefixed ULIDs

Sortable, debuggable IDs like apt_01J9X... — you can read the type and the time right off the wire.

Cursor pagination

Stable cursors that never skip or repeat a row when data changes mid-list. No page-offset drift.

Row-level tenancy

Isolation enforced in the database. 404-over-403, so the existence of another tenant's record never leaks.

Signed webhooks

HMAC-SHA256 on every delivery, with the full retry schedule and dead-letter replay above.

Spec drift-checked

The OpenAPI spec is generated from the code's validators and checked in CI — the docs can't lie.

05

Bring your own agent

Embed booking in your own app: read availability, commit a slot with a conditional write, and let reminders ride SK Notifications. The booking page uses this exact contract — and SK Voice books mid-call through it, race-free, while the caller is still on the line.

fig · MCP, scopedcatalogheadlessAPI · webhook · MCPservedyour agentsbuild on your catalog instead of being held by it
06

Just want a booking link?

Spin up a hosted, branded booking page in seconds — it writes through the identical atomic slot engine, so self-serve bookings can never collide with phone or staff bookings.

The docs go deeper.

Auth, errors, pagination, every endpoint and schema — written once for the platform, shared by every product.

docs.softknack.com/calendar  See pricing →