Pro vývojáře

Barberyo API

Napojte si rezervace na vlastní web, pokladnu nebo aplikaci. Stejná pravidla jako v našem formuláři — otevírací doba, uzavírky, předstih i rezervační okno platí i přes API.

Začátek za pět minut

  1. 1

    Zapněte API

    V administraci pod Nastavení → API a widget přepněte veřejné API.

  2. 2

    Vydejte klíč

    Pojmenujte ho podle toho, kde poběží, a dejte mu jen rozsahy, které opravdu potřebuje.

  3. 3

    Zkopírujte klíč

    Uvidíte ho jedinkrát. V databázi zůstane jen otisk, takže vám ho nikdo nepřečte — ani my.

  4. 4

    Zavolejte /shop

    Když se vrátí profil podniku, je hotovo a můžete stavět.

První požadavek
curl https://barberyo.onrender.com/api/v1/shop \
  -H "X-Api-Key: bko_vas_klic"

Ověření

Klíč se posílá v hlavičce X-Api-Key. Kdo umí jen Authorization, může použít Bearer — funguje obojí.

Klíč nese podnik, takže se v cestách nikde neuvádí, kterého podniku se týkají. Jedním klíčem se nedá dostat k datům jiného podniku.

Obě varianty hlavičky
X-Api-Key: bko_vas_klic

Authorization: Bearer bko_vas_klic
Klíč do prohlížeče patří jen s omezením na doménu. Ve widgetu je klíč vidět v HTML. Proto mu v administraci nastavte povolené domény a dejte mu jen CatalogRead, AvailabilityRead a BookingWrite. Klíč se čtením zákazníků do prohlížeče nepatří nikdy.

Oprávnění

Každý klíč má vyjmenované rozsahy. Dělí se podle toho, co špatně použitý klíč způsobí — čtení ceníku je neškodné, zápis rezervace zabírá čas v rozvrhu a čtení zákazníků vydá osobní údaje.

Rozsah Co dovolí Citlivost
CatalogRead Podnik, služby, barbeři, otevírací doba. nízká
AvailabilityRead Volné termíny na den i po dnech v měsíci. nízká
BookingWrite Zakládání a rušení rezervací. střední
BookingRead Výpis rezervací podniku i se jmény zákazníků. střední
ReviewRead Veřejná hodnocení. Soukromá zpětná vazba se nevrací nikdy. nízká
CustomerRead Zákazníci, kontakty, útrata. vysoká

Cesty

Vše je pod /api/v1. Odpovědi jsou JSON v kódování UTF-8, časy v místním čase podniku bez zóny (2026-09-12T09:30).

Chyby

Chyba má vždycky stejný tvar: strojově čitelný kód a věta pro člověka. Tu druhou jde zákazníkovi ukázat tak, jak je.

Tvar chyby
{
  "error": {
    "code": "insufficient_scope",
    "message": "Klíč nemá oprávnění BookingWrite."
  }
}
Kód HTTP Kdy nastane
missing_key 401 Chybí hlavička s klíčem.
invalid_key 401 Klíč neplatí, byl zneplatněn, nebo má podnik vypnuté API.
origin_not_allowed 403 Klíč má omezené domény a volání přišlo odjinud.
insufficient_scope 403 Klíč nemá potřebný rozsah.
rate_limited 429 Vyčerpaný limit za minutu.
invalid_date 400 Datum není ve tvaru YYYY-MM-DD.
not_found 404 Zdroj nepatří podniku z klíče, nebo neexistuje.
booking_failed 422 Termín je obsazený, zavřeno, nebo mimo rezervační okno.

Limity

Každý klíč má vlastní limit požadavků za minutu (výchozí 60, nastavitelný 10–600). Po jeho překročení přijde 429 a hlavička Retry-After říká, za kolik sekund to zkusit znovu.

Stav limitu posílá API u každé odpovědi, takže na 429 nemusíte čekat — podle X-RateLimit-Remaining poznáte, jak blízko jste, a podle X-RateLimit-Reset, za kolik sekund se okno obnoví.

Hlavičky u každé odpovědi
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 43

Vypnutí API v administraci zneplatní všechny klíče podniku okamžitě — není to jen přepínač widgetu.

Volání z prohlížeče

API se dá volat přímo ze stránky podniku. U klíče si vyplňte povolené domény — pak se s ním dá volat jen odtud a nikdo ho nezneužije na cizím webu. Prohlížeč se nejdřív zeptá metodou OPTIONS; na tu API odpoví samo. Z nepovolené domény vrátí 403 origin_not_allowed a odpověď schválně nedostane hlavičku pro prohlížeč — cizí stránka se tak nedozví ani to, jestli je klíč platný. V síťovém panelu ten stav uvidíte.

Klíč je ale ve stránce vidět každému návštěvníkovi. Do prohlížeče proto patří jen klíč se čtením katalogu a volných termínů; zakládání rezervací nechte na svém serveru, ať se k němu nikdo cizí nedostane. Volání ze serveru hlavičku Origin neposílá, takže ho seznam domén neomezuje.

Webhooky

Místo opakovaného dotazování si nechte poslat zprávu, když se něco stane. Adresa musí být https — zpráva nese jména a časy zákazníků.

BookingCreatedBookingConfirmedBookingCancelledBookingRescheduledBookingCompletedReviewCreated

Každá zpráva nese hlavičky X-Barberyo-Event, X-Barberyo-Delivery a podpis X-Barberyo-Signature. Podpis je HMAC-SHA256 z těla zprávy s tajemstvím odběru — ověřte ho, adresa webhooku bývá veřejně dosažitelná.

Ověření podpisu (Node.js)
const crypto = require('crypto');

function overit(telo, podpis, tajemstvi) {
  const ocekavany = 'sha256=' + crypto
    .createHmac('sha256', tajemstvi)
    .update(telo)
    .digest('hex');

  // Porovnání v konstantním čase — obyčejné === prozradí délku shody.
  return crypto.timingSafeEqual(
    Buffer.from(ocekavany),
    Buffer.from(podpis));
}

Odpovězte kódem 2xx. Neúspěch se opakuje pětkrát s rostoucím odstupem (1, 4, 9 a 16 minut). Odběr, který selže dvacetkrát po sobě, se vypne.

Widget na vlastní web

Nejrychlejší cesta, jak se napojit — jeden řádek a lidé se objednají přímo na vašem webu. Rezervace i tak spadne do Barberya.

Vložení na stránku
<!-- kam se má tlačítko vložit (nepovinné) -->
<div data-barberyo-button></div>

<script src="https://barberyo.onrender.com/widget/v1/barberyo.js"
        data-shop="gentleman-barber-praha"
        data-key="bko_vas_klic"
        data-label="Objednat se"
        defer></script>

Tlačítko se vloží tam, kde je značka data-barberyo-button, jinak hned za skript. Okno jde otevřít i z vlastního kódu přes Barberyo.open().

Měření dokončené rezervace
window.addEventListener('barberyo:booked', function (e) {
  console.log('Rezervace číslo', e.detail.id);
  // sem patří měření konverze
});

Kuchařka

Tři nejčastější úlohy celé.

Vykreslit kalendář na měsíc
const hlavicky = { 'X-Api-Key': 'bko_vas_klic' };

const odpoved = await fetch(
  'https://barberyo.onrender.com/api/v1/availability/month' +
  '?serviceId=1&month=2026-10',
  { headers: hlavicky });

const { days } = await odpoved.json();

// days: [{ date: "2026-10-01", freeSlots: 12 }, ...]
days.filter(d => d.freeSlots > 0).forEach(d => zvyraznit(d.date));
Založit rezervaci
curl -X POST https://barberyo.onrender.com/api/v1/bookings \
  -H "X-Api-Key: bko_vas_klic" \
  -H "Content-Type: application/json" \
  -d '{
        "barberId": 3,
        "serviceId": 1,
        "start": "2026-10-14T09:30",
        "customerName": "Jan Novák",
        "customerEmail": "[email protected]",
        "customerPhone": "+420777123456"
      }'
Přijmout webhook (Express)
app.post('/barberyo', express.raw({ type: 'application/json' }), (req, res) => {
  const podpis = req.header('X-Barberyo-Signature');

  if (!overit(req.body, podpis, process.env.BARBERYO_SECRET)) {
    return res.sendStatus(401);
  }

  const udalost = req.header('X-Barberyo-Event');
  const data = JSON.parse(req.body);

  if (udalost === 'BookingCancelled') { uvolnitVKalendari(data.id); }

  // Odpovězte hned. Vlastní práci nechte na frontě — čekáme deset vteřin.
  res.sendStatus(200);
});

Změny

Verze je v cestě. Do v1 přibývají jen nová pole a nové cesty — nic, co už funguje, se v ní nezmění. Zásah, který by něco rozbil, dostane v2 a v1 poběží dál.

Co přibylo
  • GET /api/v1/bookings/{id} — detail jedné rezervace. Na tuhle adresu odkazovala hlavička Location po založení rezervace, ale samotná cesta chyběla.
  • Stav limitu v hlavičkách X-RateLimit-Limit, X-RateLimit-Remaining a X-RateLimit-Reset u každé odpovědi.
  • Volání z prohlížeče (CORS) podle povolených domén u klíče.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.