# Hook

Use hook to be notified about events in the Procurement Service Bus. The Procurement Service Bus can send webhooks and email notifications to your application about events that happened in your Party. This mechanism is very useful for receiving invoices. Once an invoice has arrived you will be notified via the registered hooks.

There are several types of hooks. The type of hook depends on the action defined. The two general actions are 'mail' and 'https'.

Hooks can be triggered at several moments. These moments are defined as topics.

# Topics

The topic indicates when the hook is triggered.

Topic Function
InvoiceReceived Triggered when a document is successfully received by the Procurement Service Bus.
InvoiceReceivedError Triggered on a document that is rejected by the Procurement Service Bus because of an error.
InvoiceSent Triggered when a document is successfully sent by the Procurement Service Bus and received by another party.
InvoiceSentError Triggered on a document that is rejected by the receiver because of an error. This is a permanent error and the document will not be send.
InvoiceSentRetry Triggered on a document that is rejected by the receiver because of an error. This can be a temporary failure. Retries will be done.
SpecialHooks See if hooks are working correctly. Only the email action can be used.
HookSent Triggers when a hook is triggered and a hook message is sent. This means the receiving system is informed about a topic.
HookSentRetry Triggers when a hook is triggered but the message was not send because the receiver can’t be reached and a retry will be done. This is an indication that your hook receiver is not working correctly and the Procurement Service Bus is unable to inform you about the status of processed documents.
HookSentError Triggers when a hook has stopped retrying. This is a permanent error.

# Mail hooks

A mail hook has the following action: "action":"mailto:receiver@example.com".

# Include attachment

Mail hooks can also include the document as an attachment, for monitoring or debug purposes for example. To do this, add includeAttachment=true as a query parameter to the action. Optionally, query parameter targetDocumentTypeId={target} can be used to specify a target documentTypeId. The attached document will be of this documentTypeId, given a tranformation from the original to the target documentTypeId is available. Special characters in the documentTypeId have to be escaped.

"action":"mailto:receiver@example.com?includeAttachment=true&targetDocumentTypeId=urn%3Aoasis%3Anames%3Aspecification%3Aubl%3Aschema%3Axsd%3AInvoice-2%3A%3AInvoice%23%23urn%3Acen.eu%3Aen16931%3A2017%23compliant%23urn%3Afdc%3Anen.nl%3Anlcius%3Av1.0%3A%3A2.1"

# WebHooks

Webhooks deliver information by pushing a https message to a receiver. This can only be done with https.

# Configure your webhook

You can register the webhook via PUT method on the /Hook endpoint. The Procurement Service Bus starts sending HTTP POST webhooks once the webhook is registered. Events will only be send when a hook is registered with the corresponding topic. Define an action with your endpoint URL and append this URL with a # and a secret key. This key will be used to sign requests. Optionally, you can define basic authentication in the action to protect your endpoint in the form of: https://user:pass@your.endpoint#someRandomKey.

{
   "id": "1",
   "name": "webhook",
   "action": "https://user:pass@webhook.site/a81a0be5-8aad-4110-a40c-aa41a2c6e9ac#secureKey",
   "topics": [
     "InvoiceReceived"
   ],
   "isActive": true
}

# Testing webhook

For testing the call GET /api/v1/{partyId}/hook/ping can be used. This call will trigger the InvoiceReceived hook by sending a dummy document to {partyId}.

# Securing webhook

We use an HMAC SHA256 signature of the payload and include that signature in the request header 'X-EConnect-Signature'. The header value is in the form of 'sha256={signature}', where {signature} is a 64-byte, hexadecimal representation of a SHA256 signature. The signature is computed using a secret key provided by you. Validate this signature to make sure the data is not manipulated and sent from the PSB.

You could also whitelist these IP addresses: 104.40.188.59 and 104.47.148.207 for production, and 51.144.92.226 and 13.81.124.198 for acceptance.

The payload contains a 'sentOn' field. Make sure that this date is not older than 5 minutes to prevent relay attacks.

# Validate Webhook signatures

  1. Get the signature from the X-EConnect-Signature header.
  2. Get the json payload from the request body and your secret key.
  3. Compute the signature using the payload and your secret key. Then stringify the byte[] to a hexadecimal representation and prepend the string with "sha256=".
  4. Compare the signatures. (We advise to use a secure compare.)

You could use https://www.freeformatter.com/hmac-generator.html (opens new window) to manually validate the signature. Enter your secret key and select SHA256 as the digest algorithm, then compute the hash.

# Webhook using mutual SSL

With the endpoint PUT /api/v1-beta/{partyId}/hook in the PSB Api Beta you can setup a hook with mutual SSL authentication. To be able to use mutual SSL the “Init” object can be used. In this object the certificate can be added as base64 encoded string:

{
  "id": "1",
  "name": "ssl hook",
  "action": "https://econnect.eu",
  "init": {"certificate": "MIIKngIBAzCCCloGCSqGSIb3DQEHAaCCCksEggpHMIIKQzCCBgQGCSqGSIb3DQEHAaCCBfUEggXxMIIF7TCCBekGC(…)"},
  "topics": [
    "InvoiceReceived",
    "InvoiceReceivedError",
    "InvoiceSent",	
    "InvoiceSentError",
    "InvoiceSentRetry",
  ],
  "publishTopics": null,
  "isActive": true,
}

Setting a certificate is one-time action. The certificate is then saved when the hook is modified. When you update the hook, for example by adding a topic, you do not have to provide the certificate again. The certificate can no longer be read back via the GET / hook. Currently PEM and PKCS # 12 (.pfx and .p12) certificates are supported. The certificate must contain the public and private key and must not be password protected. To create a base64 encoded string from a certificate you can use OpenSSL, or the following Powershell command:

$fileContentBytes = get-content 'C:certificaat.pfx' -Encoding Byte
[System.Convert]::ToBase64String($fileContentBytes) | Out-File ‘certificaat_base64string.txt’

# Responding to a webhook

To acknowledge receipt of a webhook your endpoint should return a 2xx HTTP status code. Any response code outside of this range, including 3xx codes, will indicate that you did not receive the webhook.

We will attempt to deliver your webhooks for up to five days, with an exponential time increase between retries. Set up a mail hook with the topic HookSentError to be notified about delivery failures. The webhooks cannot be triggered manually.

We only accept https endpoints with a valid server certificate.

Disable any CSRF protection on your webhook endpoints to avoid the webhook being blocked.

# Returned elements

Element Description
topic Topic that triggered the hook.
partyId The hook's owner. The party that sent or received a document.
hookId The hook that triggered the message.
documentId Id of the document that was processed.
message Description why the hook was triggered.
details A dictionary containing more information specific to the topic.
createdOn Original date the hook was triggered.
sentOn Date the hook was actually sent.

# An example of a webhook request

Content-Type: application/json
X-EConnect-Signature: sha256=ffb4c9542b7e8dc84ac9f9ec7eb7f9af38bc118901879fe5a94485c61f36b327
X-EConnect-Delivery: 4439174b-b9eb-4ed0-9dff-e87139113328
Content-Length: 773

{
    "topic": "InvoiceReceived",
    "partyId": "NL:KVK:ECONNECTTEST",
    "hookId": "2",
    "documentId": "cf262fcf-2fe9-4c1b-b287-05f2818add30",
    "message": "'Invoice' received.",
    "details": {
        "protocol": "As4",
        "returnedMessageId": "cf262fcf-2fe9-4c1b-b287-05f2818add30@econnect.eu",
        "sender": "0106:econnectsender",
        "accessPoint": "C=NL, O=eConnect International B.V., OU=PEPPOL TEST AP, CN=PNL000052",
        "id": "12115118",
        "documentTypeId": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0::2.1",
        "profileId": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
        "messageId": "d5beee1d-0f7c-40f9-a91a-53ede0159a7d@econnect.eu",
        "refToMessageId": null
    },
    "createdOn": "2021-02-25T08:55:29.184498+00:00",
    "sentOn": "2021-02-25T08:56:14.4150988+00:00"
}
© 2021 eConnect International B.V.