Envelopify API
Verstuur echte brieven met postzegels vanuit je eigen software. Eén aanroep per brief. Wij printen, plakken echte postzegels en posten via bpost. bpost bezorgt binnen 2 tot 3 werkdagen na afgifte. Privacy: pdf’s en ontvangersgegevens worden standaard 30 dagen na posten gewist (klantkeuze 7 tot 90 dagen, dagelijkse opruiming). Daarna blijft de status beschikbaar, maar zijn ontvangersvelden leeg en geeft de pdf-download 404. Invulvelden worden alleen verwerkt in de brief, niet nog eens als losse gegevens bewaard.
https://envelopify.lovable.app/api/v1Bouw het met AI
Geef deze link aan je AI-assistent en laat hem de koppeling bouwen. De volledige documentatie staat als gewone tekst klaar (in het Engels).
Lees de documentatie van de Envelopify API op https://envelopify.lovable.app/llms-full.txt. Bouw in mijn app een koppeling die automatisch een brief verstuurt wanneer [gebeurtenis, bv. er een factuur aangemaakt wordt]. Roep de API enkel aan vanuit een serverfunctie, bewaar de API-sleutel als geheim (secret) en nooit in de browser. Begin met mijn testsleutel (test_...). Toon fouten uit de API in gewone taal aan de gebruiker en bewaar het id en de status van elke brief.Ook beschikbaar: openapi.json, developers.md en llms.txt.
In 5 minuten starten
- Sleutel aanmaken. Maak een gratis account, ga naar API-sleutels en kies Testsleutel maken. Vervang in de voorbeelden
test_JOUW_SLEUTELdoor je sleutel. - Testbrief sturen. De aanroep bij Brief versturen gebruikt onze voorbeeld-pdf en werkt zoals hij er staat. Er wordt niets geprint of aangerekend.
- Status opvragen. Neem het
iduit het antwoord en vraag de brief op metGET /api/v1/letters/{id}. Met/pdferachter zie je de pdf zoals wij hem printen. - Statusmeldingen instellen. Registreer een https-link met
POST /api/v1/webhooks, dan laten we je weten wanneer je brief geprint en gepost is. - Live gaan. Laad tegoed op in het portaal en klik bij je sleutel op Zet live. Nieuwe sleutels starten altijd in testmodus. Je sleutel zelf verandert niet.
Maak een gratis account om je sleutel te maken.
Inloggen met sleutel
Stuur je sleutel mee in elke aanvraag via de header Authorization: Bearer <sleutel>. Nieuwe sleutels starten in testmodus; je zet ze live in het portaal (API-sleutels, Zet live). De modus hangt aan de sleutel, niet aan het begin van de tekst. Met een sleutel in testmodus worden brieven nooit verstuurd of aangerekend; ze krijgen status received. We tonen een sleutel maar één keer. Bewaar hem als geheim op je server en nooit in browsercode. Een ontbrekende, ongeldige of ingetrokken sleutel geeft 401 unauthorized.
Gebeurtenis in wachtrijPOST/api/v1/flow-events
Voor een actieve herinneringsflow met een bewaarde ontvanger. Maakt een eenmalige reeks, niet onmiddellijk een brief. De dagelijkse verwerking gebruikt dezelfde prijs- en stopcontrole. Bij onvoldoende tegoed blijft de gebeurtenis in de wachtrij. event_key voorkomt dubbels per flow en sleutelmodus. Dagmaximum en wachttijd per ontvanger gelden ook in testmodus; testreeksen versturen en kosten niets en worden alleen door een beheerder getest.
| Veld | Type | Verplicht | Uitleg |
|---|---|---|---|
flow_id | tekst | ja | Id van actieve flow. |
contact_id | tekst | ja | Id van eigen ontvanger. |
event_key | tekst | ja | Unieke gebeurtenisreferentie, 1 tot 120 tekens. |
order_cents | getal | Bedrag voor flowvoorwaarde, standaard 0. | |
variables | object | Sjabloonvelden, enkel nodige gegevens. |
Voorbeeldverzoek
curl -X POST https://envelopify.lovable.app/api/v1/flow-events \
-H "Authorization: Bearer test_JOUW_SLEUTEL" \
-H "Content-Type: application/json" \
-d '{
"flow_id": "b1d1a7f7-3db2-43df-a896-bc9dc10c6029",
"contact_id": "b1d1a7f7-3db2-43df-a896-bc9dc10c6029",
"event_key": "herinnering-104",
"variables": {}
}'{
"status": "queued",
"test": true
}Brief versturenPOST/api/v1/letters
Maakt een brief aan. Geef precies één bron: een pdf (pdf_base64 of pdf_url) of een sjabloon (template_id of template_code) met variables. Bij een pdf geldt je accountkeuze: gratis adresblad vooraan of een wit adresvak op de eerste pagina met options.address_on_first_page. Klein gaat tot 50 g, middel tot 100 g en groot tot 350 g. Middel en groot zijn alleen beschikbaar met een bevestigde, geactiveerde meerprijs. Het adresblad telt mee voor het gewicht, niet voor de basisprijs. Antwoord 201 met id, status, prijs met opsplitsing (price_breakdown), aantal vellen (adresblad inbegrepen), uiterste postdatum volgens de snelheid en test. Met een testsleutel is de status received en post_date leeg. Een geweigerde brief geeft 422 met een foutcode en het letter_id.
| Veld | Type | Verplicht | Uitleg |
|---|---|---|---|
options.address_on_first_page | ja/nee | Voor opgeladen pdf: wit vast adresvak op de eerste pagina, zonder extra adresblad. Bedekte inhoud wordt wit. Zonder keuze geldt je accountstandaard (aanvankelijk adresblad). | |
options.corrections | object | Pdf-correcties: region {left,top,width,height} in mm op A4, window left/right/both, first_page, white_margins, flatten en a4_portrait. Zonder dit object geldt de bewaarde accountregel. Met region wordt het oude adresvak wit gemaakt. Je origineel blijft bewaard. | |
recipient.language | tekst | Optioneel: nl, fr, en of de. Kies de bewaarde sjabloonvariant voor deze taal; anders de basistekst. Zonder taal kiezen we volgens de Belgische postcode. | |
recipient.company | tekst | Optioneel. Bedrijfsnaam. | |
recipient.name | tekst | ja | Naam van de ontvanger. Naam of bedrijf is verplicht. |
recipient.street | tekst | ja | Straat. |
recipient.number | tekst | ja | Huisnummer. |
recipient.box | tekst | Optioneel. Busnummer. | |
recipient.postal_code | tekst | ja | Postcode. In België 4 cijfers. |
recipient.city | tekst | ja | Gemeente. |
recipient.country | tekst | Landcode (2 letters), standaard BE. Ook alle andere EU-landen (bv. NL, FR, DE), +€1,50 per brief, levertermijn 5 tot 10 werkdagen na verzending, geen express. | |
pdf_base64 | tekst | Pdf als base64, A4, maximaal 20 MB. | |
pdf_url | tekst | Rechtstreekse openbare https-link naar je pdf, maximaal 20 MB. Geen doorverwijzing, login, privaat netwerk of afwijkende poort. | |
template_id | tekst | Id van een sjabloon, in plaats van een pdf. | |
template_code | tekst | Of de code van een sjabloon, bv. herinnering. | |
variables | object | Waarden voor de velden in je sjabloon, bv. { "voornaam": "An" }. | |
options.flat | ja/nee | Ongevouwen in grote envelop, handmatig verwerkt. Alleen beschikbaar na activering. Meerprijs via /price. | |
options.registered | ja/nee | Aangetekend papier, alleen BE en standard/express, na activering. Opvolging: registered_tracking, registered_handed_in_at en tijdelijke registered_receipt_url. | |
options.color | ja/nee | Kleur. Standaard zwart-wit. Meerprijs per vel via /price. | |
options.duplex | ja/nee | Dubbelzijdig: twee pagina's per vel. Standaard enkelzijdig. | |
options.qr_tracking | ja/nee | Dynamische QR-code met scanmeting, +€0,05 per brief. | |
options.speed | tekst | Snelheid: `standard` (binnen 3 werkdagen verstuurd), `express` (zelfde werkdag als aangeleverd vóór 12:00, +€0,15 per brief, minimum €15,00 per dag) of `flex` (binnen 5 werkdagen, €-0,05 per brief). Standaard `standard`. | |
options.qr_target_url | tekst | Verplicht bij qr_tracking. Https-link waar de QR-code naartoe gaat. Achteraf aanpasbaar in het portaal. | |
enclosure_batch_id | tekst | Id van ontvangen drukwerk, zichtbaar in het portaal. Eén exemplaar per brief, alleen na activering en ontvangstcontrole. Annulering voor productie geeft voorraad terug. | |
reference | tekst | Optioneel. Jouw eigen referentie, bv. factuurnummer. | |
post_on | tekst | Optioneel: gekozen postdag (YYYY-MM-DD), een werkdag maximaal 90 kalenderdagen vooruit. Geen bezorgdatum. Tegoed wordt bij aanmaak gereserveerd door afboeking en bij annuleren vóór productie teruggestort. |
Voorbeeldverzoek
curl -X POST https://envelopify.lovable.app/api/v1/letters \
-H "Authorization: Bearer test_JOUW_SLEUTEL" \
-H "Idempotency-Key: factuur-2026-104" \
-H "Content-Type: application/json" \
-d '{
"recipient": {
"name": "An Peeters",
"street": "Meir",
"number": "12",
"postal_code": "2000",
"city": "Antwerpen"
},
"pdf_url": "https://envelopify.lovable.app/voorbeeld.pdf",
"options": {
"color": false
},
"reference": "factuur-2026-104"
}'{
"id": "b1d1a7f7-3db2-43df-a896-bc9dc10c6029",
"status": "scheduled",
"price_cents": 129,
"price_breakdown": {
"unit_price_cents": 129,
"tier": 1,
"tier_fixed": false,
"volume_30d": 120,
"letters_to_next_tier": 379,
"pages": 1,
"sheets": 1,
"address_sheet": true,
"total_sheets": 2,
"color": false,
"duplex": false,
"speed": "standard",
"destination": "BE",
"options": [],
"total_cents": 129,
"on_request": false,
"currency": "EUR",
"vat_included": false
},
"sheet_count": 2,
"post_date": "2026-11-13",
"free_trial": false,
"test": false
}Status opvragenGET/api/v1/letters/{id}
Geeft alle velden van de brief, de tijdstippen, de prijsopsplitsing, het aantal QR-scans (scan_count) en zodra hij gepost is een tijdelijke link naar de foto van de batch (batch_photo_url, 1 uur geldig).
Voorbeeldverzoek
curl -X GET https://envelopify.lovable.app/api/v1/letters/b1d1a7f7-3db2-43df-a896-bc9dc10c6029 \
-H "Authorization: Bearer test_JOUW_SLEUTEL"{
"id": "b1d1a7f7-3db2-43df-a896-bc9dc10c6029",
"tracking_code": "B1D1A7F7",
"reference": "factuur-2026-104",
"status": "posted",
"test": false,
"reject_reason": null,
"return_reason": null,
"recipient": {
"company": null,
"name": "An Peeters",
"street": "Meir",
"number": "12",
"box": null,
"postal_code": "2000",
"city": "Antwerpen",
"country": "BE"
},
"source": "pdf",
"color": false,
"duplex": false,
"qr_tracking": false,
"sheet_count": 2,
"price_cents": 129,
"price_breakdown": {
"unit_price_cents": 129,
"tier": 1,
"tier_fixed": false,
"volume_30d": 120,
"letters_to_next_tier": 379,
"pages": 1,
"sheets": 1,
"address_sheet": true,
"total_sheets": 2,
"color": false,
"duplex": false,
"speed": "standard",
"destination": "BE",
"options": [],
"total_cents": 129,
"on_request": false,
"currency": "EUR",
"vat_included": false
},
"speed": "standard",
"post_deadline": "2026-11-13",
"created_at": "2026-11-12T10:02:11Z",
"scheduled_at": "2026-11-12T10:02:11Z",
"printed_at": "2026-11-13T09:40:00Z",
"posted_at": "2026-11-13T16:02:11Z",
"returned_at": null,
"post_date": "2026-11-13",
"scan_count": 0,
"batch_photo_url": null
}Pdf bekijkenGET/api/v1/letters/{id}/pdf
Geeft de definitieve pdf zoals wij hem printen (application/pdf), met adresblad. Enkel voor je eigen brieven. Een geweigerde brief heeft geen pdf en geeft 404.
Voorbeeldverzoek
curl -X GET https://envelopify.lovable.app/api/v1/letters/b1d1a7f7-3db2-43df-a896-bc9dc10c6029/pdf \
-H "Authorization: Bearer test_JOUW_SLEUTEL"LijstGET/api/v1/letters
Geeft je recentste brieven, nieuwste eerst, in data. Is er meer, dan krijg je een next_cursor die je meegeeft als cursor.
| Filter | Type | Uitleg | |
|---|---|---|---|
status | tekst | Filter op status, bv. posted. | |
reference | tekst | Filter op je referentie. | |
from | tekst | Vanaf datum, bv. 2026-11-01. | |
to | tekst | Tot en met datum. | |
limit | getal | Standaard 25, maximaal 100. | |
cursor | tekst | Waarde van next_cursor. |
Voorbeeldverzoek
curl -X GET https://envelopify.lovable.app/api/v1/letters?status=posted&limit=50 \
-H "Authorization: Bearer test_JOUW_SLEUTEL"{
"data": [
{
"id": "b1d1a7f7-3db2-43df-a896-bc9dc10c6029",
"status": "posted",
"reference": "factuur-2026-104"
}
],
"next_cursor": "MjAyNi0xMS0xMlQxMDo..."
}AnnulerenDELETE/api/v1/letters/{id}
Annuleert een brief zolang de batch van die dag nog open is. Je tegoed wordt teruggestort en je krijgt de brief terug met status rejected. Is de batch al afgesloten, dan krijg je 409 cutoff_passed.
Voorbeeldverzoek
curl -X DELETE https://envelopify.lovable.app/api/v1/letters/b1d1a7f7-3db2-43df-a896-bc9dc10c6029 \
-H "Authorization: Bearer test_JOUW_SLEUTEL"Prijs berekenenPOST/api/v1/price
Berekent de prijs van een brief met je huidige schijf, zonder iets aan te maken of af te rekenen. Zelfde opties als een brief, maar met het aantal bedrukte pagina's in plaats van een pdf. Met address_sheet (standaard true) reken je het gratis adresblad mee voor het maximum aantal vellen, zoals bij een opgeladen pdf; zet het op false voor een sjabloonbrief. Niet-geactiveerde gewichtsklassen geven 422 weight_class_unavailable. Met options.address_on_first_page bereken je zonder extra adresblad.
| Veld | Type | Verplicht | Uitleg |
|---|---|---|---|
options.address_on_first_page | ja/nee | Voor opgeladen pdf: wit vast adresvak op de eerste pagina, zonder extra adresblad. Bedekte inhoud wordt wit. Zonder keuze geldt je accountstandaard (aanvankelijk adresblad). | |
options.flat | ja/nee | Ongevouwen in grote envelop, handmatig verwerkt. Alleen beschikbaar na activering. Meerprijs via /price. | |
options.registered | ja/nee | Aangetekend papier, alleen BE en standard/express, na activering. Opvolging: registered_tracking, registered_handed_in_at en tijdelijke registered_receipt_url. | |
enclosure_batch_id | tekst | Id van ontvangen drukwerk, zichtbaar in het portaal. Eén exemplaar per brief, alleen na activering en ontvangstcontrole. Annulering voor productie geeft voorraad terug. | |
pages | getal | ja | Aantal bedrukte pagina's (het adresblad niet meegerekend). |
address_sheet | ja/nee | Gratis adresblad meerekenen voor het maximum aantal vellen. Standaard true. | |
options.country | tekst | Bestemmingsland, standaard BE. Een ander EU-land voegt de toeslag EU toe. | |
options.color | ja/nee | Kleur, meerprijs per vel via /price. | |
options.duplex | ja/nee | Dubbelzijdig. | |
options.qr_tracking | ja/nee | QR-code met scanmeting. | |
options.speed | tekst | standard, express of flex. |
Voorbeeldverzoek
curl -X POST https://envelopify.lovable.app/api/v1/price \
-H "Authorization: Bearer test_JOUW_SLEUTEL" \
-H "Content-Type: application/json" \
-d '{
"pages": 3,
"address_sheet": true,
"options": {
"color": false,
"duplex": false,
"qr_tracking": false,
"speed": "standard"
}
}'{
"price_breakdown": {
"unit_price_cents": 129,
"tier": 1,
"tier_fixed": false,
"volume_30d": 120,
"letters_to_next_tier": 379,
"pages": 3,
"sheets": 3,
"address_sheet": true,
"total_sheets": 4,
"color": false,
"duplex": false,
"speed": "standard",
"destination": "BE",
"options": [
{
"code": "extra_sheets",
"label": "Extra vellen (2)",
"amount_cents": 20
}
],
"total_cents": 149,
"on_request": false,
"currency": "EUR",
"vat_included": false
}
}Sjablonen opvragenGET/api/v1/templates
Geeft je sjablonen in data.
Voorbeeldverzoek
curl -X GET https://envelopify.lovable.app/api/v1/templates \
-H "Authorization: Bearer test_JOUW_SLEUTEL"{
"data": [
{
"id": "6c1f...",
"name": "Herinnering",
"code": "herinnering",
"body": "Beste {{voornaam}}, ...",
"created_at": "2026-11-12T10:00:00Z"
}
]
}Sjabloon makenPOST/api/v1/templates
Maakt een sjabloon. Velden staan tussen dubbele accolades, bv. {{voornaam}}. Een code die al bestaat geeft 409 conflict.
| Veld | Type | Verplicht | Uitleg |
|---|---|---|---|
name | tekst | ja | Naam. |
code | tekst | ja | Unieke code: letters, cijfers, - en _. |
body | tekst | ja | Tekst met velden. |
Voorbeeldverzoek
curl -X POST https://envelopify.lovable.app/api/v1/templates \
-H "Authorization: Bearer test_JOUW_SLEUTEL" \
-H "Content-Type: application/json" \
-d '{
"name": "Herinnering",
"code": "herinnering",
"body": "Beste {{voornaam}},\n\nWe ontvingen nog geen betaling van {{bedrag}}."
}'Tegoed en prijzenGET/api/v1/balance
Geeft je huidig tegoed, je schijf, het aantal echte brieven in de voorbije 30 dagen, hoeveel brieven je nog verwijderd bent van de volgende korting en de prijslijst in cent, excl. btw: prijs per brief per schijf, meerprijzen voor opties en snelheden, en de regels voor express. free_letters_remaining is het aantal gratis proefbrieven dat je nog hebt.
Voorbeeldverzoek
curl -X GET https://envelopify.lovable.app/api/v1/balance \
-H "Authorization: Bearer test_JOUW_SLEUTEL"{
"credit_cents": 4950,
"free_letters_remaining": 3,
"company_verified": true,
"tier": 1,
"tier_fixed": false,
"volume_30d": 120,
"letters_to_next_tier": 380,
"unit_price_cents": 129,
"tiers": [
{
"tier": 1,
"from": 0,
"unit_price_cents": 129
},
{
"tier": 2,
"from": 500,
"unit_price_cents": 109
},
{
"tier": 3,
"from": 5000,
"unit_price_cents": 99
}
],
"options": {
"extra_sheet_cents": 10,
"qr_tracking_cents": 5
},
"speeds": [
{
"speed": "standard",
"name": "Standaard",
"amount_cents": 0,
"working_days": 3
},
{
"speed": "express",
"name": "Express",
"amount_cents": 15,
"working_days": 0
},
{
"speed": "flex",
"name": "Flex",
"amount_cents": -5,
"working_days": 5
}
],
"express": {
"minimum_cents": 1500,
"max_letters_per_day": 1000,
"before_hour": 12
},
"heavy_letter": {
"from_grams": 50,
"amount_cents": 60
},
"eu": {
"surcharge_cents": 150,
"countries": [
"AT",
"DE",
"FR",
"NL",
"..."
],
"delivery": "5 tot 10 werkdagen na verzending",
"express": false
},
"daily_letter_max": 1000,
"max_sheets": 8,
"currency": "EUR",
"vat_included": false
}Je account en bedrijfscontroleGET/api/v1/account
Geeft de gegevens van je eigen account. company_verified is true als je btw-nummer gecontroleerd is bij de Europese btw-controle (VIES) of door ons manueel. verification_status is verified, none (niet geverifieerd), pending (controle volgt later) of invalid. Bij een geverifieerd bedrijf staan ook official_name en official_address uit het officiële register. GET /balance bevat ook company_verified. De status kan je niet via de API wijzigen: dat gebeurt enkel na een echte controle in het portaal.
Voorbeeldverzoek
curl -X GET https://envelopify.lovable.app/api/v1/account \
-H "Authorization: Bearer test_JOUW_SLEUTEL"{
"customer_id": "4f6c2a1e-...",
"company": "Jouw Bedrijf",
"email": "post@jouwbedrijf.be",
"company_verified": true,
"verification_status": "verified",
"vat_number": "BE0123456749",
"official_name": "Jouw Bedrijf BV",
"official_address": "Kerkstraat 1\n2000 Antwerpen",
"checked_at": "2026-11-12T10:00:00Z",
"free_letters_remaining": 3
}Statusmeldingen opvragenGET/api/v1/webhooks
Toont je geregistreerde links en notification_groups. null betekent alle bestaande gebeurtenissen; een lijst beperkt meldingen tot gekozen groepen.
Voorbeeldverzoek
curl -X GET https://envelopify.lovable.app/api/v1/webhooks \
-H "Authorization: Bearer test_JOUW_SLEUTEL"{
"data": [
{
"id": "a3c2...",
"url": "https://jouwsite.be/hooks/envelopify",
"active": true,
"created_at": "2026-11-12T10:00:00Z"
}
]
}Statusmelding registrerenPOST/api/v1/webhooks
Registreert een https-link. Het antwoord bevat eenmalig een secret waarmee je de handtekening controleert.
| Veld | Type | Verplicht | Uitleg |
|---|---|---|---|
url | tekst | ja | Https-link die onze POST ontvangt. |
notification_groups | lijst | Optioneel: problems (review/rejected), sent (posted/registered_handed_in), undeliverable (returned), delivered (binnenkort, nog geen gebeurtenissen). Weglaten bewaart alle bestaande gebeurtenissen, [] ontvangt niets. Instelbaar per adres in het portaal. |
Voorbeeldverzoek
curl -X POST https://envelopify.lovable.app/api/v1/webhooks \
-H "Authorization: Bearer test_JOUW_SLEUTEL" \
-H "Content-Type: application/json" \
-d '{
"url": "https://jouwsite.be/hooks/envelopify"
}'{
"id": "a3c2...",
"url": "https://jouwsite.be/hooks/envelopify",
"active": true,
"created_at": "2026-11-12T10:00:00Z",
"secret": "whsec_..."
}Statusmelding verwijderenDELETE/api/v1/webhooks/{id}
Verwijdert een link.
Voorbeeldverzoek
curl -X DELETE https://envelopify.lovable.app/api/v1/webhooks/a3c2... \
-H "Authorization: Bearer test_JOUW_SLEUTEL"{
"id": "a3c2...",
"deleted": true
}Statusmeldingen
Bij elke gebeurtenis sturen we een POST naar al je actieve links met { event, letter_id, status, occurred_at, letter }. Elke melding draagt de header x-envelopify-signature: de HMAC-SHA256 (hex) van de ruwe inhoud met je geheim. Controleer die voor je de melding vertrouwt en antwoord met een 2xx-status. Lukt een melding niet (geen 2xx of geen antwoord binnen 8 seconden), dan proberen we ze tot 3 keer opnieuw (bij je volgende gebeurtenis en bij elke productieronde), dus 4 pogingen in totaal. Testbrieven blijven op received en geven geen meldingen.
| Gebeurtenis | Wanneer |
|---|---|
letter.scheduled | Ingepland voor een postdag, tegoed afgeboekt |
letter.review | Adres te controleren: wij kijken het na voor we printen |
letter.checked | Adres goedgekeurd na controle, ingepland |
letter.rejected | Afgekeurd na controle of geannuleerd vóór productie, teruggezet op je Envelopify-tegoed, niet uitbetaald |
letter.printed | Geprint en gefrankeerd |
letter.posted | Afgegeven bij bpost |
letter.returned | Teruggekomen als onbestelbaar |
letter.registered_handed_in | Aangetekend afgegeven, tracking en bewijs beschikbaar |
letter.scanned | QR-code gescand |
{
"event": "letter.posted",
"letter_id": "b1d1a7f7-3db2-43df-a896-bc9dc10c6029",
"status": "posted",
"occurred_at": "2026-11-13T16:02:12Z",
"letter": {
"id": "b1d1a7f7-3db2-43df-a896-bc9dc10c6029",
"tracking_code": "B1D1A7F7",
"reference": "factuur-2026-104",
"status": "posted",
"posted_at": "2026-11-13T16:02:11Z"
},
"created_at": "2026-11-13T16:02:12Z"
}Handtekening controleren:
// Node 18+ with Express: verify a webhook signature
import crypto from "node:crypto";
import express from "express";
const SECRET = "whsec_JOUW_GEHEIM"; // returned once when you create the webhook
const app = express();
app.post("/hooks/envelopify", express.raw({ type: "application/json" }), (req, res) => {
const expected = crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");
const given = req.get("x-envelopify-signature") ?? "";
const ok = given.length === expected.length && crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));
if (!ok) return res.status(401).end();
const { event, letter } = JSON.parse(req.body.toString("utf8"));
console.log(event, letter.id, letter.status);
res.status(200).end();
});
app.listen(3000);Dubbels vermijden
Stuur een header Idempotency-Key mee, bv. je factuurnummer. Stuur je dezelfde sleutel opnieuw, binnen 24 uur, dan krijg je de bestaande brief terug (status 200) in plaats van een nieuwe, en wordt er niets extra aangerekend. Na 24 uur geldt de sleutel als nieuw.
Statussen
| Status | Betekenis |
|---|---|
received | Ontvangen. Testbrieven blijven in deze status. |
scheduled | Ingepland voor een postdag, tegoed afgeboekt. |
review | Te controleren: de postcode bestaat niet of past niet bij de gemeente. Wij keuren het adres goed of af (tegoed terug). Zie address_warning. |
printed | Geprint en gefrankeerd. |
posted | Afgegeven bij bpost. |
returned | Teruggekomen als onbestelbaar. |
rejected | Geweigerd of geannuleerd. De reden staat in reject_reason. |
Foutcodes
Fouten hebben altijd de vorm { error: { code, message } }. De code (error.code) is altijd dezelfde, in elke taal: gebruik die in je logica. De melding (error.message) is in het Nederlands en mag je zo tonen aan je gebruiker.
| Code | HTTP | Betekenis |
|---|---|---|
sender_not_verified | 422 | Echte verzending, ook gratis proefpost, vereist een bevestigd e-mailadres en nagekeken bedrijf. Testmodus blijft beschikbaar. |
weight_class_unavailable | 422 | Gewichtsklasse niet geactiveerd of boven 350 gram. |
service_unavailable | 422 | De gekozen dienst of ontvangen foldervoorraad is nog niet beschikbaar. |
invalid_post_date | 422 | De gekozen postdag is geen geldige werkdag binnen 90 dagen. |
address_incomplete | 422 | Er ontbreekt een adresveld of de postcode klopt niet. |
insufficient_balance | 422 | Je tegoed volstaat niet. |
pdf_invalid | 422 | De pdf kan niet geopend worden, is geen pdf of is groter dan 20 MB. |
too_many_sheets | 422 | Meer dan 8 vellen, adresblad inbegrepen. |
express_limit | 422 | Meer dan 1.000 expressbrieven op één dag. |
country_not_supported | 422 | Land buiten België en de EU. |
express_not_available | 422 | Express kan niet naar andere EU-landen. |
daily_limit | 422 | Dagelijks maximum brieven bereikt (standaard 1.000, aanpasbaar op aanvraag). |
template_invalid | 422 | Sjabloon niet gevonden of er ontbreken velden. |
invalid_request | 400 | De aanvraag is niet geldig, bv. een ontbrekende bron of foute QR-link. |
unauthorized | 401 | Sleutel ontbreekt, is ongeldig of ingetrokken. |
not_found | 404 | Brief, webhook of eindpunt bestaat niet. Ook zonder sleutel. |
cutoff_passed | 409 | Annuleren kan niet meer, de brief is in productie. |
not_cancellable | 409 | Annuleren kan niet, bv. omdat de brief al geweigerd of geannuleerd is. |
conflict | 409 | Er bestaat al een sjabloon met deze code. |
rate_limited | 429 | Meer dan 60 aanvragen per minuut. Kijk naar de header Retry-After. |
server_error | 500 | Er liep iets mis aan onze kant. |
{
"error": {
"code": "address_incomplete",
"message": "Een Belgische postcode bestaat uit 4 cijfers"
}
}Limieten
Maximaal 60 aanvragen per minuut per sleutel. Daarboven krijg je 429 rate_limited en een header Retry-After. Pdf's mogen maximaal 20 MB zijn, een brief maximaal 350 g, middel en groot alleen na activering, maximaal 1.000 expressbrieven per dag en standaard maximaal 1.000 brieven per dag per account. De error.code is taalonafhankelijk en verandert niet; de message is Nederlands. CORS staat open, maar gebruik je sleutel nooit in browsercode.
Prijzen
Eén prijs per brief, excl. btw, alles inbegrepen: 1 vel (enkel- of dubbelzijdig, zwart-wit), envelop, echte postzegels en posten. Volgens je echte brieven in de glijdende voorbije 30 dagen, de nieuwe brief meegeteld, zonder maandreset: €1,29 onder 500, €1,09 vanaf 500, €0,99 vanaf 5.000. Kleur: +€0,08 per vel. Dubbelzijdig zonder meerprijs. Extra vel: +€0,10 per vel bovenop het eerste (dubbelzijdig zijn het twee pagina's per vel). QR-code met scanmeting: +€0,05. Het adresblad is gratis en telt niet mee voor de prijs. Een standaardbrief gaat tot 8 vellen in totaal, adresblad inbegrepen; grotere brieven kunnen op aanvraag via WhatsApp. Snelheden: Standaard (binnen 3 werkdagen verstuurd), Express (+€0,15, zelfde werkdag als aangeleverd vóór 12:00, anders de volgende werkdag) en Flex (€-0,05, binnen 5 werkdagen). Verstuurd betekent: door ons afgegeven aan bpost. bpost bezorgt binnen 2 tot 3 werkdagen na afgifte. Minimum express via de API: zijn je expressbrieven van één dag om 12:00 samen minder dan €15,00, dan houden we het verschil af met de regel "Aanvulling minimum express" in je bewegingen. Je tegoed moet dat bedrag bij het aanmaken al dekken. Maximum 1.000 expressbrieven per dag. Elk antwoord met een prijs bevat price_breakdown met unit_price_cents, tier, volume_30d, letters_to_next_tier, sheets, total_sheets, speed, options (lijst met code, label, amount_cents: extra_sheets, qr_tracking, express, flex) en total_cents. Gratis proefbrieven: elk nieuw account krijgt 3 echte brieven gratis, ook via de API met je sleutel in livemodus. Voorwaarden: snelheid standard, maximaal 3 vellen inhoud, bevestigd e-mailadres en maximaal 3 proefbrieven per ontvangstadres. Een brief die niet voldoet, wordt gewoon van je tegoed betaald. Een proefbrief heeft free_trial: true en price_cents: 0; annuleren voor productie geeft hem terug. GET /balance toont free_letters_remaining. Zware brief: boven 50 g komt er +€0,60 per brief bij (optie heavy_letter). Andere EU-landen: +€1,50 per brief (optie eu), levertermijn 5 tot 10 werkdagen na verzending, geen express. Adrescontrole: bij een Belgisch adres kijken we of de postcode bestaat en bij de gemeente past. Twijfel je antwoord niet weg: de brief krijgt status review met address_warning en wij keuren hem goed of af (tegoed terug).
Alle tarieven en de rekenhulp staan op de prijzenpagina.