Getting Started

Set up an account, create API keys, switch between test and live.

Welcome to Southbill

Take card, wallet, bank and BNPL payments with one API — no PSP account required.

Welcome to Southbill

Southbill is a payments platform. You create a merchant account, we handle the PSP relationships (cards, wallets, SEPA, Klarna, iDEAL, and more), and you get one REST API to charge customers, run subscriptions, issue refunds and receive payouts to your bank.

This section gets you from zero to your first live payment.

What you can do with the API

Capability Endpoint Docs
One-off payment POST /v1/checkout/sessions Checkout Sessions
Recurring billing POST /v1/subscriptions Subscriptions
Invoicing Dashboard (/dashboard/invoices/new) Invoices
Catalog POST /v1/products · POST /v1/products/{id}/prices Products
Refunds POST /v1/refunds Refunds
Realtime updates Webhooks How webhooks work

Everything is JSON over HTTPS. Base URL: https://api.southbill.com/v1.

Quickstart (5 minutes)

1. Onboard your merchant account. Sign in to the dashboard, complete the 15-step onboarding, and wait for approval. You must be active before live keys work.

2. Grab an API key. Dashboard → DevelopersAPI keys. You'll get two:

  • sk_test_… — sandbox, no real money, no payout.
  • sk_live_… — real money.

Treat these like passwords. See API security best practices.

3. Make your first charge.

curl -X POST https://api.southbill.com/v1/checkout/sessions \
  -H "Authorization: Bearer sk_test_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_0001" \
  -d '{
    "amount": 2500,
    "currency": "eur",
    "customer_name":  "Jane Doe",
    "customer_email": "jane@example.com",
    "success_url": "https://example.com/thanks",
    "cancel_url":  "https://example.com/cart"
  }'

Redirect the buyer to the returned checkout_url. Use test card 4242 4242 4242 4242 with any future expiry and any CVC.

4. Receive the webhook. Add an endpoint at Dashboard → Developers → Webhooks and listen for checkout.session.completed. Always verify the signature — instructions here.

Core concepts

  • Merchant account. Your business on southbill. Owns your keys, products, transactions, payouts.
  • Session / Subscription / Invoice. Three ways to collect money. Pick by use case.
  • client_secret. Short-lived token used by the browser to confirm a payment. Never trust it as proof of payment — details.
  • Fees. Per-plan, per-method, calculated in EUR and deducted per transaction. See Fees.
  • Payouts. Automatic, on your configured schedule (daily/weekly), to your verified bank account.

Environments

Mode Keys Money Payouts
Test sk_test_… / pk_test_… No No
Live sk_live_… / pk_live_… Yes Yes

Both modes share the same base URL and endpoints. The key alone decides which environment you hit.

Test and live responses use the identical object shape — amounts are integers in the smallest currency unit, currencies are lowercase ISO codes, and every object carries livemode (false in test).

Idempotency, errors, rate limits

  • Send Idempotency-Key: <your-key> on every mutating request. Safe retries, no duplicate charges.
  • Errors follow a stable shape: { "error": { "type": "…", "message": "…", "param": "…" } }. See Error reference.
  • Default limits per key, in fixed one-minute windows: 300 req/min for reads, 120 req/min for checkout creates, 60 req/min for other writes. 429 rate_limited includes a Retry-After header.

Where to next

API keys & authentication

Create keys, keep them safe, rotate them

API keys

Create a key

Open Dashboard → Developers → API keys and click Create key. Pick a name, a mode (Test or Live), and copy the secret. The secret is shown once — Southbill stores only a SHA-256 hash. If you lose it, revoke and create a new one.

Keys look like:

sk_live_ABCDEfghi23jkLmnOPqrSTUv...   ← live
sk_test_ABCDEfghi23jkLmnOPqrSTUv...   ← test

Authenticate a request

Send the secret as a Bearer token in the Authorization header:

POST /v1/checkout/sessions HTTP/1.1
Host: api.southbill.com
Authorization: Bearer sk_test_ABCDEfghi23jkLmnOPqrSTUv...
Content-Type: application/json

Never call the API with a secret key (sk_…) from the browser — requests carrying an Origin header are rejected with 401. For client-side calls use a publishable key (pk_live_… / pk_test_…) restricted to allow-listed origins; it can only create Checkout Sessions from your own catalog prices.

Scopes

Secret keys carry explicit scopes (checkout:write, checkout:read, refunds:write, products:write, …). A call outside the key's scopes returns 403 permission_error. Publishable keys ignore scopes and are limited to the browser checkout flow.

Rotation

Rotating a key is a two-step revoke:

  1. Create a new key, deploy it, verify traffic uses it.
  2. Revoke the old key in the dashboard (revoked_at is set immediately, all subsequent requests receive 401).

Idempotency

Every mutating request accepts an Idempotency-Key header. Southbill stores the first response for 24 hours and returns the exact same status and body when the same key is sent again with the same payload. Reusing the key with a different payload returns 409 idempotency_error (Idempotency-Key reused with different payload).

Idempotency-Key: order_9781_attempt_1

Currencies & amount format

Supported currencies, minor units, zero-decimal rules, min/max.

Currencies & amount format

All amount fields in the Southbill API are integers in the smallest currency unit (minor units), following the ISO 4217 exponent for that currency.

Amount format

Currency type Example 10.00 → integer
2-decimal (most currencies) EUR, USD, GBP, CHF, CAD, AUD, SEK, NOK, DKK, PLN, CZK, RON, BGN 1000
0-decimal (zero-decimal) JPY, KRW, VND, CLP, ISK, HUF 10
3-decimal BHD, JOD, KWD, OMR, TND 1000 = 1.000

Send integers only. 10.5 or "10.00" are rejected with invalid_request.

Supported currencies

Currencies accepted on POST /v1/checkout/sessions:

eur, usd, gbp, chf, sek, nok, dkk, pln, czk, ron, bgn, huf, cad, aud, nzd, jpy, sgd, hkd.

Always lowercase 3-letter ISO. Currencies outside this list return 400 invalid_request (currency_unsupported).

Payment method coverage

Not every method supports every currency. Southbill automatically hides methods at checkout that the currency does not support (e.g. Klarna is EU-only, iDEAL is EUR-only, Bancontact is EUR-only).

Minimum and maximum

  • Minimum: 2.50 EUR equivalent (e.g. 250 in EUR/USD/CHF, 300 in JPY). Below this: 400 amount_too_small.
  • Maximum per charge: 999,999.99 in the transaction currency. Above this: 400 amount_too_large.

See Fees, currency & minimum amounts for the reasoning behind the minimum.

Payout currency

Merchants are paid out in their onboarding currency (usually EUR or CHF). Charges in other currencies are converted at the daily FX rate with a +2.00% FX surcharge.

Fees, currency & minimum amounts

How Southbill calculates fees, converts currencies and why there is a minimum charge.

Fees, currency & minimum amounts

Southbill charges fees in a predictable way — no matter which currency your customer pays in. This page explains exactly how it works.

1. Fees are always denominated in EUR

Every fee in your plan (Free / Starter / Business / Plus) and every per-method fee shown on the pricing and compare pages is defined in EUR.

  • The percentage part (e.g. 2.5%) applies to the transaction amount converted to EUR.
  • The fixed part (e.g. €0.25) is an EUR amount.
  • The final fee is charged in the transaction currency, converted at the live FX rate at the moment the payment is captured.

Example: a customer pays CHF 40.00 on the Business plan (3.9% + €0.30).

  1. CHF 40.00 → EUR ≈ 41.20 (live FX)
  2. Fee in EUR = 41.20 × 3.9% + 0.30 = €1.91
  3. Fee back to CHF ≈ CHF 1.85 — this is what appears on the charge.

You always see both values in your dashboard (wallet, transactions, ledger).

2. Why the fee ledger sometimes shows a "top-up"

At checkout creation we don't yet know which card region the customer will use, so we charge the base rate. Once the payment is captured we know the real card region (EU / UK / intl) and compare the real fee to what was already deducted:

  • Correct: no ledger entry.
  • Under-collected: a fee_topup entry is created and added to the next transaction.
  • Over-collected: a refund entry balances it out.

This guarantees the merchant always pays exactly the plan's rate — no more, no less.

3. Minimum charge amount: 2.50 EUR

You can only create invoices, products and payment links with a total of at least 2.50 EUR (or the equivalent in the transaction currency).

Why? PSP fees + Southbill fees always include a fixed component (e.g. €0.25 – €0.95 per transaction). On a €1.00 charge those fixed costs would exceed the amount and result in a loss — for you and for us.

The 2.50 minimum applies to:

  • Invoice totals (line items + tax)
  • Product prices (one-time and recurring)
  • API checkout_sessions — smaller amounts are rejected with amount_too_small

For subscriptions with trial periods the minimum applies to each billing cycle amount, not to the trial.

4. Payout currency & FX conversion

Payouts are made in your merchant currency (usually EUR or CHF). If a customer pays in another currency:

  • The gross amount is converted to your payout currency at the daily FX rate.
  • A +2.00% currency-conversion surcharge is applied on top of the standard fee.
  • The full breakdown is visible on the transaction detail sheet.

5. Full fee summary (per transaction)

Component When Amount
Plan percentage Every transaction e.g. 2.5% (plan-dependent)
Plan fixed Every transaction e.g. €0.25 (plan-dependent)
International card surcharge Card issued outside merchant country +1.50%
FX surcharge Charge currency ≠ payout currency +2.00%
Chargeback Per dispute case €15.00
Payout Per bank payout included on all paid plans

All values are defined in EUR and converted per transaction. Surcharges apply on top of the plan rate and only when the trigger condition is met.

6. TL;DR

  • Everything is priced in EUR.
  • Fees are converted to the transaction currency at capture time.
  • Minimum 2.50 EUR per invoice, product or checkout — otherwise fees can't be covered.
  • The fee ledger self-corrects so your effective rate always matches your plan.

API security best practices

How to protect your secret keys, webhooks and integration.

API security best practices

Never expose secret keys

  • sk_live_… and sk_test_… grant full merchant access. Never ship them in browser code, mobile apps, git repos, logs, error reports, or client-side analytics.
  • Always call the Southbill API from your server. From the browser, only ever use the client_secret returned by POST /v1/checkout/sessions.
  • Rotate keys immediately if you suspect a leak (Dashboard → Developers → Revoke).

Separate test and live

  • sk_test_… keys only work in test mode and never move real money. Use them for CI, staging and local development.
  • Live keys should be stored in your production secret store (AWS Secrets Manager, Vault, GitHub Actions Secrets, etc.) — never in .env files committed to git.

Enforce TLS

  • The API only accepts requests over HTTPS (TLS 1.2+). Plaintext HTTP is rejected.
  • Verify TLS certificates in your HTTP client. Disabling verification defeats the point.

Always use Idempotency-Keys

  • Send an Idempotency-Key header on every POST that creates money-moving objects.
  • Use a stable value per business action (e.g. order_12345) — not a random UUID per retry.
  • See Checkout Sessions → Idempotency.

Verify webhook signatures

  • Never trust a webhook body without verifying the Southbill-Signature header with your whsec_… secret.
  • Reject signatures older than 5 minutes (replay protection).
  • See Webhooks → Verify signatures.

Rate limits

  • Per API key, per minute: 120 Checkout Session creates, 300 reads, 60 writes (products, subscriptions, refunds).
  • Exceeding returns 429 rate_limited with a Retry-After header. Implement exponential backoff.

Principle of least privilege

  • Create separate keys per environment / service and revoke unused ones.
  • Keys are scoped — create one key per service with only the scopes it needs (checkout:write, refunds:write, products:write, …).

Incident response

If a key is leaked:

  1. Revoke it in the Dashboard immediately — all requests using it start returning 401.
  2. Create a new key and deploy it.
  3. Review the Developers → Request log for suspicious traffic.
  4. Contact support@southbill.com if funds were moved that you did not authorise.