This is a pre-release preview of upcoming documentation. The features, workflows, and UI described here are subject to change before the final release.
Loyalty endpoints you host and Revolut calls. Implement them to this contract so loyalty cards in customers' Revolut Wallets are applied automatically when they pay with a Revolut card. Revolut is always the client; you are the server.
- Apply a loyalty card to a transaction:
POST /loyalty/apply. Called after a customer enrolled in your loyalty program pays with a Revolut card at your business, we ask you to apply their loyalty card and tell us how many points they earned.
Customers enrol in your loyalty program via Revolut Wallet. Revolut sends the partner-issued membership and program identifiers recorded during enrolment, together with the transaction context you use to match the purchase. Passes themselves are managed through the companion APIs: the Revolut-hosted Wallet Partner API and the pass endpoints you host in the Wallet Partner Callbacks API.
Revolut uses the merchant ID and acquiring institution ID you provide during onboarding to route eligible transactions. The acquiring institution ID is routing data and is not included in the callback request.
The base URL in servers is illustrative; you register your real base URL during onboarding.
Start with the Revolut Wallet guide and Get started to onboard your business.
Authentication
mutualTLSMutual TLS (mTLS). Revolut presents a client certificate signed by the Revolut Partner CA. Validate it against the Revolut CA chain from onboarding and reject any request without a valid Revolut certificate. Your Partner ID is bound to it. Can be used on its own, or layered on top of JSON Web Signature (JWS) signing for defence in depth.
A failed mTLS handshake terminates at the TLS layer and produces no HTTP response.
Return 401 only when the connection was established but the client certificate is
missing, untrusted, or not bound to your Partner ID — for example, when TLS
terminates at a proxy in front of your application.
Loyalty
Auto-apply loyalty cards to Revolut-card transactions.
This is a pre-release preview of upcoming documentation. The features, workflows, and UI described here are subject to change before the final release.
Apply a loyalty card to a transaction
This is a pre-release preview of upcoming documentation. The features, workflows, and UI described here are subject to change before the final release.
Revolut calls this after detecting an eligible Revolut-card transaction by a customer enrolled
in your loyalty program. Locate the active membership using member_id and program_id, match
the purchase from transaction_context, apply the loyalty card, and award the points earned.
Transaction matching: rrn + merchant_id is the primary key; once you have a
candidate, validate transaction_at (±24 hours) and require total.currency and the decimal
numeric value of total.amount to match exactly. The LoyaltyTransactionContext schema
documents the authoritative algorithm and collision handling.
If member_id and program_id do not identify an active membership, return 404 with
membership_not_found. If the membership is active but the purchase earns no points under
your program rules, return 200 with outcome set to no_points_earned and 0 points.
Idempotency (this operation has side effects on your side): Revolut sends one
Idempotency-Key for each logical apply operation and reuses it for every retry. If the
operation has already completed, return the original successful result without awarding
points again. Reusing the same key with a different request body returns 409. Do not store
202, 429, or 503 as the final result for a key; Revolut retries them with the same key.
Status semantics (these drive our retry behaviour):
200: loyalty card applied; return theoutcome, the points earned, and optionally the new balance (0points withno_points_earnedwhen the purchase earns no points).202: transaction not ready yet (settlement lag); we retry, honouringRetry-After.404: transaction or active membership definitively not found; we stop retrying.409: theIdempotency-Keywas reused with a different request body, or the transaction match is ambiguous (ambiguous_transaction); we stop retrying.410: transaction existed but is void (refund/cancellation); we stop.429/503: temporary capacity issue; we retry, honouringRetry-After.
Validate Revolut's credentials (mutual TLS (mTLS), JSON Web Signature (JWS), or OAuth 2.0) and reject any unauthenticated request with 401.
Request
Response
Loyalty card applied. Returns the outcome, the points the transaction earned, and,
optionally, the customer's new balance.
curl -X POST "https://passes.partner.example/revolut-wallet/loyalty/apply" \
-H "Content-Type: application/json" \
-H "Revolut-Api-Version: 2026-09-17" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-H "Request-Id: 01970c4c-5790-7fb5-8331-84dfa075bbe9" \
-d '{
"member_id": "member_987654",
"program_id": "program_gb_rewards",
"transaction_context": {
"rrn": "123456789012",
"merchant_id": "mer_example_01",
"transaction_at": "2026-09-17T12:00:00.000Z",
"total": {
"amount": "72.40",
"currency": "GBP"
}
}
}'Authorization
mutualTLSMutual TLS (mTLS). Revolut presents a client certificate signed by the Revolut Partner CA. Validate it against the Revolut CA chain from onboarding and reject any request without a valid Revolut certificate. Your Partner ID is bound to it. Can be used on its own, or layered on top of JSON Web Signature (JWS) signing for defence in depth.
A failed mTLS handshake terminates at the TLS layer and produces no HTTP response.
Return 401 only when the connection was established but the client certificate is
missing, untrusted, or not bound to your Partner ID — for example, when TLS
terminates at a proxy in front of your application.
apiKeyJws-SignatureMessage signing (JSON Web Signature, JWS). Revolut signs every request as a
detached JWS (RFC 7515, Appendix F) and sends the compact serialisation in the
Jws-Signature header.
Verify it exactly as follows:
- Signed bytes. The signature covers the exact raw HTTP request body bytes as
transmitted — nothing is re-serialised or re-encoded. The JWS uses
b64: false(RFC 7797), so to verify, take the body bytes you received, verbatim, as the JWS payload. - Protected JOSE header.
alg(RS256orES256),kid(the id of the Revolut Partner signing key whose certificate you registered during onboarding),iat(integer Unix epoch seconds, UTC — when the signature was created),b64: false, andcrit: ["b64", "iat"]. - Replay protection. Reject any request where
iatdiffers from your current time by more than 5 minutes, allowing for clock skew. - Key selection and rotation. Verify only against the registered key whose
kidmatches the header. Revolut may register a new key (newkid) and keep the previous key valid for an overlap window before revoking it — accept any registered, unrevokedkid. - Integrity scope. The signature covers the request body only. The
Idempotency-Key,Request-Id, HTTP method, path, andRevolut-Api-Versionheaders are not integrity-protected — TLS (optionally mTLS) and theIdempotency-Keysemantics cover them.
May be used on its own or together with mTLS.
oauth2clientCredentialsOAuth 2.0 client credentials. Revolut requests a short-lived access token from your
token endpoint (authenticating with its onboarding credential: client_secret,
private_key_jwt, or its mTLS certificate) and sends it as Authorization: Bearer <token>.
The token carries the loyalty.apply scope. May be used on its own or together with
mTLS.
Request body samples
{
"member_id": "member_987654",
"program_id": "program_gb_rewards",
"transaction_context": {
"rrn": "123456789012",
"merchant_id": "mer_example_01",
"transaction_at": "2026-09-17T12:00:00.000Z",
"total": {
"amount": "72.40",
"currency": "GBP"
}
}
}Response body samples
{
"outcome": "applied",
"points_earned": {
"value": "72",
"unit": "points"
},
"points_balance": {
"value": "4892",
"unit": "points"
}
}