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 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):

{
  "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

{
    "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:

"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:

"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