Pace API

Server = intent, phone = fire. Any program — a Telegram bot, a cron job, a home-automation hook — can read a user's upcoming wakes and queue changes. Nothing here rings: every write becomes an intent the iPhone applies (or declines) on its next sync.

Get a token

Open Pace → Settings → Connect an agent. The app shows an 8-character pairing code, valid 10 minutes, single use. Exchange it once:

curl -s https://mcp-production-e0af.up.railway.app/v1/tokens/exchange \
  -H 'Content-Type: application/json' \
  -d '{"pairing_code":"K7PM-3QXZ","name":"my telegram bot","scope":"wakes:read wakes:write"}'
# → {"token":"pat_…","name":"my telegram bot","scope":"wakes:read wakes:write","expires_at":"…","token_id":"tok_…"}

The token lives 90 days, is stored only as a hash, shows up on the phone as a connected agent, and can be revoked from the phone or with DELETE /v1/tokens/me.

Endpoints

CallScopeReturns
GET /v1/wakes/nextreadthe next wake that will actually ring, or 404 no_upcoming_wake
GET /v1/wakes?days=14readevery occurrence in the window (1–60 days), skipped ones included
POST /v1/wakes/proposalswrite202 intent: a new one-time wake on a date
POST /v1/occurrences/{id}/movewrite202 intent: new time for one day
POST /v1/occurrences/{id}/skipwrite202 intent: no ring that day
POST /v1/occurrences/{id}/notewrite202 intent: reason shown when it rings
GET /v1/intents/{id}readwhat the phone did: pending → acked → applied | rejected, or expired

Occurrence ids are <alarm_id>@<YYYY-MM-DD> and stable. All times are local to the user's zone (tz). Errors are {"error":"snake_code","message":"…"}. 60 requests per minute per token; 429 carries Retry-After. Send an Idempotency-Key header on POSTs to make retries safe — a replay returns the original 202 with "deduplicated": true.

Full reference below (rendered from openapi.json).