---
api: '[PREVIEW] Revolut Wallet Loyalty Callbacks'
---

# Retrieve a loyalty profile

:::warning [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's backend calls this once per enrolment or link, immediately after exchanging the
authorisation code at your token endpoint, to fetch the membership the customer just
enrolled in or linked. Return the membership identifiers, its current loyalty state, and
the complete pass envelope for the customer's Revolut Wallet. The `member_id` you return
must equal the `member_id` claim of the ID token you issued for the same code.

After this call, keep the pass current through
[pass updates](https://developer.revolut.com/docs/guides/revolut-wallet/operations/update-pass): push changes through
the Wallet Partner API, or serve Revolut's poll requests.

Validate the access token your authorisation server issued and require the
`loyalty.profile` scope. Revolut uses the token only for this endpoint, including any
retries after `429` or `503`, so issue a short-lived access token whose lifetime still
covers the `Retry-After` delays you return. Signal token errors in the `WWW-Authenticate`
header (RFC 6750): reject a request without a token with `401` and a bare `Bearer`
challenge, an expired or invalid token with `401` (`invalid_token`), and a token without
`loyalty.profile` with `403` (`insufficient_scope`).

When the customer unlinks the membership in Revolut Wallet, Revolut doesn't notify you; it
stops calling your loyalty endpoints for that membership.

## Endpoint

GET `/loyalty/profile`

## Parameters

### header parameters

- `Revolut-Api-Version` (enum, required)
  Contract version Revolut is calling with. Currently `2026-09-17`.
  
  :::note
  If you receive a version you do not implement, respond with `400`.
  :::
  Possible enum values:

  - `2026-09-17`

- `Request-Id` (string, optional)
  Revolut's correlation ID for this request. Echo it back in your response.

## Returns

### 200

The membership's profile: its identifiers, current loyalty state, and the complete
pass envelope.

#### Response attributes

- `member_id` (string)
    Partner-issued identifier of the enrolled or linked membership.
- `program_id` (string)
    Partner-issued identifier of the loyalty program.
- `tier` (string, optional)
    Membership tier label.
- `points_balance` (object, optional)
    Current points balance. Include it if you track balances.
  - `points_balance.value` (string)
      Current points balance as a non-negative decimal string with up to six fractional digits.
      Do not use a sign, exponent notation, or redundant leading zeros. Compare values as decimals,
      so `"1500"` and `"1500.00"` are equivalent.
  - `points_balance.unit` (string)
      Unit label for the balance (e.g. points, miles).
  - `points_balance.monetary_value` (object, optional)
      Optional monetary equivalent of the points balance.
    - `points_balance.monetary_value.amount` (string)
        Non-negative decimal amount as a string (e.g. "72.40").
    - `points_balance.monetary_value.currency` (string)
        ISO 4217 currency code (e.g. GBP, EUR, USD).
- `pass` (oneOf)
    The complete loyalty pass envelope, in any format accepted by `POST /passes` on the
    [Wallet Partner API](https://developer.revolut.com/docs/api/revolut-wallet-partner). Its `partner_reference` is
    your stable key for the pass when you push updates later. To apply one of your
    [templates](https://developer.revolut.com/docs/guides/revolut-wallet/operations/template-management), set
    `template_id` in the envelope; without it, the pass uses only the styling it carries.

## Error responses

| HTTP status code | Description |
| --- | --- |
| 400 | Malformed request or invalid body. |
| 401 | No access token, or an expired or invalid one. For a request without a token, send a bare `Bearer` challenge with no error code (RFC 6750, section 3.1). For an expired or invalid token (not issued for this enrolment or link, expired, or failing validation), send `invalid_token`. Signal the error in `WWW-Authenticate`; the JSON body is optional. |
| 403 | The access token lacks the `loyalty.profile` scope (`insufficient_scope`). Signal the error in `WWW-Authenticate` (RFC 6750); the JSON body is optional. |
| 404 | No active membership found for this access token. Revolut stops retrying. |
| 429 | Rate limit exceeded. Revolut retries, honouring `Retry-After`. |
| 503 | Temporary capacity issue. Revolut retries, honouring `Retry-After`. |
