Hjelp / API
Headless API
Bygg billettkjøp på egen nettside. Brumio håndterer lager, ordre og betaling — kjøperen omdirigeres til SagaPay, og billetter sendes på e-post som vanlig.
Slik starter du
- Logg inn og gå til Innstillinger.
- Slå på Headless API og opprett en hemmelig nøkkel (bare eieren).
- Kall API-et fra serveren deres — aldri eksponer nøkkelen i nettleseren.
Autentisering
Send nøkkelen som Authorization: Bearer br_sk_… eller header X-Brumio-Api-Key. Nøkkelen må være aktiv og API-et må være slått på for arrangøren.
Testnøkler starter med br_sk_test_, live med br_sk_live_ (følger testmodus på kontoen).
Endepunkter
GET https://www.brumio.no/api/v1/integr/events/{orgSlug}/{eventSlug}
Publisert arrangement med billettyper, salgsstatus og gebyrregel — samme data som på Brumio-siden deres. Feltet seatingEnabled er true når kjøp krever valgte seter.
GET https://www.brumio.no/api/v1/integr/events/{orgSlug}/{eventSlug}/seats
Setekart for arrangementet: sections (seksjon, billettype, pris) og seats (rad, nummer, seksjon, status: available eller taken). Oppdater kartet jevnlig (f.eks. hvert 30. sekund) mens kjøperen velger — solgte og holdte seter er taken.
404 når arrangementet ikke har setekart. Samme JSON som offentlig GET /api/v1/events/{eventId}/seats, men autentisert og med CORS for tillatte domener.
POST https://www.brumio.no/api/v1/integr/promo/check
Body: { "eventId": "…", "code": "RABATT" }. Sjekk rabattkode før checkout.
POST https://www.brumio.no/api/v1/integr/checkout
Oppretter ordre og returnerer payment.embed for self-hosted checkout med SagaPay Online SDK (sdkUrl, publicKey, providerOrderId, nonce). Last sdkUrl og kall SurfboardOnlineSDK.initialiseOnlineSDK({ publicKey, orderId: providerOrderId, nonce }). SagaPay godtar bare domenet som er godkjent for butikken (www.brumio.no). Krever header Idempotency-Key (16–100 tegn) — samme nøkkel gir samme svar ved retry.
Body følger samme skjema som offentlig checkout, pluss valgfritt successUrl og cancelUrl (må ligge på tillatte domener i API-innstillinger). Etter betaling sendes kjøperen til successUrl?orderId=…&t=… i stedet for Brumio-kvittering.
Redirect kjøperen til betaling: bruk paymentPageUrl fra responsen (eller payment.redirectUrl når den finnes og peker til SagaPay). Ikke send kjøperen til brumioReceiptUrl eller payment.embed.receiptUrl før betaling er fullført — det er kvittering/retur-URL etter betaling. Gratis ordre (totalOre: 0) er allerede betalt; da kan dere bruke brumioReceiptUrl.
Setekart: når seatingEnabled er true, må hver linje ha seatIds (én UUID per sete; quantity må matche). Maks 6 seter per ordre. Uten setekart sendes bare ticketTypeId og quantity.
GET https://www.brumio.no/api/v1/integr/orders/{orderId}
Status, kjøper, arrangement og receipt (linjer, rabatt, gebyr, mva) når ordren er betalt eller venter. Bruk dette på deres takk-side (server-til-server med API-nøkkel) for å vise kvittering på egen nettside. ticketPageUrl peker til billettene når de er klare.
Betaling og sikkerhet
Dere lagrer eller sender aldri kortnummer. Enklest flyt: etter POST /checkout, send kjøperen til paymentPageUrl på brumio.no — der fullføres SagaPay-betalingen. Alternativt kan dere bygge egen side med payment.embed, men SDK-et må da kjøre på domenet SagaPay har godkjent (typisk www.brumio.no). Med successUrl kommer kjøperen tilbake til siden deres etter betaling med orderId og t; hent kvitteringsdata fra ordre-endepunktet. Billett sendes på e-post som vanlig.
Hvis dere kaller API-et fra nettleseren (ikke anbefalt), må nettstedets origin stå under tillatte domener i innstillingene. Server-til-server-kall trenger ikke CORS-oppsett.
Eksempel (Node, uten setekart)
const res = await fetch('https://www.brumio.no/api/v1/integr/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + process.env.BRUMIO_SECRET_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
eventId: '…',
buyer: {
name: 'Ola Nordmann',
email: 'ola@example.com',
phone: '900 00 000',
addressLine1: 'Storgata 1',
postalCode: '0150',
city: 'Oslo',
},
lines: [{ ticketTypeId: '…', quantity: 2 }],
acceptTerms: true,
}),
});
const { paymentPageUrl } = await res.json();
window.location.href = paymentPageUrl; // betaling på brumio.noEksempel (Node, setekart)
Hent arrangement, deretter setekart. Bygg deres eget kart (eller liste) ut fra seats — vis bare seter med status: "available". Send valgte id-verdier i checkout.
const headers = {
Authorization: 'Bearer ' + process.env.BRUMIO_SECRET_KEY,
};
const orgSlug = 'mitt-selskap';
const eventSlug = 'sommerkonsert';
const eventRes = await fetch(
`https://www.brumio.no/api/v1/integr/events/${orgSlug}/${eventSlug}`,
{ headers },
);
const { event } = await eventRes.json();
const { id: eventId, seatingEnabled } = event;
if (!seatingEnabled) {
// Vanlig checkout med ticketTypeId + quantity (se eksempel over)
throw new Error('Forventet setekart');
}
const seatsRes = await fetch(
`https://www.brumio.no/api/v1/integr/events/${orgSlug}/${eventSlug}/seats`,
{ headers },
);
const { sections, seats } = await seatsRes.json();
const pick = seats.filter((s) => s.status === 'available').slice(0, 2);
if (pick.length < 2) throw new Error('Ikke nok ledige seter');
// Grupper per billettype (samme type kan ha flere seter på én linje)
const byType = new Map();
for (const s of pick) {
const cur = byType.get(s.ticketTypeId) ?? { ticketTypeId: s.ticketTypeId, seatIds: [] };
cur.seatIds.push(s.id);
byType.set(s.ticketTypeId, cur);
}
const lines = [...byType.values()].map((l) => ({
ticketTypeId: l.ticketTypeId,
quantity: l.seatIds.length,
seatIds: l.seatIds,
}));
const checkoutRes = await fetch('https://www.brumio.no/api/v1/integr/checkout', {
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
eventId,
buyer: { name: 'Ola Nordmann', email: 'ola@example.com', phone: '900 00 000' },
lines,
acceptTerms: true,
successUrl: 'https://example.com/takk',
}),
});
const { payment } = await checkoutRes.json();
// sections[0].label, pick[0].row + pick[0].number — vis valgte plasser i UI