Skip to main content
Documentation

Guide

Recipes

Three integrations end to end: booking a job from a voice agent, syncing a CRM, and a nightly export.

Any AI voice platform — Vapi, Retell, Bland, ElevenLabs — can book into a Service VIN calendar without an integration written for it. Point the platform at the booking MCP server, which is reached with a booking token, exposes availability and booking only, and is on a fixed allowlist rather than the opt-out default the rest of the registry uses.

  1. 1Add the booking server as a tool source on the voice platform, with the shop's booking token.
  2. 2The agent asks for the vehicle and the service, calls the availability capability, and reads back real slots — not a guess, and not a callback promise.
  3. 3It books the chosen slot. The job lands on the board with the call attributed to it, and the shop's own confirmation automation texts the customer.

Why the booking server inverts the default

Everywhere else a capability is published unless it opts out. The booking server is reached by an unauthenticated caller acting for a member of the public, so the honest default there is nothing: a capability reaches it only by naming it, and one added next month inherits invisibility rather than exposure.
  1. 1Backfill with the REST resource lists, paging on meta.next_cursor until it comes back null. Paging walks backwards from a fixed point, so an import landing mid-sync cannot make you skip or repeat a record.
  2. 2Subscribe to customer.created, customer.updated, lead.created and lead.status_changed rather than polling. A subscription costs you no rate limit at all.
  3. 3Verify every delivery against the raw bytes before parsing, and return a 2xx quickly — the work belongs in your queue, not in the request.
  4. 4Write back with the capability endpoints, sending a stable Idempotency-Key on anything whose page declares key.

Mint a read-only key for this and nothing else. It is refused by every capability that writes, which means the job cannot do damage even if the script is wrong — the scope gate is a property of the credential, not of your code.

Walk one resource to the end
cursor=""
while :; do
  page=$(curl -s "$SERVICEVIN_ORIGIN/api/v1/jobs?limit=100${cursor:+&cursor=$cursor}" \
    -H "Authorization: Bearer $SERVICEVIN_API_KEY")
  echo "$page" | jq -c '.data[]' >> jobs.ndjson
  cursor=$(echo "$page" | jq -r '.meta.next_cursor // empty')
  [ -z "$cursor" ] && break
done

Spread the run rather than bursting it: the read budget is the widest of the four, but a nightly job that walks ten resources at full speed is still the loudest thing on that key. If you are exporting to answer a question rather than to keep a copy, ask a capability instead — a narrow read beats a full table you then have to reduce.