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

# Push an authorisation request

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

OAuth 2.0 Pushed Authorization Request (PAR) endpoint (RFC 9126): the
`pushed_authorization_request_endpoint` in your discovery document. Revolut's backend calls
it before sending the customer's browser to your authorisation endpoint, so the enrolment
claims travel over a server-to-server channel instead of through the browser. Store the
request and return a single-use `request_uri`.

Revolut pushes one of the following variants:
- **Enrol a new member**: `prompt` is `create` and `enrolment_claims` carries the details
  the customer agreed to share. Revolut sends it after `POST /loyalty/auto-enrol` returns
  a UI-required `403` other than `account_exists`, or directly when you don't implement
  auto-enrol.
- **Link an existing account**: `prompt` is `login` and `enrolment_claims` is `{}`, so no
  personal data is shared. Revolut sends it when the customer starts "Link existing
  account" in Revolut Wallet, or after `POST /loyalty/auto-enrol` returns
  `account_exists`.

Both variants carry Proof Key for Code Exchange (PKCE, RFC 7636): store `code_challenge`
with the request and verify the `code_verifier` Revolut sends to your token endpoint.
Both also carry `program_id` when you operate several loyalty programs.

Authenticate Revolut's client credentials (client secret, private key JSON Web Token
(JWT), or mutual TLS (mTLS), as registered during onboarding) and reject any
unauthenticated request with `401` (`invalid_client`). Unless mTLS is the registered
method, Revolut sends a client secret or JWT assertion in the request body; that's why
`security` lists mTLS as optional.

The `request_uri` must expire after `expires_in` seconds (60–90) and be consumable
exactly once at your authorisation endpoint.

## Endpoint

POST `/oauth2/par`

## Parameters

### header parameters

- `Revolut-Api-Version` (string, optional)
  Contract version Revolut is calling with. Revolut sends it to your authorisation server
  too, but you may ignore it there: never reject a request because of this header.

- `Request-Id` (string, optional)
  Revolut's correlation ID for this request. You may ignore it; echoing it is optional on authorisation-server endpoints.

## Request body

### Attributes

- `client_id` (string)
    Revolut's OAuth 2.0 client ID, as registered during onboarding.
- `client_secret` (string, optional)
    Revolut's client secret. Omit it when the registered client-authentication method
    is private key JWT or mTLS.
- `client_assertion_type` (string, optional)
    Client-assertion type, used when the registered client-authentication method is
    private key JWT (RFC 7521).
- `client_assertion` (string, optional)
    The signed JWT assertion authenticating Revolut's client, used with
    `client_assertion_type` for private key JWT authentication.
- `redirect_uri` (string)
    The registered Revolut redirect URI the customer's browser returns to.
- `response_type` (enum)
    OAuth 2.0 response type. This flow always uses the authorisation-code grant.
    Possible enum values:

    - `code`
- `scope` (string)
    The scopes Revolut requests: always `openid loyalty.profile`. `openid` makes your
    token endpoint issue an ID token (OpenID Connect).
- `state` (string)
    Opaque value Revolut sends and expects back, unchanged, on the redirect. Single-use
    and short-lived.
- `nonce` (string)
    OpenID Connect nonce. Echo it in the `nonce` claim of the ID token issued at
    your token endpoint.
- `prompt` (enum)
    How to route the customer at your authorisation endpoint:
    
    | Value | Description |
    | ----- | ----------- |
    | `login` | Forced re-authentication: route the customer straight to your sign-in screen, ignoring any existing session. Revolut sends it when the customer links an existing account, and after `POST /loyalty/auto-enrol` returns `account_exists`. |
    | `create` | Route the customer straight to your registration screen. Revolut sends it after `POST /loyalty/auto-enrol` returns a `403` UI-required code other than `account_exists`, or directly when you don't implement auto-enrol. |
    Possible enum values:

    - `login`
    - `create`
- `code_challenge` (string)
    PKCE code challenge: the base64url-encoded SHA-256 hash of the `code_verifier` Revolut
    later sends to your token endpoint (RFC 7636). Store it with the request.
- `code_challenge_method` (enum)
    PKCE challenge method. Always `S256`.
    Possible enum values:

    - `S256`
- `program_id` (string, optional)
    Partner-issued identifier of the loyalty program the customer selected in Revolut
    Wallet: the program to enrol them in, or the program whose membership they want to
    link. Revolut sends it only if you operate several loyalty programs; the valid values
    are agreed during onboarding.
- `enrolment_claims` (string · application/json)
    JSON-serialised enrolment claims: a flat `EnrolmentClaims` object with the details
    the customer agreed to share. An empty JSON object (`{}`) means no personal data is
    shared: Revolut sends it in the link flow (`prompt=login`), where the customer
    identifies themselves by signing in to you.

## Returns

### 201

Authorisation request stored. Return the single-use `request_uri` and how long it
stays valid.

#### Response attributes

- `request_uri` (string)
    Single-use reference to the stored authorisation request. Consumable exactly once
    at your authorisation endpoint.
- `expires_in` (integer)
    Seconds before the `request_uri` expires.

## Error responses

| HTTP status code | Description |
| --- | --- |
| 400 | Malformed or invalid pushed request, for example a missing `code_challenge`. The body uses the standard OAuth 2.0 error format (RFC 6749, section 5.2, as applied by RFC 9126). |
| 401 | Client authentication failed (`invalid_client`): Revolut's client credentials are missing, unknown, or invalid for the registered client-authentication method. |
| 429 | Rate limit exceeded (`429`) or temporary capacity issue (`503`) on your authorisation server. Revolut retries, honouring `Retry-After`. The body format is not specified. |
| 503 | Rate limit exceeded (`429`) or temporary capacity issue (`503`) on your authorisation server. Revolut retries, honouring `Retry-After`. The body format is not specified. |
