Dokumentace
Vše, co potřebujete k integraci BezBrany do svého e-shopu. Kompletní API referenci najdete ve Swagger dokumentaci.
Rychlý start
- 1
Zaregistrujte se a vytvořte merchant účet
Po přihlášení vás provede onboarding — vyplníte základní údaje a přidáte bankovní účet s Fio API tokenem.
- 2
Vygenerujte si API klíč
V administraci v sekci Nastavení → API klíče. Pro testování použijte test klíč — platby lze simulovat bez skutečných peněz.
- 3
Vytvořte první platbu
Zavolejte API s klíčem v hlavičce
X-API-Key— odpověď obsahuje QR kód i platební kód pro widget.
REST API reference
| Metoda | Endpoint | Popis |
|---|---|---|
| POST | /api/v1/payments | Vytvoření platby (API klíč) |
| GET | /api/v1/payments/{paymentCode} | Stav platby (API klíč) |
| POST | /api/v1/payments/{paymentCode}/simulate-success | Simulace úspěchu (jen test klíče) |
| POST | /api/v1/widget/payments | Vytvoření platby z frontendu (veřejný pk_ klíč, hlavička X-Public-Key) |
| GET | /api/v1/widget/payments/{paymentCode} | Stav platby pro widget |
| GET | /api/v1/merchants/me/payments | Seznam plateb (Bearer token) |
| GET | /api/v1/merchants/me/payments/export | CSV export plateb (Bearer token) |
Příklad vytvoření platby:
curl -X POST https://api.bezbrany.cz/api/v1/payments \
-H "X-API-Key: VAS_API_KLIC" \
-H "Content-Type: application/json" \
-d '{
"amount": 100,
"currency": "CZK",
"orderNumber": "OBJ-2026-001",
"payer": { "contact": { "firstName": "Jan", "lastName": "Novák", "email": "jan@example.cz" } },
"items": [{ "name": "Tričko", "amount": 100, "quantity": 1 }]
}'Tarify a limity
Tarif obchodníka určuje, kolik plateb za měsíc se spáruje, kolik bankovních účtů lze připojit a zda se odesílají webhooky. Počítají se spárované (ne testovací) platby od začátku kalendářního měsíce. Podrobnosti a ceny najdete v ceníku.
| Tarif | Spárované platby / měsíc | Blokace nových plateb od | Bankovní účty | Webhooky | Branding |
|---|---|---|---|---|---|
| Free | 20 | 22 | 1 | ne | ano |
| Start | 300 | 330 | 2 | ano | ne |
| Pro | neomezeně | — | 10 | ano | ne |
Po dosažení měsíčního limitu máte ještě 10 % toleranci. Teprve potom vrátí vytvoření
nové platby (POST /api/v1/payments, POST /api/v1/widget/payments i ruční platba z nástěnky) HTTP 402 s kódem PLAN_LIMIT_REACHED. Už vytvořené platby se spárují vždy — zákazník, který
zaplatil, o nic nepřijde.
HTTP/1.1 402 Payment Required
Content-Type: application/json
{
"error": "Tarif Free má limit 20 spárovaných plateb za měsíc. Přejděte na vyšší tarif pro další platby.",
"code": "PLAN_LIMIT_REACHED",
"details": {
"limit": "matchedPayments",
"current": 22,
"max": 20,
"plan": "free",
"upgradeTo": "start"
},
"status": 402,
"path": "/api/v1/payments",
"timestamp": "2026-10-24T09:15:00.000Z"
}V details je limit (který limit
byl dosažen — matchedPayments nebo accounts), current (aktuální
využití), max (limit tarifu), plan (aktuálně platný tarif) a upgradeTo (doporučený vyšší tarif, u Pro null). Stejnou
chybu vrátí i přidání bankovního účtu nad limit tarifu (POST /api/v1/merchants/me/accounts).
Doporučené zpracování: zákazníkovi nezobrazujte technickou chybu — ukažte přívětivou zprávu a nabídněte náhradní způsob platby (např. ruční převod podle údajů v objednávce). Obchodníka upozorněte (e-mail, log, interní notifikace), ať může přejít na vyšší tarif v Nastavení → Tarif. Na 402 neopakujte request automaticky — dokud se tarif nezmění, skončí stejně.
const res = await fetch('https://api.bezbrany.cz/api/v1/payments', { method: 'POST', headers, body });
if (res.status === 402) {
const err = await res.json();
if (err.code === 'PLAN_LIMIT_REACHED') {
// 1) Zákazníkovi nezobrazujte technickou chybu — nabídněte náhradní platbu
// (ruční převod podle údajů z objednávky, dobírka…)
showManualPaymentInstructions(order);
// 2) Upozorněte obchodníka (e-mail, Slack, log) — err.details.upgradeTo
notifyMerchant(`Limit tarifu ${err.details.plan} vyčerpán (${err.details.current}/${err.details.max})`);
return;
}
}Widget integrace
Nejjednodušší způsob integrace — vložte skript a kontejner do HTML. Widget zobrazí QR kód, sleduje stav platby v reálném čase a po zaplacení zobrazí potvrzení.
<script src="https://api.bezbrany.cz/widget/v1.js"></script> <div data-bezbrany-widget data-payment-code="VAS_PLATEBNI_KOD"></div>
Podporované data-* atributy:
data-bezbrany-widget— označí kontejner widgetudata-payment-code— kód platby získaný z API
Alternativně lze widget inicializovat programaticky přes BezBranyWidget.init({ paymentCode, containerId, onPaymentSuccess }).
Odpověď GET /api/v1/widget/payments/{paymentCode} obsahuje pole branding (boolean). Na tarifu Free je true a widget i hostovaný
checkout zobrazí v patičce nenápadný odkaz „Platby přes BezBrany“. Pokud vykreslujete platbu
sami, můžete se podle pole řídit také.
Webhooky
Webhooky jsou dostupné v tarifech Start a Pro. Na
tarifu Free se po spárování platby webhook neodešle (ani při simulaci testovací platby) —
obchodník dostane jen e-mail o přijaté platbě. Stav platby pak ověříte přes GET /api/v1/payments/{paymentCode}.
Po dokončení platby odešleme POST request na vaši webhook URL (nastavíte v profilu
merchanta nebo per platba přes callback.notificationUrl). Payload:
{
"id": "b7c3e1a2-...",
"event": "payment.completed",
"createdAt": "2026-07-24T10:12:30.000Z",
"paymentId": "uuid",
"paymentCode": "A1B2C3D4E5F6A7B8",
"orderNumber": "OBJ-2026-001",
"status": "completed",
"amount": 100,
"currency": "CZK",
"metadata": {}
}Pole id je unikátní
pro každé doručení — použijte ho k deduplikaci (opakované doručení má stejné id). Podle event filtrujte typ
události; ignorujte neznámé typy, ať vás nerozbijí budoucí události.
Každý webhook je podepsán HMAC SHA-256 pomocí vašeho webhook secretu. Ověření podpisu:
// Hlavička: X-BezBrany-Signature: t=<timestamp>,v1=<podpis>
const crypto = require('crypto');
function verifyWebhook(rawBody, signatureHeader, secret) {
const parts = Object.fromEntries(
signatureHeader.split(',').map(p => p.split('='))
);
const signedPayload = `${parts.t}.${rawBody}`;
const expected = crypto.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(parts.v1)
);
}Při selhání doručení webhook opakujeme s exponenciálním rozestupem (1 min → 5 min → 30 min → 2 h).