Gebruik de API vanuit je eigen server of persoonlijke app. Alle endpoints zijn alleen-lezen en gebruiken JSON. De basis-URL is https://donolink.nl/api/v1.
Ga naar Instellingen → Developer → API keys. Geef je integratie een naam en kies een vervaldatum.
Kopieer de sleutel eenmalig en bewaar hem als DONOLINK_API_KEY in de geheime configuratie van je server.
Doe je eerste request. Zonder filters ontvang je maximaal 50 events, nieuwste eerst.
Stuur je sleutel bij ieder request mee in de Authorization-header. Een sessiecookie, queryparameter of overlay-token geeft geen toegang tot deze API.
Authorization: Bearer dl_live_YOUR_SECRET_KEY
Je kiest een geldigheid van 30, 90 of 365 dagen. Je kunt maximaal 10 actieve sleutels hebben en één sleutel per minuut aanmaken. DonoLink bewaart alleen een SHA-256-hash; de volledige sleutel is alleen direct na aanmaken zichtbaar.
Gebruik een eigen sleutel per integratie. Maak voor rotatie eerst een nieuwe sleutel aan, werk je app bij en trek daarna de oude in. Een ingetrokken of verlopen sleutel werkt niet meer bij het volgende request.
Iedere sleutel heeft de vaste scope activity:read en is aan jouw account gebonden. Er zijn geen schrijf-, betaal- of beheerrechten. OAuth voor apps met meerdere klanten is nog niet beschikbaar.
Endpoints
GET/api/v1/me
Controleer welke streamer bij je sleutel hoort en wanneer de sleutel verloopt. Alleen het publieke profiel, de scope en sleutelmetadata worden teruggegeven.
Lees de gezamenlijke feed van DonoLink-donaties en opgeslagen platformevents. Het account wordt uitsluitend uit de API key bepaald.
Parameter
Beschrijving
limit
Aantal events per pagina: 1 tot 100, standaard 50.
order
desc (standaard) voor nieuwste eerst, asc voor oudste eerst en doorlopend pollen. Sortering op recorded_at, daarna intern record-ID en bron.
type
Optioneel: donation, follow, subscription, giftsub, cheer of raid. Eén soort per request.
platform
Optioneel: donolink, twitch, kick, youtube, tiktok of een importbron: tipeeestream, streamlabs, streamelements, kofi, csv. Eén bron per request.
since
Optioneel, inclusief. UTC ISO 8601, bijvoorbeeld 2026-09-07T00:00:00Z. Filtert recorded_at, het moment van opslaan.
until
Optioneel, exclusief. Zelfde datumformaat als since. Houd deze grens vast tijdens een historische export.
cursor
Neem pagination.next_cursor ongewijzigd over. De cursor is ondertekend en gebonden aan je account, filters en sortering. limit mag veranderen.
Onbekende of dubbele parameters leveren HTTP 400 op. Geef geen account-ID, sleutel of PocketBase-filter in de URL mee.
Eventformaat
Elk event heeft een stabiel id met don_ of evt_ als voorvoegsel. Gebruik dit id om dubbele verwerking na een retry te voorkomen.
type
unit
Beschrijving
donation
cents
Donatie via DonoLink of een opgeslagen platformdonatie, zoals YouTube Super Chat.
follow
none
Nieuwe volger. value is 0.
subscription
months
Abonnement. value bevat het opgeslagen aantal maanden.
giftsub
subscriptions
Cadeau-abonnementen. value is het aantal.
cheer
bits / diamonds
Bits; voor TikTok is de eenheid diamonds. Geen donatieomzet.
raid
viewers
Raid. value is het opgeslagen aantal kijkers.
actor.name is de opgeslagen schermnaam of null. message is tekst of null. occurred_at is de donatiedatum; bij platformevents is alleen de opslagtijd bekend. recorded_at is altijd de opslagtijd en bepaalt de paginering. Alle tijden zijn UTC ISO 8601.
value bevat bij donation het oorspronkelijke bedrag in gehele centen, currency de valuta. refunded_amount_cents bevat voor DonoLink het terugbetaalde bedrag, anders null. Donaties met status paid worden getoond, inclusief geïmporteerde historie met de importbron als platform. Volledig terugbetaalde en betwiste donaties ontbreken. Dit is een activity feed, geen financieel grootboek.
Platformevents zijn beschikbaar voor zover DonoLink ze via een actieve koppeling heeft ontvangen en opgeslagen. Er wordt geen geschiedenis van vóór de koppeling bij het platform opgehaald. Er is geen gegarandeerde bewaartermijn; verwijderde records zijn niet meer opvraagbaar. Testalerts staan niet in deze feed.
Historie & live feed
Voor een export: gebruik order=asc met vaste since- en until-grenzen. Verwerk data en vraag met next_cursor de volgende pagina op zolang has_more true is. Er is geen limiet op het aantal historische pagina’s, wel een requestlimiet.
Een lege pagina behoudt je bestaande cursor. Zonder eerdere cursor en zonder events is next_cursor null. Cursors bevatten geen API key, maar behandel ze als ondoorzichtige waarden. Na een filterwijziging begin je zonder cursor.
Voor je IRL-app: gebruik order=asc, een vaste since en geen until. Sla de cursor pas op nadat je events hebt verwerkt. Poll ongeveer iedere 5 seconden; bij has_more mag je direct door naar de volgende pagina. Er is in v1 geen WebSocket- of webhookendpoint.
// Node.js: run on your server. Keep the key out of frontend bundles.
const base = new URL('https://donolink.nl/api/v1/activity');
base.searchParams.set('order', 'asc');
base.searchParams.set('limit', '100');
// Persist both this fixed starting point and the returned cursor.
base.searchParams.set('since', '2026-09-07T00:00:00Z');
let cursor = await loadCheckpoint();
for (;;) {
const url = new URL(base);
if (cursor) url.searchParams.set('cursor', cursor);
const response = await fetch(url, {
headers: { Authorization: 'Bearer ' + process.env.DONOLINK_API_KEY },
signal: AbortSignal.timeout(15000)
}).catch(() => null);
if (!response || response.status === 429 || response.status >= 500) {
const seconds = Number(response?.headers.get('Retry-After') || 60);
await new Promise(r => setTimeout(r, seconds * 1000));
continue;
}
if (!response.ok) throw new Error('DonoLink API: ' + response.status);
const page = await response.json();
// Implement these storage functions in your app.
// Process idempotently by event.id, then save the checkpoint.
for (const event of page.data) await processOnce(event.id, event);
if (page.pagination.next_cursor) {
cursor = page.pagination.next_cursor;
await saveCheckpoint(cursor);
}
if (!page.pagination.has_more)
await new Promise(r => setTimeout(r, 5000));
}
De feed leest de huidige opgeslagen records en is geen onveranderlijke snapshot of gegarandeerde exactly-once eventbus. Wijzigingen in betaalstatus kunnen eerder getoonde records laten verdwijnen. Gebruik idempotente verwerking, retries en indien nodig een overlappende herlezing voor herstel.
Limieten & fouten
Maximaal 120 requests per 60 seconden per account, gedeeld door alle sleutels. Daarnaast geldt 300 requests per 60 seconden per IP-adres. HTTP 429 en 503 bevatten Retry-After: 60. Wacht die tijd en probeer met dezelfde cursor opnieuw.
HTTP
code
Beschrijving
400
invalid_parameter / invalid_cursor
Herstel je parameters of begin opnieuw zonder ongeldige cursor.
401
invalid_api_key
Sleutel ontbreekt, is ongeldig, verlopen of ingetrokken.
403
account_unavailable
Het account is niet beschikbaar of niet geverifieerd.
429
rate_limit_exceeded
Te veel requests. Respecteer Retry-After.
503
temporarily_unavailable
Tijdelijke storing. Toegang wordt ook geweigerd als de gedeelde limiter niet beschikbaar is.
{
"error": {
"code": "invalid_api_key",
"message": "API key is invalid, expired or revoked.",
"request_id": "request-uuid"
}
}
Iedere response heeft X-Request-Id; foutresponses bevatten ook error.request_id. Geef dit ID en het tijdstip door bij een supportvraag. Deel nooit je sleutel, Authorization-header of volledige requestlogs. Gebruik GET voor data. HEAD en OPTIONS zijn beschikbaar voor HTTP-controles; schrijfmethodes leveren 405 op.
Veilig integreren
Gebruik HTTPS. Zet sleutels nooit in URL’s, Git, browsercode, localStorage, analytics of logbestanden. API-responses gebruiken Cache-Control: private, no-store. De API biedt geen cross-origin browsertoegang.
In een persoonlijke native app voer je je eigen sleutel in en bewaar je die in Keychain of Android Keystore. Bouw je een app voor anderen, gebruik dan een backend met gescheiden geheimen per gebruiker. Embed nooit een gedeelde sleutel in de appbinary.
De API geeft alleen schermnamen, berichten, eventwaarden en beperkte profielgegevens terug. E-mailadressen, betaalmethodes, Stripe-ID’s, platformtokens en beheerinstellingen worden niet gedeeld. Behandel namen en berichten als persoonsgegevens en bewaar alleen wat je integratie nodig heeft.
Bij een gelekte sleutel: trek hem meteen in onder Instellingen → Developer en maak een nieuwe aan. Ingetrokken en verlopen sleutels, geblokkeerde accounts en verwijderde accounts krijgen geen toegang.
Namen en berichten zijn onbetrouwbare invoer. Render ze als tekst, nooit als HTML of uitvoerbare code. Automatiseer geen betaalacties op basis van deze feed.