Skip to content

Online Payments Quickstart

Create a sandbox Hosted Checkout, complete a test payment, and verify the result through the SumUp API.

Complete your first online payment with 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.

Note

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

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.
  • 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.
  1. Log in to the SumUp Dashboard(Opens in a new tab).
  2. Open Developer Settings(Opens in a new tab).
  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(Opens in a new tab). New developer accounts start with a sandbox merchant account.

Sandbox payments are simulations and do not move real funds.

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

export SUMUP_API_KEY="sk_test_replace_me"
export SUMUP_MERCHANT_CODE="replace_me"
export SUMUP_CURRENCY="EUR"
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.

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

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:

{
"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:

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.

  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.

Retrieve the checkout from your backend or terminal:

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:

{
"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.
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.

Set the deliberate failure amount and a new reference:

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.

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.

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. For mobile applications or other checkout experiences, compare the checkout integrations.