Naar de inhoud
iRoamly Shop

Webhookmeldingen

Gebruik webhooks om de resultaten van QR-codelevering en verlengingen in je applicatie te ontvangen.

Webhookmeldingen

Inleiding

Gebruik webhooks om de resultaten van QR-codelevering en verlengingen in je applicatie te ontvangen.

Wat is een webhook?

iRoamly stuurt webhookmeldingen voor QR-codelevering en verlengingsresultaten. Elke webhook gebruikt HTTPS en bevat een JSON-payload. Met webhooks kun je:

  • QR-codegegevens ontvangen nadat een inwisselcode is omgezet of een directe QR-codeaankoop is voltooid.
  • Verlengingsresultaten via een webhook ontvangen: esim.renewal.success wanneer de QR-code van de verlenging klaar is, esim.renewal.failed wanneer de verlengingsbestelling bij de upstreamprovider mislukt.

Als je endpoint niet met een 2xx-status antwoordt, doet iRoamly in totaal maximaal 5 afleverpogingen: de eerste direct, daarna nieuwe pogingen na 30 seconden, 2 minuten, 3 minuten en 5 minuten.

Stappen om een webhook te ontvangen

Met deze stappen ontvang je realtime events in je app:

  • Maak een lokaal endpoint om verzoeken te ontvangen
  • Registreer je webhook-endpoint in het iRoamly Shop-dashboard onder Ontwikkelaars > Webhookmeldingen

1. Maak een lokaal endpoint om verzoeken te ontvangen

Maak in je lokale applicatie een nieuwe route die POST-verzoeken kan accepteren.

Je kunt bijvoorbeeld een API-route toevoegen in Next.js:

typescript
import type { NextApiRequest, NextApiResponse } from 'next';

export default (req: NextApiRequest, res: NextApiResponse) => {
  if (req.method === 'POST') {
    const payload = req.body;
    console.log(payload);
    res.status(200);
  }
};

Antwoord bij ontvangst van een event met HTTP 200 OK, zodat iRoamly weet dat het event is afgeleverd.

2. Registreer je webhook-endpoint voor ontwikkeling

Registreer je openbaar bereikbare HTTPS-URL in het iRoamly Shop-dashboard.

Je kunt een tunnel naar je localhost-server maken met een tool zoals ngrok.

Pagina Webhookmeldingen in het Dashboard met het paneel “Nieuwe webhook” geopend: veld Webhook-URL en status Ingeschakeld / Uitgeschakeld

3. Test of je webhook-endpoint goed werkt

Zet een test-inwisselcode om naar een QR-code of doe een directe QR-codeaankoop om te controleren of je webhook-endpoint het event ontvangt.

Webhookmeldingen

Eventtypes

Lijst met ondersteunde eventtypes en hun payloads.

EventtypeVerzonden wanneerOpmerkingen
esim.qrcodeEen inwisselcode is omgezet naar een QR-code, of een directe QR-codeaankoop is voltooid.Ongewijzigd. isrenew is altijd 0.
esim.renewal.successEen verlenging is gelukt en de QR-code van de verlengingscode is klaar.Nieuw. Bij verlengingen wordt geen esim.qrcode meer verzonden.
esim.renewal.failedEen verlenging is mislukt omdat de upstreambestelling niet kon worden geplaatst.Nieuw. Wordt alleen verzonden bij mislukte upstreambestellingen.

Levering

Elk event wordt op dezelfde manier geleverd: een POST-verzoek met een JSON-body naar elk endpoint dat op het event is geabonneerd. Elke 2xx-response geldt als afgeleverd; anders wordt het opnieuw geprobeerd, met in totaal maximaal 5 pogingen (de eerste direct, daarna na 30 seconden, 2 minuten, 3 minuten en 5 minuten). Elk verzoek bevat deze headers:

HeaderBeschrijvingType
X-Webhook-EventEventtype: esim.qrcode, esim.renewal.success of esim.renewal.failed.String
X-Webhook-DeliveryLeverings-ID.String
X-Webhook-TimestampTijdstip waarop het verzoek is ondertekend, in Unix-seconden.String
X-Webhook-Signaturesha256= gevolgd door de hex-HMAC-SHA256 van de onbewerkte requestbody.String
X-Webhook-Signature-V2v1= gevolgd door de hex-HMAC-SHA256 van "{timestamp}.{body}". Tijdens een rotatie van het geheim bevat de header meerdere door komma’s gescheiden v1=-waarden.String

Zie Webhookverzoeken verifiëren voor het controleren van de handtekeningen.

esim.qrcode

Gegevens over de eSIM-QR-code die worden teruggegeven na het inwisselen of kopen van de eSIM-QR-code.

Voorbeeld van de requestbody

json
{
	"code": 0,
	"data": {
		"activation_code": "CD112885573C49DDA42F64C905B925F4",
		"code": "UtTpoKCe769u2tt",
		"create_at": "2025-09-01 11:34:30",
		"isrenew": 0,
		"order_id": "ESIM202509021134343282",
		"plan_name": "Japan-eSIM-3GB-15 Days-Daily",
		"qrcode": "https://www.iroamly.com/qrcode/20250901/xSQfryvOWo0QUhsGcbpeTm9wWYfGu9BQ.png",
		"qrcode_content": "LPA:1$rsp1.cmlink.com$CD352885573C49DDA42F64C905B925F4",
		"sm_dp_address": "rsp1.cmlink.com"
	},
	"event_type": "esim.qrcode"
	}
Webhookmeldingen

esim.renewal.success

Wordt verzonden wanneer een verlenging slaagt: zodra de upstreamprovider de downloadgegevens van de verlengingsbestelling teruggeeft, genereert het systeem de QR-code voor de verlengingscode en wordt de status 2 (Ingewisseld).

Requestheaders

X-Webhook-Event:esim.renewal.success

Het verzoek bevat ook X-Webhook-Delivery, X-Webhook-Timestamp, X-Webhook-Signature en X-Webhook-Signature-V2, net als elk event (zie Eventtypes).

Voorbeeld van de requestbody

json
{
	"code": 0,
	"data": {
		"activation_code": "CD112885573C49DDA42F64C905B925F4",
		"code": "RnB7xTq2Lm9pQaZ",
		"create_at": "2026-10-28 09:12:41",
		"download_url": "LPA:1$rsp1.cmlink.com$CD352885573C49DDA42F64C905B925F4",
		"iccid": "8944501234567890123",
		"iscouldrenewal": 1,
		"isrenew": 1,
		"plan_name": "Japan-eSIM-3GB-15 Days-Daily",
		"qrcode": "https://www.iroamly.com/qrcode/20261028/xSQfryvOWo0QUhsGcbpeTm9wWYfGu9BQ.png",
		"qrcode_content": "LPA:1$rsp1.cmlink.com$CD352885573C49DDA42F64C905B925F4",
		"renew_order_id": "TG202610280912410001",
		"renewal_father_code": "UtTpoKCe769u2tt",
		"sm_dp_address": "rsp1.cmlink.com"
	},
	"event_type": "esim.renewal.success"
}

Velden

VeldBeschrijvingType
codeAltijd 0.Int
event_typeesim.renewal.successString
data.codeDe nieuwe inwisselcode die voor deze verlenging is gegenereerd. Gebruik hem met QR-code opvragen (qrcodeQuery) of om opnieuw te verlengen.String
data.renewal_father_codeDe oorspronkelijke (bovenliggende) inwisselcode die is verlengd.String
data.renew_order_idID van de upstreamverlengingsbestelling.String
data.plan_nameNaam van de verlengingsbundel.String
data.qrcodeURL van de QR-codeafbeelding.String
data.qrcode_contentLPA-string; kan direct worden geïmporteerd.String
data.sm_dp_addressSM-DP+-adres.String
data.activation_codeActiveringscode.String
data.iccidICCID. Kan leeg zijn.String
data.download_urlDownloadstring die door de upstreamprovider is teruggegeven.String
data.create_atAanmaaktijd: servertijd, in het formaat YYYY-MM-DD HH:mm:ss.String
data.isrenewAltijd 1.Int
data.iscouldrenewalOf de nieuwe inwisselcode opnieuw kan worden verlengd: 1 - kan worden verlengd 2 - kan niet worden verlengd 3 - verlopenInt
Webhookmeldingen

esim.renewal.failed

Wordt verzonden wanneer een verlenging mislukt: de upstreamprovider beantwoordt de verlengingsbestelling met een andere code dan 0000, of het verzoek aan de provider mislukt.

(Let op: een ontbrekende of late callback van de upstreamprovider activeert dit event niet. Stel een time-out in en val terug op het opvragen van de code — zie Verlengingsevents afhandelen.)

Requestheaders

X-Webhook-Event:esim.renewal.failed

Het verzoek bevat ook X-Webhook-Delivery, X-Webhook-Timestamp, X-Webhook-Signature en X-Webhook-Signature-V2, net als elk event (zie Eventtypes).

Voorbeeld van de requestbody

json
{
	"code": -1,
	"data": {
		"code": "RnB7xTq2Lm9pQaZ",
		"create_at": "2026-10-28 09:12:41",
		"error_msg": "TuGe_RenewOrderEx RespCode: 9999",
		"isrenew": 1,
		"plan_name": "Japan-eSIM-3GB-15 Days-Daily",
		"renewal_father_code": "UtTpoKCe769u2tt"
	},
	"event_type": "esim.renewal.failed"
}

Velden

VeldBeschrijvingType
codeAltijd -1.Int
event_typeesim.renewal.failedString
data.codeDe verlengingscode die voor deze poging is gegenereerd. Hij is niet ingericht en heeft geen QR-code.String
data.renewal_father_codeDe oorspronkelijke (bovenliggende) inwisselcode die verlengd had moeten worden.String
data.plan_nameNaam van de verlengingsbundel.String
data.error_msgFoutmelding van de upstreamprovider, voor probleemoplossing.String
data.create_atAanmaaktijd: servertijd, in het formaat YYYY-MM-DD HH:mm:ss.String
data.isrenewAltijd 1.Int
Webhookmeldingen

Verlengingen en esim.qrcode

Verlengingen worden niet meer als esim.qrcode geleverd; dat event wordt verzonden voor omzettingen naar QR-codes en directe QR-codeaankopen. Vergeleken met de payload van esim.qrcode:

  • event_type en de header X-Webhook-Event zijn esim.renewal.success of esim.renewal.failed, en isrenew is 1.
  • data.code is de nieuwe inwisselcode die door de verlenging is aangemaakt; de verlengde code is data.renewal_father_code.
  • esim.renewal.success voegt renew_order_id, renewal_father_code, iscouldrenewal, download_url en iccid toe en heeft geen order_id.
  • Een mislukte verlenging wordt gemeld met esim.renewal.failed, met code -1 op het hoogste niveau en de upstreamfout in data.error_msg.
Webhookmeldingen

Eventabonnementen

Nieuwe endpoints zijn standaard op alle drie de events geabonneerd. Bestaande endpoints ontvangen esim.renewal.success en esim.renewal.failed automatisch — er hoeft niets te worden gewijzigd.

Webhookmeldingen

Verlengingsevents afhandelen

  • Maak je handler idempotent. Bij een nieuwe poging kan hetzelfde event meer dan eens worden geleverd; ontdubbel daarom op X-Webhook-Delivery of op event_type + data.code, en negeer events die je al hebt verwerkt.
  • Gebruik een terugvaloptie met time-out. Als binnen een redelijke tijd noch esim.renewal.success noch esim.renewal.failed binnenkomt, vraag de code dan op met de query-API (bijvoorbeeld QR-code opvragen) in plaats van aan te nemen dat de verlenging is mislukt.
  • Gebruik esim.renewal.failed niet om over terugbetalingen te beslissen. Het meldt alleen dat de upstreambestelling is mislukt; of en wanneer de credits worden teruggestort, wordt apart bepaald. Betaal je klanten dus niets terug op basis van dit event.
Webhookmeldingen

Webhookverzoeken verifiëren

Verifieer de iRoamly-handtekening op webhookverzoeken.

Hoe verifieer je de iRoamly-handtekening?

De iRoamly-handtekening wordt meegestuurd in de header X-Webhook-Signature van het webhookverzoek, als sha256= gevolgd door de hex-gecodeerde handtekening. De handtekening wordt gegenereerd met het HMAC-SHA256-algoritme, met het webhookgeheim als sleutel en de onbewerkte requestbody (precies zoals ontvangen, vóór het parsen van JSON) als bericht.

Voorbeeld van een webhookheader

json
{
'X-Webhook-Signature': 'sha256=dd7bdd2cf1f6bac6e171c6c508c157b7cd3cc1fd196394277fb59ba0bdd9b87b'
}

Je webhookgeheim vind je in het Dashboard onder Ontwikkelaars > Webhookmeldingen.

Pagina Webhookmeldingen in het Dashboard: webhook-endpoint met de URL en het ondertekeningsgeheim (Tonen), en de leveringsgeschiedenis

Je kunt het volgende codefragment gebruiken om de handtekening te genereren:

typescript
import * as crypto from 'crypto';

  generateSignature(payload: string, secret: string): string {
    const computedSignature = crypto
      .createHmac('sha256', secret)
      .update(payload)
      .digest('hex');
    return 'sha256=' + computedSignature;
  }

In het codefragment hierboven is payload de onbewerkte requestbody en secret het webhookgeheim. Vergelijk de gegenereerde handtekening (inclusief het voorvoegsel sha256=) met de waarde van de header X-Webhook-Signature om de verificatie te voltooien.

Handtekening met tijdstempel (X-Webhook-Signature-V2)

Elk verzoek bevat ook X-Webhook-Signature-V2: v1= gevolgd door de hex-gecodeerde HMAC-SHA256, met hetzelfde webhookgeheim, van {timestamp}.{body} — de waarde van de header X-Webhook-Timestamp, een punt en de onbewerkte requestbody.

Nadat je het webhookgeheim hebt geroteerd, blijft het oude geheim 24 uur geldig. In die periode wordt X-Webhook-Signature nog met het oude geheim ondertekend, en bevat X-Webhook-Signature-V2 één waarde per geheim, gescheiden door komma’s (v1=<old>,v1=<new>): accepteer het verzoek als een van de waarden overeenkomt.