Naar inhoud

Eigen widgets en de kanaal-API

Met een Eigen widget bouw je je eigen boekingservaring. Je stelt de regels in Bookingmood in, en je eigen code gebruikt de kanaal-API om beschikbaarheid op te halen en boekingen aan te nemen.

Pre-release: de kanaal-API kan nog veranderen, ook op manieren die bestaande code laten stoppen met werken, en deze pagina behandelt misschien nog niet alles. JavaScript-pakketten voor de API zijn nog niet beschikbaar. Test je integratie goed voordat je erop vertrouwt.

Een eigen widget maken

Eigen widgets zijn beschikbaar vanaf het Booking-abonnement.

  • Ga naar Kanalen en klik op Nieuw kanaal.

  • Kies Eigen widget, voer een titel in en selecteer de objecten die erbij horen.

  • Om boekingen aan te nemen, zet je Interactie op Boeken.

  • Kopieer de Publieke sleutel.

Een eigen widget heeft geen weergave-instellingen. Hij bepaalt alleen wat de API teruggeeft en toestaat: de objecten, hoe geboekte, gesloten en openstaande data worden getoond, of gasten kunnen boeken, wat er na het boeken gebeurt, of beoordelingen beschikbaar zijn en, als je wilt, een wachtwoord.

De Publieke sleutel is de ID van de widget. Die is openbaar, dus je kunt hem in een browser gebruiken. Zet nooit een Bookingmood-API-sleutel in browsercode: die zijn geheim.

Verzoeken

De basis-URL is https://www.bookingmood.com/api/public/v1. Verzoeken zijn toegestaan vanaf elke website.

const channelId = "YOUR_PUBLISHABLE_KEY";
const baseUrl = "https://www.bookingmood.com/api/public/v1";

const response = await fetch(`${baseUrl}/channels/${channelId}`);
const { availability, channel, organization, products } = await response.json();
Methode en padWat het doet
GET /channels/:idHet kanaal, de organisatie en objecten ervan, en hun beschikbaarheid. Telt als een weergave van het kanaal.
GET /channels/:id/availabilityAlleen de beschikbaarheid. Voeg product_ids per object één keer toe om het tot die objecten te beperken.
POST /channels/:id/calendars/syncSynchroniseert de geïmporteerde kalenders van objecten.
GET /channels/:id/reviewsBeoordelingen van een object, als het kanaal beoordelingen toont.
GET /channels/:id/couponsKortingscodes op code. Voeg codes per code één keer toe.
POST /channels/:id/coupons/verifyControleert of een kortingscode gebruikt kan worden.
POST /channels/:id/cart/validateControleert of een winkelwagen geboekt kan worden en wat die kost.
POST /channels/:id/cart/checkoutBoekt een winkelwagen.
POST /channels/:id/accessWisselt het wachtwoord van het kanaal in voor een token.
GET /bookings/:idDe status en betalingen van een boeking.
POST /bookings/:id/payHaalt een betaallink op voor een openstaande boeking.
POST /bookings/:id/cancelAnnuleert een openstaande boeking.

Een verblijf boeken

Boekingen lopen via een winkelwagen, met daarin een of meer verblijven:

const cart = {
  coupon_codes: [],
  items: [
    {
      id: "stay-1", // Your own ID, to match results to items
      product_id: "UNIT_ID",
      interval: { start: "2027-03-01", end: "2027-03-08" },
      occupancy: { CAPACITY_GROUP_ID: 2 },
      form_values: { SERVICE_ID: "Arriving around 16:00" },
    },
  ],
};
  • interval: data als YYYY-MM-DD. Een verblijf per nacht eindigt op de dag dat gasten vertrekken. Een verblijf per dag eindigt de dag na de laatste dag.

  • occupancy: het aantal gasten per capaciteitsgroep, met de ID uit organization.capacity_groups.

  • form_values: de antwoorden op het boekingsformulier, met de ID uit de services van het object.

1. De winkelwagen valideren

Valideer de winkelwagen voordat je een gast om gegevens of een betaling vraagt. Het resultaat laat zien of elk verblijf geboekt kan worden en wat het kost. Bedragen zijn in centen.

const response = await fetch(`${baseUrl}/channels/${channelId}/cart/validate`, {
  body: JSON.stringify(cart),
  headers: { "Content-Type": "application/json" },
  method: "POST",
});
{
  "items": [
    {
      "availabilityMatch": true,
      "id": "stay-1",
      "occupancyMatch": true,
      "price": {
        "currency": "EUR",
        "deposit": 0,
        "lines": [],
        "subtotal": 70000,
        "tax": 6300,
        "total": 76300
      },
      "valid": true
    }
  ],
  "valid": true
}

2. Afrekenen

Stuur de winkelwagen mee, met optioneel een weergavevaluta in currency en een taal in language. Afrekenen maakt een echte boeking aan en geeft een 201-antwoord. De winkelwagen kan nog steeds worden geweigerd, omdat de beschikbaarheid kan veranderen nadat je hebt gevalideerd.

const response = await fetch(`${baseUrl}/channels/${channelId}/cart/checkout`, {
  body: JSON.stringify({ cart, currency: null, language: "en-US" }),
  headers: { "Content-Type": "application/json" },
  method: "POST",
});
const { booking_id, payment_expiry_timestamp, payment_url, reference, secret } =
  await response.json();

Als payment_url niet null is, stuur je de gast daarheen om te betalen. Na het betalen gaan gasten naar wat de instelling Na boeking van de widget aangeeft.

3. Later betalen of annuleren

Gebruik de secret van de boeking als bearer-token voor de routes onder /bookings/:id. Die geeft toegang tot de status en betalingen van de boeking, zonder gegevens van de gast. Deel hem alleen met de gast die de boeking heeft gemaakt.

const response = await fetch(`${baseUrl}/bookings/${booking_id}/pay`, {
  body: JSON.stringify({ language: "en-US" }),
  headers: {
    Authorization: `Bearer ${secret}`,
    "Content-Type": "application/json",
  },
  method: "POST",
});
const { payment_url } = await response.json();

Betalen en annuleren werken alleen zolang een boeking op de betaling wacht. Anders krijg je 409 terug met de code booking_not_pending. Een geslaagde annulering geeft 204 terug, zonder inhoud.

Kortingscodes

POST /channels/:id/coupons/verify krijgt de code, de product_ids in de winkelwagen en de al ingevoerde current_codes. Het result is een van deze waarden:

ResultaatBetekenis
VALIDDe code kan worden gebruikt.
INVALIDDe code bestaat niet of geldt niet voor deze objecten.
STACK_NOT_ALLOWEDEen code die al is ingevoerd, kan niet met andere worden gecombineerd.
LIMIT_REACHEDDe winkelwagen heeft al 5 codes, het maximum.

Beoordelingen

GET /channels/:id/reviews heeft een product_id nodig. Je kunt een limit van 1 tot 1000 (de standaardwaarde) toevoegen, en een order: most-recent (de standaardwaarde), highest-rating of lowest-rating.

Geïmporteerde kalenders synchroniseren

Als je objecten kalenders importeren, stuur je { "product_ids": [...] } naar POST /channels/:id/calendars/sync om ze bij te werken. Het antwoord bevat de totalen. Met Accept: application/x-ndjson krijg je in plaats daarvan een regel JSON zodra elke kalender klaar is.

Een verzoek start na 40 seconden geen nieuwe kalenders meer. Als remaining in het resultaat boven de 0 ligt, stuur je nog een verzoek.

Kanalen met een wachtwoord

Als de widget een wachtwoord heeft, geeft elk kanaalverzoek 401 terug met de code password_required, totdat de bezoeker is ingelogd:

const response = await fetch(`${baseUrl}/channels/${channelId}/access`, {
  body: JSON.stringify({ password }),
  headers: { "Content-Type": "application/json" },
  method: "POST",
});
const { expiresAt, token } = await response.json();

Stuur het token als Authorization: Bearer <token> mee met volgende verzoeken. Het is een week geldig, en expiresAt geeft die tijd in milliseconden.

Fouten en limieten

Fouten hebben een code en een message:

{
  "code": "channel_not_found",
  "details": null,
  "hint": null,
  "message": "No channel found with this ID"
}
StatusCodeBetekenis
400BM400Het verzoek past niet bij het schema van de route. details geeft aan wat er mis is.
400product_not_listedEen object in het verzoek hoort niet bij dit kanaal.
400checkout_failedDe winkelwagen kan niet worden geboekt. message geeft de reden.
400password_not_setHet kanaal heeft geen wachtwoord.
401password_requiredHet kanaal heeft een toegangstoken nodig.
401invalid_passwordHet wachtwoord is onjuist.
403channel_inactiveHet abonnement van de organisatie staat dit kanaal niet toe.
403channel_not_bookableDe Interactie van het kanaal staat niet op Boeken.
403reviews_disabledHet kanaal toont geen beoordelingen.
404channel_not_foundEr is geen kanaal met deze ID.
404booking_not_foundDe boeking bestaat niet, of de secret klopt niet.
409booking_not_pendingDe boeking wacht niet op een betaling.
429rate_limitedTe veel verzoeken.

Per IP-adres zijn de limieten 300 verzoeken per minuut per kanaal, 60 per minuut naar de boekingsroutes en 10 per minuut om kortingscodes te controleren. Ook het aantal wachtwoordpogingen is beperkt.

Laatst gewijzigd 6 november 2026


Neem de controle over je boekingen. Bouw een bedrijf dat van jou is.

Sluit je aan bij 1200+ onafhankelijke vakantieverhuurbedrijven die Bookingmood gebruiken om hun directe boekingen te vergroten en een sterkere band met hun gasten op te bouwen.

Start je gratis 14-daagse proefperiode