# Online Payments Quickstart

import Callout from "@components/content/Callout";

Complete your first online payment with [Hosted Checkout](/online-payments/checkouts/hosted-checkout/), SumUp's hosted payment page. This path requires one server-side API call and no payment UI code.

**Expected time:** 10–15 minutes after you can access the SumUp Dashboard.

<Callout type="note">

You are finished when the Hosted Checkout shows a successful payment and a server-side Retrieve Checkout request returns `PAID`.

</Callout>

## What runs where

| Surface                  | Responsibility                                                                                                      |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| Your backend or terminal | Creates the checkout, stores its ID and reference, and verifies the final status. The API key stays here.           |
| Customer's browser       | Opens the returned `hosted_checkout_url` and displays SumUp's payment form.                                         |
| SumUp                    | Hosts the payment UI, handles card data and authentication, processes the payment, and records the checkout status. |

## Prerequisites

- A SumUp developer account and sandbox merchant account.
- The sandbox merchant's merchant code, currency, and API key.
- A terminal with `curl` and `jq`.
- A browser in which to open the hosted payment page.

## Getting a sandbox merchant account

1. Log in to the [SumUp Dashboard](https://me.sumup.com).
2. Open [Developer Settings](https://me.sumup.com/settings/developer?tab=sandboxes).
3. Create a sandbox merchant account, then select it in the Dashboard account switcher.
4. With the sandbox merchant selected, go to **Settings** > **For Developers** > **Toolkit** > **API Keys**.
5. Create and copy an API key. Do not use the SumUp Public Key.
6. Copy the sandbox merchant code and note its account currency.

If you do not have a SumUp account, [create a developer account](https://me.sumup.com/signup?signup_intent=developer). New developer accounts start with a sandbox merchant account.

Sandbox payments are simulations and do not move real funds.

## 1. Configure your terminal

Replace the values below with the sandbox credentials you just collected. The checkout currency must match the sandbox merchant account currency.

```bash
export SUMUP_API_KEY="sk_test_replace_me"
export SUMUP_MERCHANT_CODE="replace_me"
export SUMUP_CURRENCY="EUR"
```

<Callout type="caution">

Keep the API key on your server or local development machine. Never put it in browser code, a mobile application, source control, screenshots, or support messages.

</Callout>

## 2. Create a Hosted Checkout

Set a successful test amount and a unique reference, then create the checkout:

```bash
export SUMUP_AMOUNT="12.00"
export SUMUP_CHECKOUT_REFERENCE="quickstart-$(date +%s)"

SUMUP_CHECKOUT_RESPONSE="$(
  curl --fail-with-body --silent --show-error \
    --request POST "https://api.sumup.com/v0.1/checkouts" \
    --header "Authorization: Bearer $SUMUP_API_KEY" \
    --header "Content-Type: application/json" \
    --data @- <<JSON
{
  "checkout_reference": "$SUMUP_CHECKOUT_REFERENCE",
  "amount": $SUMUP_AMOUNT,
  "currency": "$SUMUP_CURRENCY",
  "merchant_code": "$SUMUP_MERCHANT_CODE",
  "description": "Quickstart order",
  "hosted_checkout": {
    "enabled": true
  }
}
JSON
)"

echo "$SUMUP_CHECKOUT_RESPONSE" | jq
```

The response should contain these fields:

```json
{
  "id": "64553e20-3f0e-49e4-8af3-fd0eca86ce91",
  "checkout_reference": "quickstart-1785686400",
  "status": "PENDING",
  "hosted_checkout": {
    "enabled": true
  },
  "hosted_checkout_url": "https://checkout.sumup.com/pay/8f9316a3-cda9-42a9-9771-54d534315676"
}
```

Store the values needed for the next steps:

```bash
export SUMUP_CHECKOUT_ID="$(echo "$SUMUP_CHECKOUT_RESPONSE" | jq -r '.id')"
export SUMUP_HOSTED_CHECKOUT_URL="$(echo "$SUMUP_CHECKOUT_RESPONSE" | jq -r '.hosted_checkout_url')"

echo "$SUMUP_HOSTED_CHECKOUT_URL"
```

If either value is empty or `null`, stop and inspect the API response before continuing.

## 3. Complete the payment

1. Copy the printed `SUMUP_HOSTED_CHECKOUT_URL` into your browser.
2. Enter the following sandbox card details.
3. Submit the payment and wait for the Hosted Checkout success page.

| Field           | Test value                       |
| --------------- | -------------------------------- |
| Card number     | `4200 0000 0000 0091`            |
| Expiry date     | Any future date, such as `12/30` |
| CVV             | Any three digits, such as `123`  |
| Cardholder name | Any name                         |

The browser result is useful customer feedback, but it is not the state your backend should use to fulfill an order.

## 4. Verify the payment

Retrieve the checkout from your backend or terminal:

```bash
SUMUP_VERIFICATION_RESPONSE="$(
  curl --fail-with-body --silent --show-error \
    "https://api.sumup.com/v0.1/checkouts/$SUMUP_CHECKOUT_ID" \
    --header "Authorization: Bearer $SUMUP_API_KEY"
)"

echo "$SUMUP_VERIFICATION_RESPONSE" | jq
```

After the successful sandbox payment, the relevant fields look like this:

```json
{
  "id": "64553e20-3f0e-49e4-8af3-fd0eca86ce91",
  "checkout_reference": "quickstart-1785686400",
  "status": "PAID",
  "transactions": [
    {
      "status": "SUCCESSFUL",
      "transaction_code": "TEENSK4W2K"
    }
  ]
}
```

- `PAID`: mark the order as paid exactly once.
- `PENDING`: wait and retrieve the checkout again.
- `FAILED`: keep the order unpaid and let the customer start a new attempt.
- `EXPIRED`: create a new checkout with a new reference.

<Callout type="caution">

Fulfill the order only after your backend retrieves the checkout and confirms `PAID`. A browser redirect, hosted success page, frontend callback, or webhook delivery is not payment proof on its own.

</Callout>

## 5. Test a failed payment

Set the deliberate failure amount and a new reference:

```bash
export SUMUP_AMOUNT="11.00"
export SUMUP_CHECKOUT_REFERENCE="quickstart-failure-$(date +%s)"
```

Repeat steps 2–4 with the same test card. The hosted page should show a failed payment and Retrieve Checkout should return `FAILED`. Never reuse the successful checkout ID or reference for this attempt.

## Troubleshooting

| Symptom                                       | What to check                                                                             |
| --------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `401 Unauthorized`                            | The value is a sandbox secret API key, and the header uses `Bearer`.                      |
| `403 Forbidden`                               | The sandbox merchant can accept online payments and the credential can create checkouts.  |
| `409 Conflict`                                | Generate a new `checkout_reference`; do not reuse a previous attempt's reference.         |
| Missing `hosted_checkout_url`                 | Confirm that `hosted_checkout.enabled` is `true` and inspect the complete error response. |
| Hosted page is expired                        | Hosted Checkout sessions expire after 30 minutes. Create a new checkout and URL.          |
| Browser says success but the API is `PENDING` | Keep the order pending and retrieve the checkout again.                                   |

## Move to production

Before accepting real payments:

1. Switch to the live merchant account and create separate production credentials.
2. Store `checkout.id`, `checkout_reference`, merchant code, amount, currency, and transaction identifiers with your order.
3. Add a real HTTPS `redirect_url` for customer navigation and a webhook for status-change notifications.
4. Make checkout creation and order fulfillment safe against retries and duplicates.
5. Test success, failure, expiry, and abandoned-payment scenarios.
6. Process a small live payment and reconcile it in the SumUp Dashboard before launch.

For an embedded payment form, continue with the [Payment Widget](/online-payments/checkouts/card-widget/). For mobile applications or other checkout experiences, compare the [checkout integrations](/online-payments/checkouts/).