Sandbox
Help

[PREVIEW] Revolut Wallet Loyalty Callbacks2026-09-17

Pre-release preview

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

Security scheme type:mutualTLS

Mutual 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.

Pre-release preview

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

Pre-release preview

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 the outcome, the points earned, and optionally the new balance (0 points with no_points_earned when the purchase earns no points).
  • 202: transaction not ready yet (settlement lag); we retry, honouring Retry-After.
  • 404: transaction or active membership definitively not found; we stop retrying.
  • 409: the Idempotency-Key was 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, honouring Retry-After.

Validate Revolut's credentials (mutual TLS (mTLS), JSON Web Signature (JWS), or OAuth 2.0) and reject any unauthenticated request with 401.

Request

Header parameters
Revolut-Api-Version
stringrequired
Idempotency-Key
string(uuid)required
Request-Id
string
Request body
member_id
stringrequired
program_id
stringrequired
transaction_context
objectrequired

Response

Loyalty card applied. Returns the outcome, the points the transaction earned, and, optionally, the customer's new balance.

Headers
Request-Id
string
Body
object
points_earned
objectrequired
outcome
stringrequired
points_balance
object
post/loyalty/apply
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
SecuritySchemaType:mutualTLS

Mutual 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.

SecuritySchemaType:apiKey
Header parameter name:Jws-Signature

Message 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 (RS256 or ES256), 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, and crit: ["b64", "iat"].
  • Replay protection. Reject any request where iat differs from your current time by more than 5 minutes, allowing for clock skew.
  • Key selection and rotation. Verify only against the registered key whose kid matches the header. Revolut may register a new key (new kid) and keep the previous key valid for an overlap window before revoking it — accept any registered, unrevoked kid.
  • Integrity scope. The signature covers the request body only. The Idempotency-Key, Request-Id, HTTP method, path, and Revolut-Api-Version headers are not integrity-protected — TLS (optionally mTLS) and the Idempotency-Key semantics cover them.

May be used on its own or together with mTLS.

SecuritySchemaType:oauth2
Flows:clientCredentials

OAuth 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"
  }
}