In addition to the APIs to access the resources, Poynt Cloud APIs also provide webhook notifications for various state changes of each resource to registered endpoints. Applications can register their own endpoints as webhook url for various events programmatically. In addition to sending notifications, Poynt APIs also provide a way to obtain a list of all notifications (from last 30 days) sent so the applications can always make sure they didn’t miss any notifications that they would need to process.

Registering a webhook

Example request:

curl -v https://services.poynt.net/hooks \
-H "Poynt-Request-Id: <request id>" \
-H "api-version: 1.2" \
-H "Content-Type: application/json;charset=UTF-8" \
-H "Authorization: BEARER <access token>" \
-d '
{
        "applicationId": "urn:aid:6bcee3b0-ced0-4263-ac4e-f783acc9857e",
        "businessId": "569e957c-57a7-4d54-a72a-9e8f3296adad",
        "deliveryUrl": "http://www.mysite.com/webhook_listener.php",
        "secret": "not-the-secret-you-know",
        "eventTypes":[
	        "ORDER_OPENED",
	        "ORDER_COMPLETED",
	        "ORDER_CANCELLED",
	        "ORDER_UPDATED"
        ]
}
'

Example response:

{
    "active": true,
    "applicationId": "urn:aid:6bcee3b0-ced0-4263-ac4e-f783acc9857e",
    "businessId": "569e957c-57a7-4d54-a72a-9e8f3296adad",
    "createdAt": "2015-09-17T03:41:54Z",
    "deliveryUrl": "http://www.mysite.com/webhook_listener.php",
    "eventTypes": [
        "ORDER_OPENED",
        "ORDER_COMPLETED",
        "ORDER_CANCELLED",
        "ORDER_UPDATED"
    ],
    "id": "dbd29830-a67f-419b-a1d5-777a228543d6",
    "secret": "********",
    "updatedAt": "2015-09-17T03:41:54Z"
}

Validating a webhook

When a specific event occurs Poynt will send a webhook to the registered listener URL which will look something like this:

Accept-Encoding: gzip,deflate
User-Agent: Apache-HttpClient/4.5 (Java/1.8.0_45-internal)
Connection: close
Host: www.mysite.com
Content-Length: 660
Poynt-Webhook-Signature: PkaykJxe3c5rHtZjcfBKWLk2khA=
Content-Type: application/json

{
    "applicationId": "urn:aid:6bdee3b0-ced0-4263-ac4e-f783acc9857e",
    "businessId": "469e957c-57a7-4d54-a72a-9e8f3296adad",
    "createdAt": "2015-09-15T20:00:44Z",
    "deviceId": "urn:tid:7e113874-9c3e-3d45-9c37-bde91ebe60e8",
    "eventType": "ORDER_COMPLETED",
    "hookId": "3574d16a-671c-47e3-ac0b-06dc5878abdc",
    "id": "77c6d7f7-2eeb-4ed0-9cb7-d1a846473cfc",
    "links": [
        {
            "href": "https://services.poynt.net/businesses/469e957c-57a7-4d54-a72a-9e8f3296adad/orders/d297262c-014f-1000-01e4-3c85d2679731",
            "method": "GET",
            "rel": "resource"
        }
    ],
    "resource": "/orders",
    "resourceId": "d297262c-014f-1000-01e4-3c85d2679731",
    "storeId": "c2855b41-1dd5-4ecc-8258-f0c89ae40338",
    "updatedAt": "2015-09-15T20:00:44Z"
}

To validate the authenticity of the webhook payload you need to create a base64 encoded binary SHA1 HMAC of the payload and compare it to the value of Poynt-Webhook-Signature HTTP header sent in the webhook request. Here’s an example how this can be done using openssl:

bash$ echo -n '<webhook json object>' | openssl sha1 -hmac "not-the-secret-you-know" -binary | base64

PkaykJxe3c5rHtZjcfBKWLk2khA=

Please note that Poynt only waits for 2 seconds to receive an acknowledgement from your webhook listener (i.e. HTTP 200 response). If we don't receive a response, the delivery will be retried, so as a best practice make sure your webhook listener logic can de-dupe multiple requests.

Python sample is available here.