Push payments to Revolut Terminal

This guide explains how 3rd-party Point of Sale (POS) software providers can integrate with the Revolut Terminal to push payment intents from their server-side POS applications to physical Revolut Terminal devices.

This integration is designed for developers and integrators building Point of Sale (POS) software who want to enable their merchants to accept payments using Revolut Terminal devices.

How it works

Push payments to Revolut Terminal is a server-to-server integration that allows your POS software to send payment requests directly to Revolut Terminal devices. This integration requires internet connectivity on both the POS system and the Revolut Terminal (there is no Bluetooth or physical cable communication).

From an implementation perspective, the integration works with the following components:

  1. Server-side: Your POS server communicates with the Revolut Merchant API to create orders, find available terminals, and push payment intents.
  2. Revolut Terminal: The physical terminal (connected to the internet and in Pay at Counter mode) polls for payment intents assigned to its location and processes customer payments.
  3. Polling mechanism: Your POS server polls the Merchant API to track the payment status in real-time.

Orders, payment intents, and payments

Before diving into the payment flow, it's important to understand how these three concepts relate to each other:

  • Order: The foundation of any transaction. An order represents what the merchant wants to receive payment for (e.g., items purchased, total amount). Orders can have multiple payment attempts associated with them.

  • Payment intent: The link between an order and the terminal. When you create a payment intent, you're signalling your intention to complete payment for a specific order on a specific terminal. The payment intent allows the terminal to recognise and display the payment request.

  • Payment: The actual payment attempt and its result. Once a customer interacts with the terminal (e.g., inserts their card), a payment is created and processed. Each payment intent can result in one payment.

info

A payment intent reaching completed status means the checkout process finished on the terminal—but it does not guarantee the payment succeeded. You must check the actual payment status, which can be captured or completed (successful), declined (card rejected), failed (technical error), or cancelled.

Payment flow

  1. The Revolut Terminal is set to Pay at Counter mode and listens for payment intents assigned to its location.
  2. A customer is ready to pay at your point of sale.
  3. Your POS server creates an order via the Merchant API: Create an order endpoint.
  4. Your POS retrieves available terminals at the same location via the Terminals API.
  5. Your POS creates a payment intent (payment request), specifying the target terminal.
  6. The Revolut Terminal polls for and fetches the payment intent assigned to it.
  7. The Revolut Terminal displays the payment request, and the customer completes the payment.
  8. Your POS polls the payment intent status until it reaches completed.
  9. Your POS polls the payment status until it reaches a final state (captured, completed, declined, failed, or cancelled).
  10. The terminal displays the result to the customer, and your POS displays the result to the merchant staff.
info

For more information about the order and payment lifecycle in the Merchant API, see: Order and payment lifecycle.

Implementation overview

Check the following high-level overview on how to implement push payments to Revolut Terminal:

  1. Create or use an existing location
  2. Create an order
  3. Find available terminals
  4. Push payment intent to terminal
  5. Track payment intent status
  6. Track payment status
  7. Display results on POS

Your role as API orchestrator

As a POS software provider integrating with Revolut Terminal, you act as an API orchestrator - making API calls to Revolut's Merchant API on behalf of your merchants. This means merchants will provide their Revolut Merchant API keys to your POS system, and your system will use these keys to create orders, push payment intents, and track payment statuses.

This is a critical security responsibility that requires proper handling of merchant API keys.

CRITICAL SECURITY REQUIREMENT

Never expose merchant API keys in:

  • Frontend/client-side code (JavaScript, mobile apps)
  • Browser network requests visible in developer tools
  • Application logs or error messages
  • Source code repositories (use environment variables instead)
  • Plain-text configuration files

Exposing API keys can allow unauthorised parties to create orders, process payments, and access merchant data.

API key management requirements

Collection:

  • Collect API keys through secure, encrypted channels (HTTPS)
  • Use secure input forms that don't expose keys in browser developer tools or network logs
  • Never transmit API keys via email, chat, or other insecure communication methods
  • Provide clear instructions to merchants about where to find their API keys and how to securely provide them

Storage:

  • Store API keys encrypted at rest using industry-standard encryption (e.g., AES-256)
  • Implement strict access controls - limit which systems and personnel can access stored keys
  • Store keys in secure credential management systems or vaults
  • Never store API keys in plain text in databases, configuration files, or source code

Usage:

  • API keys must only be used in your server-side application - never expose keys in client-side code, mobile apps, or browser JavaScript
  • Never log API keys in application logs, error messages, or debugging output
  • Use environment variables or secure configuration management for production deployments
  • Implement monitoring to detect unusual API usage patterns that might indicate compromised keys

Compliance and best practices:

  • Follow PCI DSS requirements if you're handling payment card data
  • Implement API key rotation procedures to allow merchants to update their keys if compromised
  • Provide merchants with the ability to revoke access and update their API keys in your system
  • Document your security practices in your POS documentation to give merchants confidence in your integration
tip

If you're unsure about security best practices for API key management, consult with your security team or a security professional before deploying your integration to production.

Before you begin

Before you start this tutorial, ensure you have the followings:

info

If you don't have the required Terminal app version, you can update your device by restarting it twice. See Update software for details.

Implement push payments

This section walks you through the exact sequence of API calls needed to process a payment from your POS to a Revolut Terminal.

1. Create or use an existing location

A location is required to link orders in the Merchant API with the physical place where your merchant operates and uses their Revolut Terminal.

  • From a business perspective: Locations help you organize your business operations by associating transactions with specific physical stores or points of sale. This is essential for reporting, inventory management, and understanding where your sales are happening.
  • From a technical perspective: The Merchant API stores location information and requires you to use the location_id during order creation to link that purchase to a specific location. This link is what enables push payments to work—only terminals assigned to the same location can receive payment intents for orders created at that location.
warning

Only physical location types work with push payments. Online locations are not supported for terminal integrations.

You have two options: create a new location or use an existing one.

Use the Create a location endpoint to register a new physical location in the Merchant API.

Request:

POST https://merchant.revolut.com/api/locations

Headers:

HeaderValue
AuthorizationBearer <your_secret_api_key>
Revolut-Api-Version<api_version>
Content-Typeapplication/json

Request body:

Provide the location details including name, type (must be "physical"), and address information.

{
"name": "Example Street Store",
"type": "physical",
"address": {
"street_line_1": "123 Example Street",
"city": "London",
"postcode": "W1B 5TH",
"country_code": "GB"
}
}
info

Alternatively, you can create locations via the Revolut Business Portal, as described in the Locations section.

In this case, you'll need to retrieve the location ID using the Retrieve location list endpoint.

tip

After obtaining your location's id, make sure your Revolut Terminal is assigned to the same location. You can check and change the terminal's location via More > Settings > General > Locations on the device.

See Additional features: Change the Terminal location for details.

2. Create an order

When a customer is ready to pay at your POS, your server-side application should create an order that captures the purchase details. This order is the foundation of the payment flow—it defines what is being purchased, for how much, and at which location.

Your POS server is responsible for:

  1. Collecting the checkout details (e.g., amount, currency, line_items, etc.) from your POS interface.
  2. Securely calling the Merchant API: Create an order endpoint with these details and your API key.
  3. Receiving the order details, including the unique id, back from the Merchant API.
  4. Using this id in subsequent steps to push the payment intent to a terminal.

Request:

POST https://merchant.revolut.com/api/orders

Headers:

HeaderValue
AuthorizationBearer <your_secret_api_key>
Revolut-Api-Version<api_version>
Content-Typeapplication/json

Request body:

The following fields are required for push payments to work correctly:

FieldValueDescription
channel"pos"Identifies this as a POS transaction (required for push payments).
location_id"<your_location_id>"The location ID from step 1 (links order to terminal location).
capture_mode"manual"Set to manual for controlled capture timing. The terminal will automatically handle capture or cancellation based on the payment outcome.
fulfilment_type"eat_in" or "take_away"Transaction context (required for reporting and compliance).
metadata.pos_partner_name"<your_pos_name>"Your POS software name for tracking and support purposes.
{
"amount": 2500,
"currency": "GBP",
"channel": "pos",
"location_id": "b9d53717-90e3-462b-8ac1-c6d51bcf497c",
"fulfilment_type": "eat_in",
"capture_mode": "manual",
"metadata": {
"pos_partner_name": "YourPOS"
}
}
tip

You can include additional fields like line_items, customer.email, or description to provide more context in the merchant's Revolut Business dashboard for reporting and customer service purposes.

3. Find available terminals

Before you can push a payment intent, you need to identify which terminal at the location should receive the payment request. This step is performed each time a payment is initiated, allowing staff to dynamically select the appropriate terminal for each transaction (for example, a staff member at a POS station choosing which terminal a colleague should use to accept payment at a customer's table).

Your POS server queries the Merchant API to retrieve a list of terminals that are online, in Pay at Counter mode, and assigned to the same location as your order.

Request:

GET https://merchant.revolut.com/api/terminals?operation_mode=pos&location_id=<location_id>

Headers:

HeaderValue
AuthorizationBearer <your_secret_api_key>
Revolut-Api-Version<api_version>

Query parameters:

ParameterValueDescription
operation_modeposFilters to only return terminals in Pay at Counter mode (required for push payments).
location_id<location_id>The same location_id you used in previous steps. This ensures you only see terminals at that specific location.
note

Troubleshooting: No terminals returned

If the API returns an empty list, verify that:

  • The terminal is logged in to the correct Revolut Business account
  • The terminal is assigned to the same location (matching the location_id from step 1)
  • Pay at Counter mode is enabled on the terminal (see Enable Pay at Counter mode)
  • The terminal is powered on and connected to the internet

4. Push payment intent to terminal

Now that you have both an order and a terminal, you can push the payment intent to the selected terminal. This action sends the payment request to the physical terminal device, where it will be displayed to the customer.

Your POS server sends the payment intent by calling the specified endpoint with:

  1. The order_id from step 2 (in the URL path)
  2. The terminal_id from step 3 (in the request body)
  3. The amount to charge (must match the order amount)

Request:

POST https://merchant.revolut.com/api/orders/{order_id}/payment-intents

Request body:

{
"amount": 2500,
"terminal_id": "0e53f673-7705-473a-a263-89a3e7647c3d"
}
What happens next

At this point, the payment request appears on the Revolut Terminal screen, prompting the customer to present their card or device. The terminal will process the payment and update the payment intent status accordingly.

Cancel a payment intent (optional)

If needed, you can cancel a payment intent while it's still in pending state (before the customer has completed the payment):

Request:

POST https://merchant.revolut.com/api/payment-intents/{payment_intent_id}/cancel

This is useful if the customer changes their mind or if there's an issue with the order before payment is completed.

5. Track payment intent status

After pushing the payment intent to the terminal, you need to monitor its status to know when the customer has completed (or cancelled) the payment. This is done by repeatedly checking the payment intent's state.

What your POS server does:

  • Polls the payment intent endpoint using the payment_intent_id from step 4
  • Continues polling while the state is pending or processing
  • Handles the final state (completed, cancelled, or failed)
  • Extracts the payment_id when payment is completed

Request:

Use the payment_intent_id you saved from step 4:

GET https://merchant.revolut.com/api/payment-intents/{payment_intent_id}

Headers:

HeaderValue
AuthorizationBearer <your_secret_api_key>
Revolut-Api-Version<api_version>

Payment intent states and actions

StateDescriptionAction
pendingPayment intent has been created and sent to the terminal. The customer has not yet started interacting with the terminal.Continue polling.
processingCustomer is actively interacting with the terminal (e.g., inserting card, entering PIN).Continue polling.
completedPayment authorization is complete. The response includes a payment_id.Stop polling. Extract the payment_id and proceed to step 6 to retrieve the final payment status.
cancelledPayment intent was cancelled (either by your system calling the cancel endpoint, or by the customer on the terminal).Stop polling. Handle the cancellation in your system (e.g., notify staff, update order status). You'll need to create a new order if the customer wants to retry.
failedPayment intent failed due to technical issues (e.g., timeout, terminal became unavailable, network error).Stop polling. Handle the error in your system. Check the terminal's availability and connection. You may retry by creating a new payment intent.
Polling strategy
  • Poll every second while the state is pending or processing
  • Set a reasonable timeout (e.g., 60 seconds) to handle cases where the customer abandons the payment
  • When the timeout is reached, consider calling the cancel endpoint and updating your order status accordingly

6. Track payment status

Once the payment intent reaches completed state, you need to poll the payment status until it reaches a final state. The terminal automatically handles the payment capture or cancellation based on the transaction outcome, so your POS should continuously check the payment status until processing is complete.

What your POS server does:

  • Retrieves payment details using the payment_id from step 5
  • Continuously polls while the payment is in transitional states (authorised, capture_started, declining, cancelling, failing)
  • Stops polling when reaching a final state: captured, completed, declined, failed, or cancelled
  • Extracts payment method details (card information) for display or receipts

Request:

Use the Retrieve payment details endpoint with the payment_id you saved from step 5:

GET https://merchant.revolut.com/api/payments/{payment_id}

Headers:

HeaderValue
AuthorizationBearer <your_secret_api_key>
Revolut-Api-Version<api_version>

Payment states and actions

StateDescriptionAction
capturedPayment successfully captured. Funds will be transferred to the merchant's account.Stop polling. Proceed to step 7 to display success message.
completedPayment completed successfully (typically for alternative payment methods).Stop polling. Proceed to step 7 to display success message.
declinedPayment was declined by the card issuer (e.g., insufficient funds, card blocked).Stop polling. Display decline message. Customer may retry with a different payment method.
failedPayment failed due to technical issues during processing.Stop polling. Display failure message. Customer may retry.
cancelledPayment was cancelled before completion.Stop polling. Display cancellation message. Customer may retry if needed.
authorisedPayment authorised, capture in progress.Continue polling (terminal is processing the capture).
capture_startedCapture process has started.Continue polling.
decliningDecline process in progress.Continue polling.
cancellingCancellation in progress.Continue polling.
failingFailure process in progress.Continue polling.
Polling strategy
  • Poll every second while the payment is in a transitional state
  • Set a reasonable timeout (e.g., 60 seconds) to handle edge cases
  • Do not use transitional states for business logic—only use final states to determine the transaction outcome
info

The payment_method object in the response contains card details that can be useful for displaying on receipts or in your POS interface (e.g., "Visa ending in 4242"). Never log or store full card numbers — only use the provided last_four and other safe fields.

7. Display results on POS

Once the payment reaches a final state, use the payment response data to display the transaction result to merchant staff. The Revolut Terminal automatically displays the result to the customer.

Available data from the payment response:

The payment response from step 6 includes:

  • state: The final payment state (captured, completed, declined, failed, or cancelled)
  • amount and currency: Transaction amount
  • payment_method: Card details including card_brand, card_type, and last_four digits
  • created_at, updated_at, completed_at: Timestamps for tracking

Handling different payment states:

Use the state field to determine how to handle the transaction in your POS:

  • Success states (captured or completed): The payment was successful and funds will be transferred. Update your order status accordingly and offer receipt options.
  • Unsuccessful states (declined, failed, or cancelled): The payment was not successful. Consider providing an option to retry with a new payment attempt.

Example approaches:

Your POS UI might display information like:

  • Successful payments: Transaction confirmation with payment method details (e.g., "Paid with Visa ending in 4242") and receipt options
  • Unsuccessful payments: Payment status with an option to create a new transaction
tip
  • The terminal shows the result to the customer; your POS display is for merchant staff only
  • Use payment_method details for generating receipts (never log or store full card numbers)
  • Update order status in your system based on the payment state

Merchant journey

This section provides context for integrators on how merchants will set up the Revolut Terminal integration with your POS software.

Overview for integrators

As a POS software provider, implementing push payments to Revolut Terminal allows you to offer your merchants a seamless payment acceptance solution using Revolut's physical terminal devices. This integration becomes a key feature of your POS offering.

From a business perspective:

  • Your merchants gain access to Revolut Terminal devices without switching POS systems
  • You can market "Revolut Terminal support" as a competitive advantage
  • Merchants benefit from Revolut's competitive payment processing rates
  • You maintain control of the merchant relationship and POS experience

From a technical perspective:

  • Your POS software communicates directly with Revolut's Merchant API
  • No complex terminal SDKs or drivers are required — it's pure REST API integration
  • Your server-side application remains the central hub for order management and business logic
  • Terminals operate independently, with your POS pushing payment requests as needed

Documentation requirements:

Once you've implemented this integration, you should update your own POS documentation to guide your merchants through the setup and usage of Revolut Terminal. The merchant setup journey below outlines what your merchants will need to do — this information should be incorporated into your product documentation.

Security requirements:

As a POS provider, you're responsible for securely handling your merchants' Revolut API keys. When merchants provide their API keys during the pairing process, you must:

  • Store API keys encrypted at rest using industry-standard encryption
  • Only use API keys from your secure server-side application (never in client-side code, browser JavaScript, or mobile apps)
  • Never log or expose API keys in application logs, error messages, or network requests
  • Implement access controls and monitoring for stored credentials
  • Provide merchants with the ability to update or revoke their API keys if needed

For comprehensive security guidelines and best practices, see Your role as API orchestrator.

warning

Merchant API keys provide full access to create orders and process payments. Improper handling of these credentials can lead to unauthorised access to merchant accounts and payment data.

Merchant setup steps

Phase 1: Initial setup and login

  1. Merchant logs into POS (on 3rd Party POS) The merchant logs into their third-party Point of Sale application.

  2. Merchant logs into Revolut Business (on Revolut Terminal) The merchant logs into their Revolut Business account on the Revolut Terminal and selects a specific location (e.g., "Regent Street, 123 Store").

  3. Merchant enables 'Pay at Counter' mode (on Revolut Terminal) The merchant enables 'Pay at Counter' mode in the Revolut Terminal's settings, allowing the integrated POS to push payments to it. For detailed instructions, see Enable Pay at Counter mode.

Phase 2: Device pairing

  1. Merchant navigates to POS pairing settings (on 3rd Party POS) The merchant accesses the pairing/integration settings within the POS application and selects the "Revolut Terminal" option.

  2. Merchant enters API key (on 3rd Party POS) The merchant enters their Merchant API Secret Key into the POS to authenticate and link their Terminal devices.

note

Currently, only API key authentication is supported. Additional authentication options may be available in future releases.

Phase 3: Processing payments

  1. Merchant initiates order (on 3rd Party POS) The merchant starts a new order on the POS system for a customer who is ready to pay.

  2. POS sends payment to Terminal (automated) The merchant selects one of the available Revolut Terminals (logged into the same location) as the payment method. The POS automatically sends the payment request to the selected terminal to be processed.

Implementation checklist

Before deploying your push payments integration to production, complete the checklist below to ensure everything works as expected. You should verify that all checks pass in both the sandbox environment and production environment before rolling out to your merchants.

Testing in sandbox

You can test push payments to Terminal in the sandbox environment using simulated payment scenarios. The sandbox behaves identically to production with the following differences:

API base URL:

  • Use https://sandbox-merchant.revolut.com for all API calls (instead of https://merchant.revolut.com)

Terminal discovery (Step 3):

  • The sandbox returns a single virtual terminal with ID: 11111111-0000-0000-0000-000000000000
  • Use this terminal ID when testing payment intent creation

Order amounts for testing scenarios:

Different order amounts trigger specific payment outcomes in sandbox:

Payment outcomeAmount (minor units)
Successful paymentAny amount not listed below
Insufficient funds3500 or 2000 ≤ amount < 2300
Transaction not allowed for cardholder4000 or 2300 ≤ amount < 2500
Suspected fraud2500 ≤ amount < 2700

Initial setup

  • Merchant account is created and API key is generated
  • At least one Revolut Terminal device is available (app version 1.56 or higher)
  • Physical location is created via the Merchant API or exists in Revolut Business
  • Terminal is assigned to the correct location via terminal settings
  • Pay at Counter mode is enabled on the terminal

Order creation and terminal discovery

  • Your POS server successfully creates orders with required POS fields (channel: "pos", location_id, capture_mode: "manual", fulfilment_type)
  • API request includes the correct location_id matching your terminal's location
  • Order creation returns a valid order_id
  • Terminal discovery API returns your terminal in the list (with correct location_id and operationMode: "pos")
  • Your POS can handle multiple terminals at the same location (if applicable)

Payment flow

  • Push payment intent successfully sends payment to the terminal
  • Payment request appears on the Revolut Terminal screen
  • Polling logic correctly checks payment intent status every 2-3 seconds
  • Polling stops when reaching a final state (completed, cancelled, or failed)
  • Timeout logic is implemented (e.g., 90 seconds) to handle abandoned payments
  • Successful payment flow:
    • Customer can complete payment on the terminal with a real card
    • Payment intent reaches completed state
    • POS polls payment status continuously until reaching final state
    • Payment status reaches final success state (captured or completed)
    • Terminal automatically displays result to customer
    • POS displays transaction result to merchant staff based on payment response data
  • Error handling works as expected:
    • Declined payments are handled correctly with appropriate messaging
    • Failed payment intents are handled with proper error messaging
    • Cancelled payments are handled appropriately
    • Your POS recovers gracefully from errors

Edge cases and security

  • Cancel payment intent endpoint works correctly for pending payments
  • Partial capture functionality works as expected (if you use this feature)
  • API keys are never exposed in client-side code, mobile apps, or browser JavaScript
  • API keys are stored encrypted at rest using industry-standard encryption (e.g., AES-256)
  • API keys are never logged in application logs, error messages, or debugging output
  • Secure credential management system is implemented for storing API keys (e.g., AWS Secrets Manager, Azure Key Vault, HashiCorp Vault)
  • API key collection happens over secure, encrypted channels (HTTPS only)
  • Merchants can update or revoke their API keys in your POS system
  • Order amounts are validated server-side before creating payment intents
  • Your system handles network timeouts and connection errors gracefully
  • Terminal unavailability is handled appropriately (no terminals returned scenario)

Documentation and merchant experience

  • Your POS documentation includes Revolut Terminal setup instructions
  • Merchants understand how to enable Pay at Counter mode
  • Merchants understand how to assign terminals to locations
  • Merchants understand how to enter API keys in your POS
  • Your support team is trained on troubleshooting common issues (e.g., terminal not appearing, payment not showing on terminal)
tip

Testing recommendations

  • In production, test with small amounts (e.g., £0.01) and refund immediately after each test (you need to have sufficient funds on your account to process refund fees)
  • Test both successful and failed payment scenarios
  • Test with multiple terminals at the same location (if applicable)
  • Simulate network failures and timeouts to ensure your error handling is robust
  • Test the complete flow from order creation through final payment status display

Going live

Once you've completed testing and verified all items in the checklist above, you can roll out the integration to your merchants. Ensure your documentation is updated and your support team is prepared to assist merchants with setup and troubleshooting.

Need help?

For guidance on testing strategies or if you encounter issues during implementation, contact your Revolut Account Executive.


What's next?

Now that you've implemented push payments to Revolut Terminal, explore these resources to enhance your integration:

Was this page helpful?