Cloud API

Details on using Solo card readers and processing remote in-person payments via the Cloud API.

The Cloud API lets you start a transaction from a Point of Sale (POS) running on any platform (Windows, iOS, Linux, Android, Web-based, etc.) capable of sending HTTPS requests and complete that transaction via a Solo reader.

Tip

You can start building with the Cloud API before you order or receive a Solo reader. Use Virtual Solo(Opens in a new tab) and a sandbox merchant account to test the pairing and checkout flow. See the Virtual Solo testing guide for supported features and limitations.

Key advantages include:

  • Compatibility with any operating system and platform
  • Ability to process simultaneous transactions on multiple Solo card readers at once
  • No distance limitation between your POS device and the Solo card reader; transactions can be sent remotely
  • No Bluetooth connection required
  • PCI compliance, ensuring secure and compliant transactions

The Cloud API integration supports:

  • Debit, credit, and installment transactions
  • Pairing multiple Solo card readers with any SumUp account
  • Naming each Solo card reader as desired to streamline checkout
  • Wi-Fi and mobile data connectivity (mobile data needs manual enabling by SumUp)

Prerequisites

  • Your device must be authorized to use the Cloud API. Refer to the authorization guide and implement the method that best fits your use case. An API key should be sufficient if you don’t plan to delegate access to third parties.

  • You must create an Affiliate Key for your app, as SumUp Cloud API requires this key in checkout requests.

  • We strongly recommend keeping the Solo terminal plugged in when using the Cloud API.

  • If you want to use mobile data, ensure you are not connected to Wi-Fi. Disconnect from Wi-Fi if necessary—when both mobile data and Wi-Fi are available, the Solo reader will always use Wi-Fi.

    To disconnect Wi-Fi, navigate to Connections > Wi-Fi and disable Wi-Fi using the on-screen slider.

Testing

Follow the in-person payment testing guide to test successful payments and simulate specific decline reasons using a sandbox merchant account.

Solo Virtual Terminal

You can also test your Cloud API integration without a card reader using Virtual Solo(Opens in a new tab) with a SumUp sandbox merchant account.

Virtual Solo simulates a Solo card reader so you can test pairing and checkout flows. Use a Solo reader to test card reading and other device behavior. The following actions are not supported by Virtual Solo:

  • Physical card insertion or tap simulation (since there is no physical Solo device)
  • Real funds transfer (sandbox merchant accounts only)
  • PIN entry simulation (always auto-approved)
  • Offline transactions
  • Custom receipt printing
  • Network configuration
  • Real device pairing (the simulator uses virtual device identifiers)

Pairing Solo Reader via Cloud API

The Cloud API acts as a bridge between your application and the Solo reader. It supports two main processes:

  • Pairing a Solo reader to your account
  • Taking in-person payments via Solo

Once the Solo reader is paired to your SumUp account, your application can initiate a card charge request. SumUp handles the rest, providing a seamless payment experience where all card data is encrypted end-to-end. Transaction results are available in real-time via webhooks.

Pairing and checkout
Step 1 of 7 · Solo readerGenerate pairing code

On the logged-out Solo reader, open Connections → API → Connect. Copy the pairing code; it expires after five minutes.

Read all steps
  1. Generate pairing code (Solo reader). On the logged-out Solo reader, open Connections → API → Connect. Copy the pairing code; it expires after five minutes.
  2. Pair reader using the code (Your application → Cloud API). Your application sends the pairing code to the Create Reader endpoint for your merchant account.
  3. Return reader ID (Cloud API → Your application). The Cloud API returns the reader ID. Your application uses this ID to address checkout requests to the paired reader.
  4. Display pairing confirmation (Cloud API → Solo reader). The Solo reader briefly displays the pairing confirmation, then returns to the idle screen.
  5. Start checkout on reader (Your application → Cloud API). Your application creates a checkout using the paired reader ID and the payment amount.
  6. Initiate checkout (Cloud API → Solo reader). The Cloud API sends the checkout to the Solo reader. Starting a checkout is asynchronous and may take some time.
  7. Present checkout to customer (Solo reader). The reader prompts the customer to pay. Follow the checkout lifecycle below to handle the final payment result.

Click an arrow to explore a step, or press Play to follow the sequence. No requests are sent to your reader.

Log out of Solo

The Cloud API pairing process is only available for logged-out users. If you’re logged in to your merchant account, do the following:

  1. Open the top-side menu on your Solo.
  2. Select Settings. The Device settings menu opens.
  3. Go to the About section.
  4. Select Log out. Solo should now display the login screen.

Generate Pairing Code

To initiate a payment on the Solo card reader, it must be enrolled with the merchant account. This enrollment, called reader pairing, starts on the card reader by generating a pairing code and finishes when your device completes a pairing request using the Cloud API with that code. Both your application and Solo reader must be connected to the internet (not necessarily the same network).

Note

The pairing process has an expiration time of 5 minutes, if any issue occurs, the process must be restarted.

  1. Turn on the Solo card reader.
  2. Make sure you’re not logged in. Log out from your Solo card reader if you are.
  3. Open the top menu drawer
  4. Go to Connections and connect to Wi-Fi (connecting is skipped in the short video below).
  5. Select API.
  6. Click Connect. The pairing code is generated.
  7. Copy the pairing code displayed on the Solo card reader screen. You will need this code to pair your Solo reader with your device.

Pair the Card Reader with Pairing Code

  1. Send a request to the Create Reader endpoint.
  2. Verify pairing confirmation on the reader screen. It appears for a short while, after which the reader returns to the idle screen.
Solo device API pairing confirmation screen.
Solo device API pairing confirmation screen.

Using Paired Reader

Cloud API lets you manage transactions and readers connected to your account.

Explore a successful or failed checkout below. The order stays unpaid until your application receives the final transaction result.

Checkout lifecycle
Your application → Cloud APICreate a checkout

Send the amount, reader ID, and HTTPS return_url.

Order unpaid
Read all steps
  1. Create a checkout. Send the amount, reader ID, and HTTPS return_url.
  2. Checkout accepted. Store client_transaction_id. Acceptance does not confirm payment: keep the order unpaid.
  3. Customer completes payment. The reader asks the customer to present a card and complete any requested steps.
  4. Receive the final result. Match the solo.transaction.updated webhook's client_transaction_id to the checkout.
  5. Update the order. For successful, mark the matching order paid. For failed, keep it unpaid and let the customer retry or choose another payment method.

Explore each step, or play the walkthrough. This example sends no payment requests.

Initiate Transaction

This is an asynchronous process; starting the transaction on the device may take some time.

curl -X POST \
  https://api.sumup.com/v0.1/merchants/$SUMUP_MERCHANT_CODE/readers/$READER_ID/checkout \
  -H "Authorization: Bearer $SUMUP_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
        "total_amount": {
          "currency": "EUR",
          "minor_unit": 2,
          "value": 1500,
        }
      }'
const checkout = await client.readers.createCheckout(merchantCode, readerId, {
  total_amount: {
    currency: "EUR",
    minor_unit: 2,
    value: 1500,
  },
});
var checkout = await client.Readers.CreateCheckoutAsync(
    merchantCode,
    readerId,
    new CreateReaderCheckoutRequest
    {
        TotalAmount = new CreateReaderCheckoutRequestTotalAmount
        {
            Currency = "EUR",
            MinorUnit = 2,
            Value = 1500,
        },
    });
var checkout = client.readers().createReaderCheckout(
    merchantCode,
    readerId,
    CreateReaderCheckoutRequest.builder()
        .totalAmount(
            Money.builder()
                .currency("EUR")
                .minorUnit(2L)
                .value(1500L)
                .build()
        )
        .build()
);
checkout, err := client.Readers.CreateCheckout(ctx, merchantCode, readerID, sumup.CreateCheckoutRequest{
      TotalAmount: sumup.CreateCheckoutRequestTotalAmount{
          Currency:  "EUR",
          MinorUnit: 2,
          Value:     1500,
      },
  })
checkout = await client.readers.create_checkout(
    merchant_code,
    reader_id,
    CreateReaderCheckoutBody(
        total_amount=CreateReaderCheckoutBodyTotalAmount(currency="EUR", minor_unit=2, value=1500),
    ),
)
let checkout = client.readers().create_checkout(
    &merchant_code,
    &reader_id,
    CreateReaderCheckoutRequest {
        total_amount: Money {
            currency: "EUR".into(),
            minor_unit: 2,
            value: 1_500,
        },
        affiliate: None,
        card_type: None,
        description: None,
        installments: None,
        return_url: None,
        tip_rates: None,
        tip_timeout: None,
    },
).await?;

Important notes:

  • The target device must be online, otherwise checkout won’t be accepted
  • After the checkout is accepted, the system has 60 seconds to start the payment on the target device. During this time, any other checkout for the same device will be rejected.
  • You need to send the Affiliate Key in the request.

Read the Create Checkout API endpoint documentation for details on the API request, examples, and parameter descriptions.

Receive Transaction Results

Because the checkout is asynchronous, the API response only confirms that the checkout was accepted—not that the payment succeeded. To receive the final result, pass a return_url when creating the checkout. SumUp sends an HTTPS POST request to that URL once the transaction reaches a final state.

curl -X POST \
  https://api.sumup.com/v0.1/merchants/$SUMUP_MERCHANT_CODE/readers/$READER_ID/checkout \
  -H "Authorization: Bearer $SUMUP_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
        "total_amount": {
          "currency": "EUR",
          "minor_unit": 2,
          "value": 1500
        },
        "return_url": "https://example.com/sumup/webhook"
      }'

The return_url must use HTTPS and be publicly reachable.

Webhook Payload

The webhook body uses the solo.transaction.updated event type:

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "event_type": "solo.transaction.updated",
  "payload": {
    "client_transaction_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "merchant_code": "M1234567",
    "status": "failed",
    "failure_reason": "Invalid merchant number"
  },
  "timestamp": "2023-10-05T14:48:00Z"
}

The status field is either successful or failed. Use client_transaction_id to match the webhook against the checkout you started—it holds the same value returned by the Create Checkout response. The transaction_id field is deprecated and should not be used in new integrations.

Failure Reason

When status is failed, the payload may include a failure_reason field describing why the transaction did not go through. Use this information to help diagnose failed payments.

Treat the value as free-form text: do not match on exact strings, as new reasons can be introduced at any time.

Do not display failure_reason directly to customers. Choose an appropriate customer-facing message instead. For lost-card or stolen-card declines, show a generic payment-declined message.

Note

failure_reason is only sent for failed transactions. It is omitted from the payload entirely—rather than sent as null—for successful transactions, and when no reason is available.

Terminate Transaction

Stops the current transaction on the target device. This process is asynchronous, and the actual termination may take some time to be performed on the device.

curl -X POST \
  https://api.sumup.com/v0.1/merchants/$SUMUP_MERCHANT_CODE/readers/$READER_ID/terminate \
  -H "Authorization: Bearer $SUMUP_API_KEY"
await client.readers.terminateCheckout(merchantCode, readerId)
await client.Readers.TerminateCheckoutAsync(merchantCode, readerId);
client.readers().createReaderTerminate(merchantCode, readerId, java.util.Map.of());
err := client.Readers.TerminateCheckout(ctx, merchantCode, readerID)
await client.readers.terminate_checkout(merchant_code, reader_id)
client.readers().terminate_checkout(&merchant_code, &reader_id).await?;

Important notes:

  • The target device must be online, otherwise termination won’t be accepted.
  • This action is only possible if the device is waiting for cardholder action: waiting for card, waiting for PIN, etc. There is no confirmation of the termination.
  • If a transaction is successfully terminated and return_url has been provided on Checkout, the transaction status is sent as failed to the provided URL. See Receive Transaction Results.

Read the Terminate Checkout API endpoint documentation for details on the API request, examples, and parameter descriptions.

List Connected Readers

List all readers connected to your merchant account.

curl https://api.sumup.com/v0.1/merchants/$SUMUP_MERCHANT_CODE/readers \
  -H "Authorization: Bearer $SUMUP_API_KEY"
const readers = await client.readers.list(merchantCode)
var readers = await client.Readers.ListAsync(merchantCode);
var readers = client.readers().listReaders(merchantCode);
readers, err := client.Readers.List(ctx, merchantCode)
readers = await client.readers.list(merchant_code)
let readers = client.readers().list(&merchant_code).await?;

Read the List API endpoint documentation for details on the API request, examples, and parameter descriptions.

Check Reader Pairing

Check the pairing status of a specific reader.

Read the Retrieve a Reader endpoint documentation for details on the API request, examples, and parameter descriptions.

Get Reader Status

Get the last known status for a Reader

Read the Get Reader Status endpoint documentation for details on the API request, examples, and parameter descriptions.

Update Reader

Update the data of a specific reader.

Check the Update a Reader endpoint documentation for details on the API request, examples, and parameter descriptions.

Delete Reader

Delete a reader from the Cloud API. After doing this, you also need to physically disconnect the reader using its menu.

Check the Delete a Reader endpoint documentation for details on the API request, examples, and parameter descriptions.

Unpairing Solo Reader

In order to unpair a reader from the merchant account, two steps are required:

  1. Delete Reader from the Merchant account (via Readers API).
  2. Disconnect Reader (manually via Solo).

Disconnect Reader Physically

  1. Open the menu drawer on your Solo.
  2. Go to Connections.
  3. Select API from the menu.
  4. Tap on Disconnect.

Your Solo device is now disconnected.

What’s Next?

For other integration possibilities, check the SDK Integration Documentation.

Type to search…