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>.

FieldTypeDescription
servicestringService name on the open slot (e.g. "Color refresh", "Trim").
startsAtstring (ISO 8601)Slot start time in UTC.
durationMininteger > 0Slot duration in minutes.
chairstringChair identifier (e.g. "Chair #2").
customerIdstring, optionalThe customer who cancelled, used as a signal; the matching engine may rank a different customer higher.
priceCentsinteger, optionalSale price in integer cents; powers dashboard Revenue Saved.

Response

Status 201 Created. Body shape:

FieldTypeDescription
idstringInternal slot identifier; pass this as `slotId` to POST /api/offer.
tokenstringPublic 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:

FieldTypeDescription
idstringIntegrator or `seed-customer-*` customer id.
namestringDisplay name on file.
tagstringLearned tag reflecting last-minute propensity (e.g. "high-fit").
history.lastServicesstring[]Recent services the customer has booked, newest first.
history.recencyDaysnumberDays since the customer's last visit.
history.fitNotestringFree-text note Powers the personalization line.
propensitynumber 0..1Learned last-minute booking likelihood.
fitScorenumber 0..100, optionalPre-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>.

FieldTypeDescription
slotIdstringThe slot to offer — the `id` returned by POST /api/slot.
channel"email" | "sms" | "push"Outbound channel for the personalized offer.
maxWaitMininteger, optional, default 15How long the offer stays open before expiry.

Response

Status 200 OK. Body shape:

FieldTypeDescription
offerIdstringInternal offer identifier; useful for matching against booking events.
tokenstringPublic single-use handle that resolves at GET /api/offer/[token] and the /offer/[token] page.
customerIdstringThe ranked customer who received the outreach.
personalizationLinestringPersonalized copy the engine composed from `history` signals.
channel"email" | "sms" | "push"The channel the offer was dispatched on.
expiresAtstring (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
  }'