Registering Webhooks to Receive Events ========================================= The endpoints you will send webhook requests to can be found: Envase Connect API Docs To receive any events from Envase Connect, the webhooks must first be registered. Envase Connect will need the following properties to be able to have a webhook registered: - ``URL``: Your URL endpoint that will receive the event. - ``Triggers``: The event “actions” you will need to be notified of - ``Event Type``: The type of event entity you are publishing - ``Signing Key``: This is the key generated in :ref:`Create a Signing Key` - ``Webhook Headers`` (optional): Custom HTTP headers to include with event notifications The example below would create a webhook that is notified when any of the follow events happen for you from the Gate Management System (GMS): .. code:: json { "url": "https://your-domain.com/some-endpoint", "triggers": [ "APPROVED","REJECTED", "REJECTED_INVALID_BOOKING", "REJECTED_EXPIRED_BOOKING", "INTERCHANGE_PROCESSED", ], "eventType": "GATE", "signingKey": "your-signing-key", "webhookHeaders": [ { "name": "X-API-Key", "value": "your-api-key-here" } ], "filters": [ { "payload.location.streetAddress1": "1 Fine Arts Dr", "payload.location.city": "St. Louis", "payload.location.state": "MO" } ] } Example Event With Headers -------------------------- .. code:: json { "headers": { "X-Envase-Connect-Signature-256": "t=1660929593448,v1=978e2b45742542a9359321bd78c666e0e39aae9d420620ddb8c71c583f0d6cf0" }, "payload": { "isTest": true, "action": "INTERCHANGE_PROCESSED", "type": "GATE", "operator": "7f809-asdf3-234d-34sa", "gateType": "IN", "payload": { "location": { "name": "test location", "streetAddress1": "1 Fine Arts Dr", "city": "St. Louis", "state": "MO", "zipCode": "63110" }, "truck": { "licensePlate": "W45H125", "axles": 6, "length": 10, "weight": 1200, "width": 10, "owned": true }, "container": { "length": 10, "weight": 1200, "width": 10, "owned": true, "sealNumber": "WED122", "containerNumber": "333212" }, "chassis": { "length": 10, "width": 10, "owned": true, "axles": 6, "licensePlate": "123ABC" } } } } Webhook Headers --------------- You can include custom HTTP headers with your webhook registration that will be sent with every event notification to your endpoint. **Why use Webhook Headers?** Webhook headers enable you to: - **Authenticate incoming events**: Include API keys or authentication tokens that your endpoint requires - **Version control**: Specify API versions to ensure compatibility as your endpoint evolves - **Format specification**: Define content types or data formats your system expects - **Custom routing**: Add identifiers that help route events within your infrastructure - **Security**: Add additional security layers beyond the signing key verification For example, if your endpoint requires an API key for authentication, you can include it as a header rather than modifying your webhook URL or implementing a workaround. The ``webhookHeaders`` property is optional and accepts an array of header objects, each containing a ``name`` and ``value``: .. code:: json "webhookHeaders": [ { "name": "X-API-Key", "value": "your-api-key-here" }, { "name": "X-API-Version", "value": "v1" }, { "name": "Content-Type", "value": "application/json" } ] When events are delivered to your webhook URL, these custom headers will be included in the HTTP request along with the system-generated headers like ``X-Envase-Connect-Signature-256`` (if a signing key is provided). **Validation and Restrictions** - The ``webhookHeaders`` property is optional. If omitted, no custom headers will be sent with events. - If ``webhookHeaders`` is included, it must contain at least one header object (empty arrays are not allowed). - Both ``name`` and ``value`` fields are required for each header object and cannot be null. - Headers are validated when creating or updating a webhook. Improperly formatted headers will cause the webhook creation/update to fail. - Header names should follow standard HTTP header naming conventions. - Header values are stored and sent as-is without modification. Webhook Filters --------------- In order to get notified about specific events, you can use optional filters when creating the webhook. An example of a single filter can be seen above. In this example, the webhook will only be created if ``ALL`` of the conditions inside the object are true. So, in order for this webhook to be created, the Gate event must meet the filter criteria: - Address is “1 Fine Arts Dr” - City is St Louis - State is MO If any of these conditions are not true or not found, the webhook will not be created. You can filter for ``ANY`` property in the given event. You can also create multiple webhooks based on the filter criteria. An example of how this works is: .. code:: json "filters": [ { "tmsId": "abc123", // AND "payload.chassis.licensePlate": "123ABC", // AND "payload.location.streetAddress1": "1 Fine Arts Dr" }, // OR { "orgId": "def456", // AND "tmsId": "789hij" }, // OR { "payload.container.streetAddress1": "123456", } ] Starting from the top, the first filter will subscribe you to events where: - ``tmsId = "abc123"`` AND - ``payload.chassis.licensePlate = "123ABC"`` AND - ``payload.location.streetAddress1 = "1 Fine Arts Dr"`` **OR** The second filter will subscribe you to events where: - ``orgId = "def456"`` AND - ``tmsId = "789hij"`` **OR** The third filter will subscribe you to events where: - ``payload.container.streetAddress1 = 123456`` If any of criteria in a filter object is not true or not found, the webhook will not be created for that filter and the next filter object will be tried. If all of the filter criteria are found and are also true, then all of the webhooks will be created with the matching filters. If some of the filter criteria are ``true/found`` but others inside the same filter object are not, then the webhook will not be created. For example, in the first filter, if the ``tmsId`` and ``licensePlate`` values are ``true/found`` but the ``streetAddress1`` is not, then the webhook will not be created and the second filter will be tried. Handling Delivered Events ------------------------- When your system receives an event through your webhook, your system is expected to send back a HTTP 2xx response code back. This allows our system to realize that the event was received from your system correctly. Otherwise, the event will be handled as a failure to send. Retry on Failure ---------------- If a webhook notification fails, the system will attempt to resend the notification at various intervals to ensure delivery. You can see how many times the notification delivery was attempted with the header property ``X-Envase-Connect-Retry-Count``. With each retry there will also be a random amount of “jitter” added on. The following table outlines the retry timelines. After about 24 hours, if the notification could not be delivered, the notification will get sent to the dead letter queue. We use jitter to add a random amount of time when retrying the notifications. This is so that notifications aren’t sent at the exact same time or intervals. The random amount of jitter added is between 1 and 300 seconds. =========== ===================== Retry count Time until next retry =========== ===================== 1 1 minute 2 4 minutes 3 9 minutes 4 16 minutes 5 25 minutes 6 36 minutes 7 49 minutes 8 1 hour 4 minutes 9 1 hour 21 minutes 10 1 hour 40 minutes 11 2 hours 1 minute 12 2 hours 24 minutes 13 2 hours 49 minutes 14 3 hours 16 minutes 15 3 hours 45 minutes =========== ===================== Total Time ~ 24 hours