Webhooks¶
Instead of constantly calling GET /api/v1/requests/{requestId} (polling), register an HTTPS endpoint of your own. Novus calls it every time something changes in one of your requests.
Registration¶
POST /api/v1/webhooks
{
"url": "https://to-logismiko-sas.gr/novus-events",
"events": [
"request.status_changed",
"request.provisioned"
]
}
| Field | |
|---|---|
url |
Your HTTPS endpoint |
events |
The events you want, at least one (see below) |
The response (201) contains endpointId, url, events, createdAt and a secret. The secret is returned only this once, so store it: you use it to verify the signature of every call.
| Call | |
|---|---|
GET /api/v1/webhooks |
Your endpoints (without the secrets) |
DELETE /api/v1/webhooks/{endpointId} |
Stops notifications to this endpoint (204) |
GET /api/v1/webhooks/deliveries?endpointId=…&page=1&pageSize=50 |
Delivery history, for debugging: what was sent and what you replied (eventId, event, attempt, responseStatus, deliveredAt, succeeded). Filters: endpointId, eventId. |
Events¶
event |
When |
|---|---|
request.created |
A request was created |
request.status_changed |
The status of a request changed. The most useful event. |
request.provisioned |
The client was activated (provisioning.status = COMPLETED) and can start issuing |
request.provisioning_failed |
Activation failed. Novus is notified automatically and handles it. Do not send the request again. |
client.statement_recalled |
The Provider declaration to AADE (the Greek tax authority) was recalled |
The call you receive¶
POST https://to-logismiko-sas.gr/novus-events
Content-Type: application/json
X-Novus-Event-Id: evt_8f7b2c9a1d4e
X-Novus-Signature: sha256=4f1c…
{
"event": "request.status_changed",
"eventId": "evt_8f7b2c9a1d4e",
"occurredAt": "2026-09-17T10:15:00Z",
"data": {
"requestId": "req_8f7b2c9a",
"status": "APPROVED",
"previousStatus": "UNDER_REVIEW",
"message": "Η αίτηση εγκρίθηκε."
}
}
A webhook tells you that something changed. It is not the source of truth
Always confirm with GET /api/v1/requests/{requestId} before you act.
- Reply
2xxas fast as possible and do your processing afterwards. Anything else is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, and then abandoned. - Duplicates: the same event can arrive again on a retry, with the same
X-Novus-Event-Id. Ignore the ones you have already seen. - Signature: always verify
X-Novus-Signature.
Verifying the signature¶
X-Novus-Signature = sha256= + the HMAC-SHA256 of the exact body, keyed with your secret, in lowercase hex. Compute it on the bytes as you received them, before any JSON parsing.
using System.Security.Cryptography;
using System.Text;
static bool IsValid(string rawBody, string header, string secret)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var expected = "sha256=" + Convert.ToHexString(hmac.ComputeHash(Encoding.UTF8.GetBytes(rawBody))).ToLowerInvariant();
return CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(expected), Encoding.UTF8.GetBytes(header ?? ""));
}
uses System.Hash, System.SysUtils;
function IsValid(const RawBody, Header, Secret: string): Boolean;
var
Expected: string;
begin
Expected := 'sha256=' + LowerCase(THash.DigestAsString(
THashSHA2.GetHMACAsBytes(TEncoding.UTF8.GetBytes(RawBody), TEncoding.UTF8.GetBytes(Secret))));
Result := SameStr(Expected, Header);
end;