Fiatside

Developers

Webhooks

Een webhook vertelt u dat een order van status is veranderd. Het vervangt het lezen van de order niet: het is een melding, geen bron van waarheid.

Gepubliceerd contract, nog niet open

Webhooks worden vandaag niet verzonden. Hun vorm, handtekening en herhalingsbeleid zijn hier vastgesteld en gepubliceerd, zodat uw ontvanger vooraf kan worden geschreven en getest.

01

Gebeurtenissen

Elke gebeurtenis heeft dezelfde envelop: een id, een type, een tijdstempel en een data-object. Abonneer u op de typen die u afhandelt en negeer de rest stilzwijgend — er zullen nieuwe typen worden toegevoegd, en een ontvanger die faalt op een onbekend type, breekt zichzelf.

Gebeurtenissen
TypeWat het betekent
order.createdDe order is aangemaakt en de koers is vastgelegd. Het stortingsadres is toegewezen.
order.deposit_detectedEen inkomende transactie wordt op het netwerk gezien, vóór bevestiging. Gebruik dit evenement om de gebruiker gerust te stellen, nooit om iets te leveren.
order.confirmingDe bevestigingsteller vordert. Uitgezonden bij elke stap, niet bij elk blok.
order.deposit_confirmedHet aantal bevestigingen dat door het netwerk wordt vereist, is bereikt.
order.underpaidHet ontvangen bedrag ligt onder het verwachte bedrag buiten tolerantie. De order is niet verloren: deze wacht op een keuze tussen bijstorten, doorgaan met het ontvangen bedrag of een terugbetaling.
order.overpaidHet ontvangen bedrag overschrijdt het verwachte bedrag. Het oorspronkelijke bedrag blijft tegen de vastgelegde koers; het overschot wordt apart afgehandeld.
order.payout_sentDe overschrijving is vertrokken via het betaalnetwerk. Let op: verzonden is niet ontvangen — de resterende vertraging hangt af van de bank van de begunstigde.
order.completedDe afwikkeling is bevestigd door het betaalnetwerk. Eindtoestand.
order.payout_failedHet betaalnetwerk heeft de overschrijving afgewezen of geretourneerd, met de reden. Er wordt geen automatische herpoging gedaan bij een retour van de bank: de oorzaak zit bijna altijd in de details.
order.refundedDe fondsen zijn teruggeboekt, uitsluitend naar het oorspronkelijke adres, na aftrek van netwerkvergoedingen.
02

De payload

Een constante envelop, ongeacht het type.

Voorbeeldjson
{
  "id": "evt_01J9ZQF3K8N2M4X7",
  "type": "order.payout_sent",
  "created": 1788356981,
  "data": {
    "reference": "K7Q4-M2XB",
    "state": "PAYOUT_SENT",
    "railId": "sepa_instant",
    "netMinor": 91228,
    "currency": "EUR",
    "sentAt": "2026-09-02T12:21:44Z"
  }
}
03

Handtekening

Elke levering bevat een handtekeningheader: een tijdstempel en een HMAC-SHA256 berekend over dat tijdstempel, een punt en de RUWE aanvraagbody.

Fiatside-Signaturehttp
Fiatside-Signature: t=<timestamp unix>,v1=<hex hmac-sha256>
Verificatie, Node.jstypescript
import { createHmac, timingSafeEqual } from 'node:crypto'

// IMPORTANT : le corps doit etre le corps BRUT, avant tout parsing JSON.
// Re-serialiser l'objet change l'ordre des cles et invalide la signature.
export function verify(rawBody: string, header: string, secret: string): boolean {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=') as [string, string]))
  const timestamp = Number(parts['t'])
  const signature = parts['v1']
  if (!timestamp || !signature) return false

  // Rejeu : une signature valide capturee hier ne doit pas etre rejouable aujourd'hui.
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false

  const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
  const a = Buffer.from(expected, 'hex')
  const b = Buffer.from(signature, 'hex')
  // Comparaison a temps constant : un === laisse fuiter la signature octet par octet.
  return a.length === b.length && timingSafeEqual(a, b)
}
  • Onderteken de ruwe body, vóór enig parsen. Het opnieuw serialiseren van het JSON-object verandert de volgorde van de sleutels en de witruimte: de handtekening komt niet meer overeen en u zult lang zoeken.
  • Vergelijk in constante tijd. Een ===-vergelijking stopt bij de eerste verschillende byte, waardoor een aanvaller de verwachte handtekening byte voor byte kan meten.
  • Wijs af buiten het 300-seconden tolerantievenster. Zonder die controle blijft een geldig verzoek dat gisteren is vastgelegd vandaag herspeelbaar.
  • Antwoord 200 vóór verwerking. Plaats de gebeurtenis in uw wachtrij en handel deze daarna af: lange verwerking veroorzaakt een time-out en dus een herhaling, ook al hebt u de gebeurtenis wel ontvangen.
04

Herhalingen en volgorde

Elke niet-2xx-status, of geen antwoord, veroorzaakt een herhaling volgens het onderstaande schema.

Herhalingen en volgorde
PogingVertraging
1onmiddellijk
230 s
32 min
410 min
51 h
66 h
  • De aankomstvolgorde is niet gegarandeerd. Een uitbetalingsgebeurtenis kan aankomen vóór de bevestigingsgebeurtenis die er logisch aan voorafgaat: vertrouw op de orderstatus, niet op de volgorde van ontvangst.
  • Hetzelfde evenement kan twee keer aankomen. Bewaar de evenement-id en negeer een id dat al is afgehandeld: idempotentie aan uw kant is uw verantwoordelijkheid, en het is gemakkelijk te realiseren.
  • Vertrouw nooit op bedragen in de payload om iets aan uw kant te crediteren. Lees de order opnieuw via de API: de payload zegt dat er iets is gebeurd, de API zegt precies wat.
  • Na de laatste poging wordt het evenement verwijderd en blijft het zichtbaar in uw evenementenlogboek. U kunt het handmatig opnieuw afspelen.