Naar de inhoud
Documentatie
Nederlands
De applicatie openen

Webhooks

De NovaFisko-gebeurtenissen op uw server ontvangen, een eindpunt aanmaken en testen, de leveringspogingen begrijpen en het logboek raadplegen.

Een webhook is een HTTP-aanroep die NovaFisko naar uw server stuurt wanneer er een gebeurtenis plaatsvindt: een geïmporteerde factuur, een gevalideerde boeking, een gevalideerde btw-aangifte. U hoeft de API niet meer te bevragen om te weten of er iets nieuws is.

De webhooks worden ingesteld op het niveau van het kantoor en dekken al zijn dossiers. Alleen de beheerders en de managers van het kantoor kunnen ze beheren.

Werking

  1. U registreert een URL en kiest de gebeurtenissen die u wilt ontvangen.
  2. NovaFisko bezorgt u een ondertekeningsgeheim, één enkele keer.
  3. Bij elke gebeurtenis plaatst NovaFisko een levering in de wachtrij en stuurt daarna, uiterlijk binnen de minuut, een ondertekende POST-request naar uw URL.
  4. Uw server verifieert de handtekening en antwoordt met een status 2xx in minder dan 10 seconden.
  5. Bij een mislukking probeert NovaFisko het opnieuw met een oplopende wachttijd.

Een eindpunt aanmaken

curl -X POST https://api.novafisko.com/v1/firms/Fd7hQ2mN8sXa/webhooks \
  -H "Authorization: Bearer $NOVAFISKO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://erp.atelier.example/hooks/novafisko",
    "description": "ERP Atelier, production",
    "events": ["document.imported", "document.booked", "entry.posted"],
    "is_active": true
  }'
Veld Verplicht Beschrijving
url ja Ontvangst-URL, max. 500 tekens. HTTPS verplicht in productie
description nee Vrije omschrijving, max. 190 tekens
events ja Lijst van gebeurtenissen, of ["*"] voor alle
is_active nee Standaard true

Antwoord 201:

{
  "webhook": {
    "id": 14,
    "url": "https://erp.atelier.example/hooks/novafisko",
    "description": "ERP Atelier, production",
    "events": ["document.imported", "document.booked", "entry.posted"],
    "is_active": true,
    "secret_hint": "whsec_…x9Qd",
    "last_delivery_at": null,
    "last_status": null,
    "created_at": "2026-10-05T09:20:00+00:00",
    "updated_at": "2026-10-05T09:20:00+00:00"
  },
  "secret": "whsec_Zp3kV8nQ1bT6yR0mW4sH7cJ2dL9fA5gE1uXox9Qd"
}
Let op

Het secret wordt alleen bij het aanmaken teruggegeven. Sla het onmiddellijk op in uw secrets manager. De volgende leesbewerkingen tonen alleen secret_hint, de laatste vier tekens ervan.

Beperkingen voor de URL

  • Het schema moet https zijn.
  • De URL mag geen inloggegevens bevatten (https://user:pass@...).
  • De host mag niet localhost zijn, niet eindigen op .local of .internal en niet naar een privé-, loopback- of gereserveerd adres verwijzen.
  • Omleidingen worden niet gevolgd.

Een geweigerde URL antwoordt 422 met de code webhook_url_refused. Een kantoor kan maximaal 20 eindpunten registreren (webhook_limit_reached).

De eindpunten beheren

Actie Request Antwoord
Oplijsten GET /v1/firms/{firm}/webhooks {"data": [...]}
Wijzigen PATCH /v1/firms/{firm}/webhooks/{id} {"webhook": {...}}
Verwijderen DELETE /v1/firms/{firm}/webhooks/{id} 204
Testen POST /v1/firms/{firm}/webhooks/{id}/test 202 en de levering
Logboek GET /v1/firms/{firm}/webhooks/{id}/deliveries Gepagineerde lijst
Catalogus GET /v1/webhooks/events Lijst van de gebeurtenissen en beschrijvingen

Een eindpunt pauzeren zonder het te verwijderen:

curl -X PATCH https://api.novafisko.com/v1/firms/Fd7hQ2mN8sXa/webhooks/14 \
  -H "Authorization: Bearer $NOVAFISKO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'

Een gebruiker die lid is van het kantoor maar de vereiste rol niet heeft, krijgt 403. Een gebruiker van buiten het kantoor krijgt 404.

De ontvangen request

POST /hooks/novafisko HTTP/1.1
Host: erp.atelier.example
Content-Type: application/json
User-Agent: NovaFisko-Webhooks/1.0
X-Novafisko-Event: entry.posted
X-Novafisko-Delivery: 90412
X-Novafisko-Signature: t=1791191400,v1=5f2b8c1e0a7d4f6b9c3e2a1d8f7b6c5a4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b

{"id":"evt_01jb6z3m8q2v7k4n5p9r0s1t2w","event":"entry.posted","api_version":"v1","created_at":"2026-10-05T09:23:20Z","firm":{"public_token":"Fd7hQ2mN8sXa","name":"Fiduciaire Exemple"},"company":{"public_token":"k3Jd9fPq2LmX","name":"Le Comptoir Montois SRL"},"data":{"id":1842,"reference":"ACH 2026/000212"}}
Header Inhoud
X-Novafisko-Signature Tijdstempel en HMAC-SHA256-handtekening. Zie Handtekeningen verifiëren
X-Novafisko-Event Naam van de gebeurtenis
X-Novafisko-Delivery Identificator van de levering, identiek bij elke poging
User-Agent NovaFisko-Webhooks/1.0

Envelop

Alle gebeurtenissen delen dezelfde envelop.

Veld Beschrijving
id Unieke identificator van de gebeurtenis, met het prefix evt_. Gebruik hem om te ontdubbelen
event Naam van de gebeurtenis
api_version v1
created_at Datum van de gebeurtenis, ISO 8601 in UTC
firm public_token en naam van het kantoor
company public_token en naam van het dossier, of null voor een kantoorgebeurtenis
data Inhoud eigen aan de gebeurtenis

Gebeurtenissen

Gebeurtenis Trigger
document.imported Een document komt in het dossier binnen (importmodule, Novadesko, Peppol)
document.booked Een document wordt geboekt
entry.posted Een boeking wordt gevalideerd
entry.reversed Een boeking wordt tegengeboekt
bank.transaction_imported Een bankverrichting wordt geïmporteerd
vat.declaration_validated Een btw-aangifte wordt gevalideerd
fiscal_year.closed Een boekjaar wordt afgesloten
peppol.status_changed De Peppol-status van het dossier verandert
third_party.created Een derde wordt aangemaakt
third_party.updated Een derde wordt gewijzigd
webhook.test Testverzending, op aanvraag

De onderstaande voorbeelden tonen het veld data van elke gebeurtenis. De envelop is weggelaten.

document.imported en document.booked

{
  "id": 7741,
  "source": "novafisko",
  "origin": "novafisko",
  "type": "purchases",
  "direction": "purchase",
  "is_credit_note": false,
  "number": "F-2026-0918",
  "document_date": "2026-10-02",
  "due_date": "2026-11-01",
  "third_party_id": 41,
  "third_party_name": "Brasserie des Collines SA",
  "third_party_vat": "BE0999900134",
  "currency": "EUR",
  "amount_net": "1250.00",
  "amount_vat": "262.50",
  "amount_gross": "1512.50",
  "status": "pending",
  "journal_entry_id": null
}

Voor document.booked heeft status de waarde booked en bevat journal_entry_id de identificator van de boeking.

entry.posted en entry.reversed

{
  "id": 1842,
  "reference": "ACH 2026/000212",
  "journal_code": "ACH",
  "fiscal_year_code": "2026",
  "number": 212,
  "entry_date": "2026-10-02",
  "due_date": "2026-11-01",
  "label": "Brasserie des Collines SA",
  "document_reference": "F-2026-0918",
  "status": "posted",
  "origin": "manual",
  "third_party_id": 41,
  "total_debit": "1512.50",
  "total_credit": "1512.50",
  "lines_count": 3,
  "reversed_entry_id": null,
  "reversed_by_entry_id": null
}

Voor entry.reversed heeft de gebeurtenis betrekking op de oorspronkelijke boeking: status heeft de waarde reversed en reversed_by_entry_id verwijst naar de tegenboeking. De tegenboeking zelf veroorzaakt haar eigen entry.posted, met reversed_entry_id ingevuld. De lijnen zijn niet inbegrepen: lees ze met GET entries/{id}.

bank.transaction_imported

{
  "id": 30418,
  "source": "novadesko",
  "account_iban": "BE68539007547034",
  "value_date": "2026-10-03",
  "amount": "-1512.50",
  "currency": "EUR",
  "counterpart_name": "Brasserie des Collines SA",
  "counterpart_iban": "BE71096123456769",
  "communication": "+++091/8202/60018+++",
  "status": "pending"
}

vat.declaration_validated

{
  "id": 88,
  "period_type": "quarterly",
  "year": 2026,
  "period": 3,
  "label": "3T 2026",
  "starts_on": "2026-07-01",
  "ends_on": "2026-09-30",
  "amount_due": "4218.36",
  "amount_refund": "0.00",
  "status": "validated",
  "validated_at": "2026-10-05T09:31:02+00:00",
  "journal_entry_id": 1860
}

fiscal_year.closed

{
  "id": 6,
  "code": "2025",
  "starts_on": "2025-01-01",
  "ends_on": "2025-12-31",
  "closed_at": "2026-03-14T10:22:05+00:00"
}

peppol.status_changed

{
  "id": 57,
  "participant_id": "0208:0999900134",
  "full_id": "iso6523-actorid-upis::0208:0999900134",
  "status": "active",
  "previous_status": "pending",
  "incoming_enabled": true,
  "activated_at": "2026-10-05T09:02:11+00:00"
}

previous_status heeft de waarde null bij de eerste registratie.

third_party.created en third_party.updated

{
  "id": 215,
  "type": "supplier",
  "code": "MARBOR",
  "name": "Maraîchers du Borinage SC",
  "vat_number": "BE0999900233",
  "enterprise_number": "0999.900.233",
  "country": "BE",
  "email": "info@maraichers-borinage.example",
  "peppol_identifier": "0208:0999900233",
  "peppol_registered": true,
  "changed": ["email", "phone"]
}

Het veld changed, dat alleen aanwezig is voor third_party.updated, somt de gewijzigde velden op. De technische controles (VIES, Peppol) veroorzaken op zich geen gebeurtenis.

webhook.test

{
  "message": "Test event sent from NovaFisko.",
  "webhook_id": 14
}

Voor deze gebeurtenis heeft company de waarde null.

Pogingen en wachttijden

Uw server moet met een status 2xx antwoorden in minder dan 10 seconden. Elk ander antwoord, een time-out of een verbindingsfout telt als een mislukking.

Poging Wachttijd na de vorige mislukking
1 Onmiddellijk, binnen de minuut na de gebeurtenis
2 1 minuut
3 2 minuten
4 4 minuten
5 8 minuten
6 16 minuten
7 32 minuten
8 64 minuten

Na de achtste poging, dus iets meer dan twee uur, krijgt de levering de status failed en wordt ze niet meer opnieuw geprobeerd. Een eindpunt dat faalt, wordt niet automatisch uitgeschakeld: houd last_status in het oog.

Opmerking

De leveringen vertrekken vanuit een verwerking die elke minuut is ingepland. Een gebeurtenis komt dus aan met een vertraging van enkele seconden tot een minuut. De leveringen van een gepauzeerd eindpunt blijven in de wachtrij en vertrekken zodra het opnieuw wordt geactiveerd.

Testen

curl -X POST https://api.novafisko.com/v1/firms/Fd7hQ2mN8sXa/webhooks/14/test \
  -H "Authorization: Bearer $NOVAFISKO_TOKEN"

De gebeurtenis webhook.test wordt onmiddellijk verstuurd, zonder nieuwe poging bij een mislukking. Het antwoord is altijd 202 en bevat de levering met de verkregen status, delivered of failed. De route is beperkt tot 12 tests per minuut.

{
  "delivery": {
    "id": 90455,
    "event_id": "evt_01jb6zb1t4c8h2m6q0x3y7z9a5",
    "event": "webhook.test",
    "status": "delivered",
    "attempts": 1,
    "next_attempt_at": null,
    "response_status": 200,
    "response_excerpt": "ok",
    "duration_ms": 184,
    "delivered_at": "2026-10-05T09:40:12+00:00",
    "created_at": "2026-10-05T09:40:12+00:00",
    "payload": {"id": "evt_01jb6zb1t4c8h2m6q0x3y7z9a5", "event": "webhook.test", "api_version": "v1", "created_at": "2026-10-05T09:40:12Z", "firm": {"public_token": "Fd7hQ2mN8sXa", "name": "Fiduciaire Exemple"}, "company": null, "data": {"message": "Test event sent from NovaFisko.", "webhook_id": 14}}
  }
}

Leveringslogboek

curl "https://api.novafisko.com/v1/firms/Fd7hQ2mN8sXa/webhooks/14/deliveries?status=failed&per_page=25" \
  -H "Authorization: Bearer $NOVAFISKO_TOKEN"
Parameter Beschrijving
status pending, delivered of failed
event Naam van een gebeurtenis
per_page Standaard 25, maximaal 100
page Paginanummer
{
  "data": [
    {
      "id": 90412,
      "event_id": "evt_01jb6z3m8q2v7k4n5p9r0s1t2w",
      "event": "entry.posted",
      "status": "failed",
      "attempts": 8,
      "next_attempt_at": null,
      "response_status": 500,
      "response_excerpt": "Internal Server Error",
      "duration_ms": 412,
      "delivered_at": null,
      "created_at": "2026-10-05T09:23:20+00:00",
      "payload": {"id": "evt_01jb6z3m8q2v7k4n5p9r0s1t2w", "event": "entry.posted"}
    }
  ],
  "meta": {"current_page": 1, "last_page": 1, "per_page": 25, "total": 1}
}

response_excerpt bevat de eerste 2000 tekens van het antwoord van uw server, of de foutmelding van de verbinding. payload is de exacte body die is verstuurd: u kunt hem zelf opnieuw afspelen nadat u een storing hebt verholpen. De afgeronde leveringen (delivered of failed) worden 30 dagen bewaard.

Goede praktijken

  • Verifieer altijd de handtekening voordat u iets verwerkt. Zie Handtekeningen verifiëren.
  • Antwoord snel. Bevestig de ontvangst met een 200, plaats de gebeurtenis in een wachtrij en verwerk ze daarna. Een lange verwerking veroorzaakt time-outs en dubbels.
  • Ontdubbel op id. Eenzelfde levering kan u meerdere keren bereiken als uw antwoord verloren is gegaan. Bewaar de id's van de gebeurtenissen die al zijn verwerkt.
  • Ga niet uit van een volgorde. Twee gebeurtenissen kort na elkaar kunnen in een andere volgorde aankomen, vooral na een nieuwe poging. Steun op created_at en lees de resource opnieuw bij twijfel.
  • Behandel de gebeurtenis als een signaal. De inhoud van data is een samenvatting. Roep de API aan voor de volledige en actuele toestand.
  • Negeer onbekende gebeurtenissen. Er kunnen nieuwe gebeurtenissen en nieuwe velden verschijnen zonder versiewijziging. Antwoord 200 op wat u niet kent.
  • Houd rekening met pieken. Een massa-import (CODA-afschrift, Novadesko-synchronisatie) levert één levering op per document of per verrichting.
  • Combineer met sync/pull. Gebruik de webhook als trigger en de wijzigingsstroom als bron van waarheid. Zie Continu synchroniseren.
Let op

Het demokantoor verstuurt geen enkele webhook en het beheer van de eindpunten is er geblokkeerd (403, code demo_mode).

Zie ook