Developers

Pace is an iOS app that gives you one number: what is safe to spend this week, after your bills and savings goals are counted. The connector lets an assistant the user already talks to, such as ChatGPT, Claude, or Meta AI, read that number and log a purchase against it. This page is the whole contract: five endpoints, one key per assistant, and a short list of things a response will never contain.

Machine-readable version: https://api.pace.money/api/v1/openapi.json (OpenAPI 3.1, public, no key needed). A plain-text index of the rest of the site is at /llms.txt.

What the connector is

A Pace subscriber creates a key in the iPhone app. An assistant holding that key can read the weekly number, the bills reserved against it, and recent spending, and can log a purchase so the number moves. That is the entire surface. It is read-mostly by design: the one write creates a manual transaction, the same thing a user does by typing a purchase into the app.

Pace never holds or moves money, and neither can anything built on this API. There is no MCP server yet; the REST endpoints below are the full interface, and this page will note an MCP endpoint if one ships.

How to get a key

  1. Open Pace on iPhone and go to Account, then Connected assistants.
  2. Tap Create key and name it after the assistant it is for. The suggestions are Muse, ChatGPT, and Claude, but any name works.
  3. Copy the key. It is shown exactly once. Pace stores only a hash, so a lost key cannot be recovered; create a new one instead.
  4. Paste it into the assistant where it asks for an API key.

Each key is tied to one Pace account. An account can hold up to five active keys; a sixth is refused with 409 too_many_keys until one is revoked. Creating a key needs an active Pace Pro subscription; without one the app gets 402 subscription_required and offers the subscription instead. The same screen lists the active keys with their name, prefix, creation date, and last use, and any key can be revoked there. Revoked keys drop off the list; they are history, not settings. Revocation is immediate: the next request with that key gets a 401.

Keys start with pace_live_ and are 53 characters long. Only the first 14 characters are ever displayed after creation.

Authentication

Every request carries the key as a bearer token. The base URL is https://api.pace.money/api/v1.

Authorization: Bearer pace_live_...

There is no OAuth flow. Pace does not run an authorization server, and a key the user can see, name, and revoke is easier to review than a consent screen. All responses are JSON.

Endpoints

Four reads and one write. The examples assume the key is in an environment variable named PACE_KEY. Amounts are US dollars as decimal numbers. Dates are YYYY-MM-DD in the user's timezone; timestamps are ISO 8601 in UTC.

MethodPathReturns
GET/v1/meWho the key belongs to.
GET/v1/numberThe weekly number. This is the one that matters.
GET/v1/billsUpcoming bills.
GET/v1/spendingRecent transactions.
POST/v1/purchasesLog a purchase. The only write.

GET/v1/me

Who the key belongs to.

Returns the first name if the user entered one, the timezone the week is computed in, the subscription status, and the display prefix of the key you are holding. Nothing here identifies a bank account.

Request

curl https://api.pace.money/api/v1/me \
  -H "Authorization: Bearer $PACE_KEY"

Response

{
  "first_name": "Sam",
  "timezone": "America/Chicago",
  "currency": "USD",
  "subscription": { "status": "active" },
  "key": {
    "prefix": "pace_live_a1b2",
    "name": "Claude",
    "created_at": "2026-09-19T14:02:11Z"
  }
}

GET/v1/number

The weekly number. This is the one that matters.

left_this_week is what is safe to spend for the rest of the current week after bills and savings goals are counted, floored at zero once the week is overspent. It is the same computation the app shows on its home screen. Weeks run Monday to Sunday in the subscriber's timezone. status is one of ahead, on_pace, behind, or off_track. If the subscriber has not finished setting up a budget in the app, this endpoint answers 409 starter_budget_missing.

Request

curl https://api.pace.money/api/v1/number \
  -H "Authorization: Bearer $PACE_KEY"

Response

{
  "left_this_week": 212.40,
  "weekly_number": 350.00,
  "spent_this_week": 137.60,
  "week_start": "2026-09-14",
  "week_end": "2026-09-20",
  "status": "on_pace",
  "bills_reserved_this_month": 1840.00,
  "savings_reserved_this_month": 400.00,
  "as_of": "2026-09-19T14:02:11Z"
}

GET/v1/bills

Upcoming bills.

Recurring bills the app has forecast for the current month. The optional until=YYYY-MM-DD query narrows the window to bills due on or before that date; without it the window runs to the last day of the current month, and it cannot extend past the month. The response echoes the until actually applied. status is upcoming, overdue, or paid. An until that is not a real YYYY-MM-DD date, including an impossible one such as 2026-02-31, gets 400 invalid_until; a subscriber with no budget set up yet gets 409 starter_budget_missing.

Request

curl "https://api.pace.money/api/v1/bills?until=2026-09-30" \
  -H "Authorization: Bearer $PACE_KEY"

Response

{
  "bills": [
    { "name": "Electric", "amount": 92.15, "due_date": "2026-09-22", "status": "upcoming" },
    { "name": "Internet", "amount": 65.00, "due_date": "2026-09-25", "status": "upcoming" }
  ],
  "total_upcoming": 157.15,
  "until": "2026-09-30"
}

GET/v1/spending

Recent transactions.

The optional days query sets how far back to look, counting today: default 7, minimum 1, maximum 90. Transactions come back newest first, at most 100 of them, and the response states the from and to dates actually covered. source is bank for transactions that arrived through a linked account and manual for ones the user typed or an assistant logged. classification is need, want, or null when the user has not sorted it yet. A negative amount is a refund or credit. Bank rows carry the cleaned merchant name only; nothing about the institution or account.

Request

curl "https://api.pace.money/api/v1/spending?days=7" \
  -H "Authorization: Bearer $PACE_KEY"

Response

{
  "transactions": [
    {
      "id": "txn_01j8f3k9m2",
      "date": "2026-09-18",
      "merchant": "Trader Joe's",
      "amount": 64.20,
      "source": "bank",
      "classification": "need"
    },
    {
      "id": "txn_01j8f1q7c4",
      "date": "2026-09-17",
      "merchant": "Coffee",
      "amount": 5.75,
      "source": "manual",
      "classification": "want"
    }
  ],
  "total": 137.60,
  "from": "2026-09-13",
  "to": "2026-09-19"
}

POST/v1/purchases

Log a purchase. The only write.

Creates a manual transaction, exactly as if the user had typed it into the app, and answers 201 with the updated weekly number in the same shape as /v1/number so the assistant can say what the purchase did to the week in one round trip. amount and merchant (up to 120 characters) are required. amount is in dollars, rounded to cents, and must come to at least 0.01 after rounding. date defaults to today in the subscriber's timezone and cannot be later than that day; tomorrow is rejected with invalid_date, and so is a date that does not exist on the calendar, such as 2026-02-31. note is optional free text up to 280 characters; a longer note is rejected with invalid_note, not truncated. If the subscriber has not finished setting up a budget in the app there is no weekly number to log against, so the call answers 409 starter_budget_missing and records nothing. Every call needs an Idempotency-Key header; see the retries note below.

Request

curl -X POST https://api.pace.money/api/v1/purchases \
  -H "Authorization: Bearer $PACE_KEY" \
  -H "Idempotency-Key: 6f1c2a9e-3b7d-4e58-9c0a-2d5b8f7e1a43" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 18.50, "merchant": "Lunch", "note": "with Priya" }'

Response

{
  "transaction": {
    "id": "txn_01j8f5z2t8",
    "date": "2026-09-19",
    "merchant": "Lunch",
    "amount": 18.50,
    "source": "manual",
    "classification": null
  },
  "number": {
    "left_this_week": 193.90,
    "weekly_number": 350.00,
    "spent_this_week": 156.10,
    "week_start": "2026-09-14",
    "week_end": "2026-09-20",
    "status": "on_pace",
    "bills_reserved_this_month": 1840.00,
    "savings_reserved_this_month": 400.00,
    "as_of": "2026-09-19T14:05:40Z"
  }
}

Retries and the Idempotency-Key header

A network timeout on a write leaves you unsure whether the purchase was logged, and logging it twice would move the number twice. So every POST /v1/purchases needs an Idempotency-Key header: a value you choose, 1 to 128 characters, that identifies this one purchase. A UUID is fine. Send the same key on every retry of the same purchase. If Pace has already seen that key for this subscriber, it returns the original { transaction, number } with status 201 and logs nothing new. The replay is the exact body the first write returned, even if the subscriber has since reclassified or edited that transaction in the app; read it as a receipt, not as the current state. The Idempotency-Replayed response header is true on a replay and false on the first write. A different purchase needs a different key. A missing header gets 400 idempotency_key_required.

Limits

  • 60 requests per minute per key. Over that, requests get a 429 with a Retry-After header until the minute rolls over.
  • Pace Pro required. The subscription is sold only through the Apple App Store. A key on an account without an active subscription gets a 402 on every endpoint, including the reads.
  • United States only. United States. Bank linking is US-only. iPhone, iOS. There is no Android app and no web app.
  • Five active keys per account. Revoke one to make room.
  • 100 transactions per spending call, 90 days back at most. Narrow the days window rather than paging.

Errors

Every error is JSON with a stable error code and, where it helps, a human-readable message. The codes, by status:

400

The request did not validate. On POST /v1/purchases the code is one of idempotency_key_required, invalid_idempotency_key, invalid_amount, invalid_merchant, invalid_date, or invalid_note. On GET /v1/bills the code is invalid_until when until is not a real YYYY-MM-DD date. The message says what to fix.

{ "error": "invalid_date", "message": "date cannot be in the future (today is 2026-09-19 in the subscriber's timezone)" }
401

The key is missing, malformed, or has been revoked.

{ "error": "invalid_key" }
402

The key is valid but the account has no active Pace Pro subscription. The response carries the App Store URL so the assistant can point the user at it. Creating a key in the app fails with the same code.

{ "error": "subscription_required", "app_store_url": "https://apps.apple.com/us/app/id6754592062" }
409

The account is not in a state the request can act on. On GET /v1/number, GET /v1/bills, and POST /v1/purchases, starter_budget_missing means the subscriber has not finished setting up a budget in the app yet; on purchases nothing is recorded. When creating a key in the app, too_many_keys means five keys are already active and one has to be revoked first.

{ "error": "starter_budget_missing" }
429

More than 60 requests in one minute on this key. The Retry-After header and the retry_after_seconds field both say how many seconds to wait.

HTTP/1.1 429 Too Many Requests
Retry-After: 23

{ "error": "rate_limited", "retry_after_seconds": 23 }

Privacy

Data leaves the app only through a key the user created, can see, and can revoke. A connector response never contains:

  • Bank credentials or Plaid tokens.
  • Account numbers, routing numbers, or per-account balances.
  • The user's email address.
  • Any way to move money. There are no payment, transfer, or bill-pay endpoints.

Spending comes back as merchant, amount, date, and whether the user sorted it as a need or a want. It does not say which account it came from. The same rules that govern the app govern the API:

  • Not a bank, lender, broker-dealer, money transmitter, or investment advisor.
  • Pace never holds or moves your money.
  • Pace does not give financial, tax, legal, or investment advice.
  • Pace does not sell your financial data.
  • Pace never sees or stores your banking credentials. Plaid handles the connection.

The full privacy policy covers what Pace collects and how bank data is handled. Pace is built and published by Purple Bluebonnets Labs LLC. Questions about the API go to support@pace.money.