Boltback · API docs
The matching engine, in three endpoints.
Slot ingestion, customer reads, and personalized offer push — the contract a scheduler integrator (or Boltback itself) talks to over a small REST surface. Authenticated with bearer tokens; JSON in and out.
Contents
Three endpoints, one matching loop.
Jump straight to the endpoint you’re integrating. Each entry below covers purpose, request shape, response shape, error cases, and a runnable curl.
POST /api/slot
Slot ingestion
Purpose
A scheduler POSTs a cancellation or open-slot record. Boltback ingests it and queues it for matching; on match, a personalized push is dispatched (see POST /api/offer).
Request
JSON body, Content-Type: application/json, authenticated with Authorization: Bearer <BOLTBACK_SCHEDULER_KEY>.
| Field | Type | Description |
|---|---|---|
| service | string | Service name on the open slot (e.g. "Color refresh", "Trim"). |
| startsAt | string (ISO 8601) | Slot start time in UTC. |
| durationMin | integer > 0 | Slot duration in minutes. |
| chair | string | Chair identifier (e.g. "Chair #2"). |
| customerId | string, optional | The customer who cancelled, used as a signal; the matching engine may rank a different customer higher. |
| priceCents | integer, optional | Sale price in integer cents; powers dashboard Revenue Saved. |
Response
Status 201 Created. Body shape:
| Field | Type | Description |
|---|---|---|
| id | string | Internal slot identifier; pass this as `slotId` to POST /api/offer. |
| token | string | Public single-use handle that resolves at GET /api/offer/[token]. |
| status | "received" | Indicates the slot is queued for matching. |
token is the public single-use handle that will later sit on /offer/[token].
Errors
- 400 invalid request body — body failed validation; payload includes `{ errors: { field: "msg" } }`.
- 401 missing/invalid api key — the scheduler key is absent or revoked.
- 422 startsAt is in the past — only future slots are accepted.
- 429 rate-limited — back off and retry; honor the `Retry-After` header.
Sample curl
curl -X POST https://app.example.com/api/slot \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BOLTBACK_SCHEDULER_KEY" \
-d '{
"service": "Color refresh",
"startsAt": "2026-08-23T16:30:00Z",
"durationMin": 75,
"chair": "Chair #2",
"customerId": "seed-customer-priya"
}'GET /api/customer/:id
Customer read
Purpose
Read personalization signals for a single customer — service history, learned tag, last-minute propensity. Mirrors the Customer.history JSON shape the engine uses to compose the offer copy.
Request
Path parameter :id is the customer id from the integrator system OR a Boltback seed-customer-* id. Authenticated with Authorization: Bearer <BOLTBACK_INTEGRATOR_KEY>.
Response
Status 200 OK. Body shape:
| Field | Type | Description |
|---|---|---|
| id | string | Integrator or `seed-customer-*` customer id. |
| name | string | Display name on file. |
| tag | string | Learned tag reflecting last-minute propensity (e.g. "high-fit"). |
| history.lastServices | string[] | Recent services the customer has booked, newest first. |
| history.recencyDays | number | Days since the customer's last visit. |
| history.fitNote | string | Free-text note Powers the personalization line. |
| propensity | number 0..1 | Learned last-minute booking likelihood. |
| fitScore | number 0..100, optional | Pre-computed fit score for a recent slot, if available. |
Errors
- 401 missing/invalid api key — the integrator key is absent or revoked.
- 404 customer not found — `:id` does not match an integrator or `seed-customer-*` id.
Sample curl
curl https://app.example.com/api/customer/seed-customer-priya \ -H "Authorization: Bearer $BOLTBACK_INTEGRATOR_KEY"
POST /api/offer
Offer push
Purpose
Trigger the matching engine to rank a slot against the customer pool and dispatch a one-to-one offer to the top match. Returns the public handle and URL the integrator (or Boltback’s own SMS/email channel) uses to reach the customer.
Request
JSON body, Content-Type: application/json, authenticated with Authorization: Bearer <BOLTBACK_INTEGRATOR_KEY>.
| Field | Type | Description |
|---|---|---|
| slotId | string | The slot to offer — the `id` returned by POST /api/slot. |
| channel | "email" | "sms" | "push" | Outbound channel for the personalized offer. |
| maxWaitMin | integer, optional, default 15 | How long the offer stays open before expiry. |
Response
Status 200 OK. Body shape:
| Field | Type | Description |
|---|---|---|
| offerId | string | Internal offer identifier; useful for matching against booking events. |
| token | string | Public single-use handle that resolves at GET /api/offer/[token] and the /offer/[token] page. |
| customerId | string | The ranked customer who received the outreach. |
| personalizationLine | string | Personalized copy the engine composed from `history` signals. |
| channel | "email" | "sms" | "push" | The channel the offer was dispatched on. |
| expiresAt | string (ISO 8601) | When the offer window closes. |
token is the public single-use handle that resolves at GET /api/offer/[token] and /offer/[token].
Errors
- 400 invalid request body — body failed validation.
- 401 missing/invalid api key — the integrator key is absent or revoked.
- 404 slot not found — `slotId` does not reference a received slot.
- 409 slot already offered — that slot already has a live or expired offer; reopen with a fresh slot.
- 409 already_claimed — the matched customer already booked the slot through another channel.
- 422 no eligible customer in pool — no ranked customer met the minimum fit threshold.
Sample curl
curl -X POST https://app.example.com/api/offer \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BOLTBACK_INTEGRATOR_KEY" \
-d '{
"slotId": "slot-2hx83a",
"channel": "sms",
"maxWaitMin": 15
}'