Sandbox
Help

Update a pass

Keep passes current after creation using push updates or poll-based refreshes.

When details change after creating a pass - a gate change, a seat update, loyalty points earned - customers need the updated pass in their wallet without re-adding it.

Two channels keep passes in sync: push the full updated pass via the Partner API, or let Revolut poll your endpoint for the latest state. You can use either channel on its own, or combine them - poll for routine refreshes and push for time-sensitive changes. Bump version on every change regardless of which method you use.

Push vs. poll

Most integrations start with push - you call Revolut's API from your backend, so there's no server endpoint to host, and updates reach wallets in near real-time. Poll becomes useful when Revolut needs to refresh passes independently (for example, after an app relaunch or a sync cycle), or when you don't want to push on every minor change - but it requires you to host a GET endpoint that Revolut can call. You can combine both approaches: poll for routine refreshes and push for urgent changes.

PushPoll
DirectionYou call RevolutRevolut calls you
LatencyNear real-timeScheduled (minutes)
You implementPUT calls with Idempotency-Key and version bumpA GET endpoint with ETag and 304 support
Best forTime-sensitive updates (gate change, seat change)Steady-state or infrequent updates

How it works

Like pass creation, this is a server-to-server integration - the customer never interacts with the API directly. Your backend and Revolut's servers exchange the full pass body; Revolut renders the updated pass in the customer's wallet.

Pass updates use two channels: push and poll. The only difference is the direction of the calls - during push, your backend calls the Revolut-hosted Partner API to replace the stored pass. During polling, Revolut calls your Wallet Partner Callbacks endpoint to fetch the latest state. Both channels send the same full pass body - there is no partial update.

The following components interact in this flow:

ComponentRole in updates
Partner API PUT /passes/{id}Push channel - your backend calls Revolut with the full updated pass
Wallet Partner Callbacks GET /passes/{partner_reference}Poll channel - Revolut calls your endpoint to fetch the latest pass
versionMonotonically increasing version - bump on every change, so Revolut can detect stale updates
ETag / If-None-MatchConditional request headers for poll - save bandwidth when the pass is unchanged
ref: prefixAddressing scheme for auto-provisioned passes where Revolut never returned a pass id

Both channels use the same pass body: the full semantic content for the pass type, without template_id (which is immutable) - partial update is not supported. Revolut replaces the stored pass and fans it out to every holder. Because a pass can be held by multiple customers (e.g. a loyalty card shared across a team), Revolut pushes every update to every wallet that holds it - you only send the update once.

Bump version whenever the pass content actually changes (new gate, updated seat, points balance updated). Sending the same body with the same version is a no-op; sending a different body with a stale version returns 409.

Update flow

A pass detail changes in your system (gate change, seat update, points balance updated). The two channels handle this independently:

  1. Your backend calls PUT /passes/{id} with the full updated pass body and a bumped version.
  2. Revolut validates the update, replaces the stored pass, and fans it out to every wallet that holds it.
  3. Revolut renders the updated pass in the customer's wallet.

Before you begin

  • Complete Get started to get your Partner ID, API credentials, and template_id
  • Have at least one pass created via Create a pass

Implement pass updates

This section covers the request/response details for each channel, including the response codes your poll endpoint must implement. For the full error reference, see the Partner API and Wallet Partner Callbacks.

1. Push updates via the Partner API

To push updates, your backend calls the Revolut-hosted Partner API. Send a request to PUT /passes/{id} with the complete, updated pass. This request executes a full replacement - send every field, including ones that haven't changed. Omit template_id; it was set at creation and is immutable.

Example request
PUT https://partner.wallet.revolut.com/passes/{id}
Revolut-Api-Version: 2026-07-01
Idempotency-Key: {uuid}
Content-Type: application/json

{
  "partner_reference": "skyjet-2241-R7K92M",
  "type": "boarding_pass",
  "version": 2,
  "semantics": {
    "passenger": { "full_name": "Sarah Connor" },
    "flight": {
      "flight_number": "2241",
      "carrier_code": "SJ",
      "departure_airport": { "iata": "LTN" },
      "arrival_airport": { "iata": "OTP" },
      "scheduled_departure_at": "2026-08-02T06:15:00.000Z",
      "scheduled_arrival_at": "2026-08-02T09:40:00.000Z"
    },
    "boarding": { "gate": "C14", "seat": "14C" },
    "booking": { "pnr": "R7K92M" }
  }
}

Path parameter:

ParameterDescription
idThe pass to update. Accepts the Revolut pass ID (UUID) or your partner_reference prefixed with ref:.

Header parameters:

ParameterDescription
Revolut-Api-VersionAPI version of the request, e.g. 2026-07-01.
Idempotency-KeyUUID for safe retries. See Idempotency below.

You can also address the pass by ref: + your partner_reference (e.g. PUT /passes/ref:skyjet-2241-R7K92M). Use this form when you don't have the Revolut-assigned id - for example, auto-provisioned passes where Revolut never returned an id.

Body parameters:

ParameterDescriptionRequired
partner_referenceYour own key for the pass - used to match it in your systemYes
typePass type discriminator - boarding_pass, event_pass, or loyalty_passYes
versionMonotonically increasing version - bump on every change so Revolut can detect stale updatesYes
semanticsFull pass content for the type. This is a full replacement - include everythingYes
relevant_atWhen the pass becomes time-relevant (departure time, event start) - drives Revolut's polling cadenceNo
actionsButtons rendered on the pass (e.g. "Open website", "Get directions")No
triggersContext-aware notifications (e.g. proximity alert, time before event) that nudge the customerNo

template_id is not accepted on updates - it's immutable and set at creation.

Set relevant_at to the event time (departure, event start) so Revolut polls more frequently around the event and less aggressively afterwards.

Idempotency

Send an Idempotency-Key header (UUID) with every push update. Retrying with the same key and the same body is safe - Revolut returns the original 204 without applying the update twice. Reusing the same key with a different body returns 409.

Revolut uses optimistic concurrency: if the version you send doesn't match the stored version +1, the update is rejected with 409. This prevents a slower update from overwriting a newer one.

If you get 409, re-fetch the pass, apply your changes to the current state, bump version, and retry.

If you also want Revolut to pull updates on its schedule - for example, after an app relaunch or sync cycle - implement the poll endpoint.

2. Serve poll requests from your backend

To serve poll requests, you need to host an HTTPS endpoint on your server that accepts GET /passes/{partner_reference} requests from Revolut. Register your callback base URL with the Revolut Wallet team during onboarding. Revolut will call it on a schedule and on demand to fetch the latest state of a pass.

Your endpoint must:

  • Accept GET requests at /passes/{partner_reference}

  • Return the full pass body (without template_id) when the pass has changed

  • Respond with 304 Not Modified when the pass hasn't changed since the supplied ETag

  • Validate Revolut's authentication (see Wallet Partner Callbacks authentication)

  • Support the response codes listed

  • ![Request]

    Revolut request
    GET /passes/{partner_reference}
    Host: https://passes.partner.example/revolut-wallet
    Revolut-Api-Version: 2026-07-01
    Request-Id: 01970c4c-5790-7fb5-8331-84dfa075bbe9
    If-None-Match: "v3"

    Path parameters:

    ParameterDescription
    partner_referenceThe partner reference of the pass Revolut tries to poll.

    Header parameters:

    ParameterDescription
    Revolut-Api-VersionAPI version of the request.
    Request-IdUnique identifier Revolut assigns to this poll attempt. Use it for tracing and idempotency on your side.
    If-None-MatchThe ETag Revolut received from your last 200 response. If the pass hasn't changed since, respond 304 Not Modified.
  • ![Response]

    Example response - updated
    HTTP/1.1 200 OK
    Content-Type: application/json
    ETag: "v4"
    
    {
      "partner_reference": "skyjet-2241-R7K92M",
      "type": "boarding_pass",
      "version": 4,
      "semantics": {
        "passenger": { "full_name": "Sarah Connor" },
        "flight": {
          "flight_number": "2241",
          "carrier_code": "SJ",
          "departure_airport": { "iata": "LTN" },
          "arrival_airport": { "iata": "OTP" },
          "scheduled_departure_at": "2026-08-02T06:15:00.000Z",
          "scheduled_arrival_at": "2026-08-02T09:40:00.000Z"
        },
        "boarding": { "gate": "C14", "seat": "14C" },
        "booking": { "pnr": "R7K92M" }
      }
    }

    Header parameters:

    ParameterDescription
    ETag (header)Entity tag for this version of the pass. Return a fresh value with every 200 - Revolut sends it back as If-None-Match on the next poll, which lets you respond 304 when nothing has changed.

    Body parameters:

    ParameterDescription
    partner_referenceYour reference for the pass.
    typePass type discriminator.
    versionCurrent pass version.
    semanticsFull pass content for the type.

    Handle unchanged passes

    Revolut sends If-None-Match with the ETag from your previous 200 response. If the pass is unchanged, respond 304 Not Modified (no body) to save bandwidth and processing.

    Example response - unchanged
    304 Not Modified
    ETag: "v3"

Response codes and actions

CodeDescriptionAction
200Pass returned with a fresh ETag. Revolut updates the pass in the customer's wallet.Include the full pass body and a fresh ETag header.
304Pass unchanged since the supplied ETag. Revolut keeps the existing pass.Return no body. No processing needed on your side.
404Pass not found. Revolut stops polling this pass.Return this when the pass was never created or has been deleted. Revolut won't retry.
410Pass permanently gone. Revolut stops polling this pass.Return this when the pass was voided or refunded (e.g. cancelled booking). Use instead of 404 when the pass existed but is no longer valid.
429 / 503Temporary capacity issue. Revolut retries after Retry-After.Include a Retry-After header with the seconds to wait. Revolut will retry after the delay.

Implementation checklist

Work through these checks in order - implement, test in sandbox, then validate on production before going live.

  • Complete onboarding and create at least one pass
  • Push: implement PUT /passes/{id} calls with version bumping
  • Push: decide whether to address by Revolut id or ref:partner_reference
  • Poll: implement a GET /passes/{partner_reference} endpoint on your server
  • Poll: support ETag / If-None-Match / 304 Not Modified
  • Poll: return correct status codes (200, 304, 404, 410, 429/503)
  • Test optimistic concurrency by sending a stale version (expect 409)

Sandbox testing:

  • Push an update with a bumped version and confirm the pass changes in the sandbox wallet
  • Push the same body with the same version and confirm it's a no-op
  • Push a different body with a stale version and confirm you get 409
  • Have Revolut poll your endpoint and confirm you return 200 with a fresh ETag when the pass changed
  • Have Revolut poll with If-None-Match matching your ETag and confirm you return 304
  • Verify ref: addressing works for a pass where you don't have the Revolut id

Production validation before go-live:

  • Push a live update and confirm it reaches real Revolut Wallets
  • Confirm Revolut can poll your production endpoint and receives the correct pass state
  • Validate that ETag / 304 flow works end-to-end in production

What's next

Auto-provision transaction results
Let Revolut pull passes from you after eligible card transactions.
Partner API
Endpoints Revolut hosts: push update
Wallet Partner Callbacks
Endpoints you host: poll update, transaction results
Rate this page