Quote FX, create payments idempotently, and track them through signed webhooks.
Quote FX, create payments idempotently, and track them through signed webhooks.
Lock an FX rate, create a payment against it, and follow it to a terminal status. Conventions, authentication and error handling are covered in the Jeeves Payment API Integration Guide.
Getting credentials: sandbox and production each need their own client credentials. Email support@tryjeeves.com to request them for either environment.
mTLS on every call: all requests — including POST /oauth/token — require your client certificate. The curl examples show the --cert/--key flags once, on the token call, and omit them elsewhere for brevity; add them to every request.
Looking for cards, boletos, transactions, or webhook subscriptions? Those live in the main API reference.
List your beneficiaries, each with the payment methods attached to it.
Use paymentMethods[].paymentMethodId as beneficiaryPaymentMethodId when creating a payment.
Pagination is page-based, matching the rest of the Jeeves Public API. Pass page and limit; count in the response is the total matching the query across all pages, so stop once page × limit reaches it. The request page and limit are not echoed back — keep track of them yourself.
The envelope is data and count, and nothing else.
Deleted beneficiaries and deleted payment methods are never returned, and there is no status field on either.
curl -i -X GET \
'https://public-sandbox.tryjeeves.com/v1/beneficiaries?limit=50&page=1&search=Acme' \
-H 'Authorization: Bearer <YOUR_TOKEN_HERE>'A page of beneficiaries.
Determines which name fields are populated: individual uses firstName and lastName; business uses name.
ISO 4217 alpha code, or one of the supported stablecoin tickers (USDB, USDC, USDT, EURC). null when the stored value is not a recognised currency code.
The beneficiary's contact details. Every key is always present and is null when the value is not set.
Every live payment method attached to this beneficiary. May be empty.
Pass as beneficiaryPaymentMethodId when creating a payment.
The rail, from a stable public set. A rail with no dedicated member is reported as local-clearing (a country-specific domestic system) or other. Treat as open.
{ "data": [ { … }, { … } ], "count": 42 }
Create a person or a business you pay. The beneficiary is created with no payment methods; read what the corridor needs with GET /v1/beneficiary-schemas, then attach a payment method with POST /v1/payment-methods.
Send firstName and lastName for an individual, or name for a business. Each name field is at most 255 characters. A required name field that is missing, or a name field that belongs to the other entityType, is a 422 (see below). Unknown fields are rejected with unknown_field, and a JSON array body is a 400.
bankCurrency must be one of the supported currencies listed on the field; any other value is a 400 with unsupported_value. A bankCountry that is well formed but not a known country is a 422 with unsupported_value.
Not idempotent. No Idempotency-Key is read; one that is sent is ignored. The duplicate check is your retry protection: a beneficiary with the same name, bank country and bank currency returns 422 with errors[].code: duplicate on the name field or fields (name for a business, firstName and lastName for an individual). That check also matches a Boleto-source vendor that GET /v1/beneficiaries does not list. Two simultaneous identical requests can both succeed, because nothing enforces uniqueness at the database.
individual takes firstName and lastName; business takes name. A name field that belongs to the other type is rejected.
curl -i -X POST \
https://public-sandbox.tryjeeves.com/v1/beneficiaries \
-H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
-H 'Content-Type: application/json' \
-d '{
"entityType": "individual",
"firstName": "Ana",
"lastName": "Gómez",
"bankCountry": "MX",
"bankCurrency": "MXN"
}'{ "beneficiaryId": "3f1c9a52-6b7e-4d80-9a13-5c2e8f0b4d76", "status": "active", "createdAt": "2026-11-02T14:02:11Z" }
Fetch one beneficiary with its contactInformation and attached payment methods.
The response is the bare beneficiary object, identical to one entry of data[] in GET /v1/beneficiaries — there is no data or count envelope. Account numbers are masked to the last four characters; an account of four characters or fewer is masked completely, and a method with no account number is null.
An unknown, deleted or malformed beneficiaryId, or one that belongs to another customer, returns the same 404 beneficiary_not_found body. It is never a 403.
curl -i -X GET \
https://public-sandbox.tryjeeves.com/v1/beneficiaries/3f1c9a52-6b7e-4d80-9a13-5c2e8f0b4d76 \
-H 'Authorization: Bearer <YOUR_TOKEN_HERE>'The beneficiary.
Determines which name fields are populated: individual uses firstName and lastName; business uses name.
ISO 4217 alpha code, or one of the supported stablecoin tickers (USDB, USDC, USDT, EURC). null when the stored value is not a recognised currency code.
The beneficiary's contact details. Every key is always present and is null when the value is not set.
Every live payment method attached to this beneficiary. May be empty.
Pass as beneficiaryPaymentMethodId when creating a payment.
The rail, from a stable public set. A rail with no dedicated member is reported as local-clearing (a country-specific domestic system) or other. Treat as open.
{ "beneficiaryId": "3f1c9a52-6b7e-4d80-9a13-5c2e8f0b4d76", "entityType": "individual", "firstName": "Ana", "lastName": "Gómez", "name": null, "bankCountry": "MX", "bankCurrency": "MXN", "contactInformation": { "streetAddress": null, "city": null, "state": null, "postcode": null, "countryCode": null, "phoneNumber": null, "emailAddress": null }, "createdAt": "2026-09-10T14:02:11Z", "paymentMethods": [ { … } ] }
Ask what a corridor needs before you attach a payment method or create a payment. For each payment method on offer the response lists the bankingInformation fields, the contactInformation fields and the purpose codes.
fields[].fieldName values are the keys of bankingInformation on POST /v1/payment-methods.contactFields[].fieldName values are the keys of contactInformation. The list is empty when the method needs none.purposeCodes[] is the exact list that payment-time validation accepts.Patterns and purposeCode are enforced again when you create the payment.
entityType is required because the form depends on it. Your company must hold the funding source you name with sourceCurrency and productAccountType; the methods and purpose codes returned are those for that funding source. Pass paymentMethod to narrow the response to one method.
Use the paymentMethod value from this response, unchanged, when you call POST /v1/payment-methods. Reading a beneficiary (GET /v1/beneficiaries) reports the payment method in a normalised vocabulary instead (ach, spei, wire and so on), so the two lists are not interchangeable.
The currency you pay from, as in POST /v1/quotes.
The kind of account you pay from.
ISO 3166-1 alpha-2, uppercase.
The currency the beneficiary receives.
Whether the beneficiary is a person or a business.
curl -i -X GET \
'https://public-sandbox.tryjeeves.com/v1/beneficiary-schemas?destinationCountry=MX&destinationCurrency=MXN&entityType=individual&paymentMethod=local_bank_transfer&productAccountType=self-funded&sourceCurrency=USD' \
-H 'Authorization: Bearer <YOUR_TOKEN_HERE>'The payment methods on offer for the corridor.
Send exactly this value as paymentMethod on POST /v1/payment-methods. It is not the normalised vocabulary used when you read a beneficiary.
The keys of bankingInformation.
The key to send in the request object this field belongs to.
Regular expression the value must match. Present when the field has one.
The values the field accepts. Present when type is enum.
The keys of contactInformation. Empty when the method needs none.
The key to send in the request object this field belongs to.
Regular expression the value must match. Present when the field has one.
The values the field accepts. Present when type is enum.
{ "paymentMethods": [ { … } ] }
Attach a payment method to a beneficiary. Use the returned paymentMethodId as beneficiaryPaymentMethodId when you create a payment.
The corridor comes from the beneficiary's stored bank country and currency, so there are no corridor parameters. paymentMethod must be a value returned by GET /v1/beneficiary-schemas; the keys of bankingInformation must equal that response's fields[].fieldName, and each value is checked against its pattern.
contactInformation is required when the method's contactFields is not empty, unless the beneficiary already has the value stored. When contactFields is empty, any contact key is rejected with unknown_field.
One payment method per rail per beneficiary. The duplicate check looks at paymentMethod only, not at the account number. To replace a method you would have to delete the old one first, and the public API has no delete.
Send paymentMethod exactly as GET /v1/beneficiary-schemas returns it. The payment method on a beneficiary you read back is reported in a normalised vocabulary, so it may not equal the value you sent.
Not idempotent. No Idempotency-Key is read, and a retry after a success returns 409 payment_method_already_exists.
Keys equal the fields[].fieldName values from GET /v1/beneficiary-schemas; each value is checked against that field's pattern.
curl -i -X POST \
https://public-sandbox.tryjeeves.com/v1/payment-methods \
-H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
-H 'Content-Type: application/json' \
-d '{
"beneficiaryId": "3f1c9a52-6b7e-4d80-9a13-5c2e8f0b4d76",
"paymentMethod": "local_bank_transfer",
"bankingInformation": {
"accountNumber": "0123456789",
"bankCode": "021000021"
}
}'{ "paymentMethodId": "b7d2e4a1-8c05-49f3-a6b2-1e7d9c3f5024", "status": "active" }