Payments
Move money from your Jeeves account to anyone you pay — lock an FX rate, create the payment idempotently, and track it to a terminal status through signed webhooks.
The Jeeves Payment API moves money from your Jeeves account to beneficiaries in 190+ countries, over local rails (SPEI, PIX, SEPA, ACH, Faster Payments, …) and international wire. The same flow handles domestic payments — paying a Mexican business in MXN from your MXN account (e.g. Bill Pay credit) via SPEI works exactly like a cross-border payout. It is built around one disciplined flow: quote, then pay, then track. A quote locks the exchange rate for a destination amount; a payment consumes that quote exactly once, protected by a mandatory idempotency key; signed webhooks push every status change, and GET /v1/payments/{paymentId} is always the source of truth.
Try it interactively in Build your payment flow, or read on for the model.
The payment flow
1. FUND Your funding account holds the source currency
(self-funded balance, credit line, or crypto wallet)
│
2. QUOTE POST /v1/quotes — lock the FX rate for a
destination amount; read expiresAt
│
3. PAY POST /v1/payments — consume the quote, with a
mandatory Idempotency-Key
│
4. TRACK Webhook on every status change;
GET /v1/payments/{id} as the source of truthWhat you can do
| Capability | How | Where to read |
|---|---|---|
| See what can fund a payment | GET /v1/product-accounts | Funding accounts |
| See who you can pay — in 190+ countries | GET /v1/beneficiaries with attached payment methods | Beneficiaries · Coverage |
| Create beneficiaries and attach payment methods | POST /v1/beneficiaries, GET /v1/beneficiary-schemas, POST /v1/payment-methods | Beneficiaries |
| Lock an FX rate | POST /v1/quotes — destination-amount based, single-use | Quotes & FX |
| Pay without duplicates | POST /v1/payments with Idempotency-Key | Send a payment |
| Pay on a future date | scheduledDate — rate locks on execution day | Scheduled payments |
| Cancel a held payment | POST /v1/payments/{id}/cancel while in-review or scheduled | Scheduled payments |
| Follow every status change | payment.status.updated webhooks + GET /v1/payments/{id} | Tracking & webhooks |
Payment lifecycle
accepted ──► in-review ──► in-progress ──► completed ──► refunded
│ │ │
▼ ▼ ▼
rejected canceled failed
scheduled ──► in-progress ──► … (future-dated payments)
│
▼
canceledTerminal states are completed, rejected, failed, canceled, and refunded. A payment never re-enters an earlier state, and the status enum is open — tolerate values you don't recognize. Full table: Tracking & webhooks.
Authentication
Every call carries a short-lived OAuth 2.0 bearer token (from POST /oauth/token with Basic client credentials) plus your client certificate (mTLS) — the certificate is required on the token call too. Curl examples in these guides show the --cert/--key flags on the token step and omit them elsewhere for brevity; every request needs them. Request only the scopes you need: quotes:write, payments:write, payments:read, beneficiaries:read, beneficiaries:write, accounts:read. payments:write covers creating and cancelling payments; beneficiaries:write covers creating beneficiaries and attaching payment methods. The response follows RFC 6749 (access_token, token_type, expires_in, scope), so a standard OAuth client reads it unchanged. Read expires_in rather than hardcoding a lifetime, and check the returned scope — it reports what was granted, not what you asked for. There is no refresh token.
Environments
| Environment | Base URL |
|---|---|
| Sandbox | https://public-sandbox.tryjeeves.com |
| Production | https://public-api.jeev.es |
All examples in this section use sandbox. Rate limits apply per credential (300 requests/minute) and every response carries X-RateLimit-* headers — see Errors & rate limits.