Last updated

Webhooks

In addition to retrieving shipment updates via the GET APIs you can receive them by webhook PUSH. A webhook is an endpoint hosted by you that you have registered to receive shipment updates on. When you have a webhook configured, changes to your shipments will be sent (pushed) to your hosted endpoint via an HTTP request.

Setup and Configuration

Create or Update a PUSH Configuration

This is a one-time activity to set up a webhook or to update an existing webhook configuration.

Once a webhook is created please reach out to your project44 representative to complete the webhook setup process.

Workflow

Complete these steps:

  1. Prepare a PUT request to /api/v4/webhooks.
  2. Complete the request schema.
JSON
{
  "authParams": {},
  "authType": "API_KEY",
  "authenticationMethods": [
    {
      "parameters": {},
      "type": "API_KEY"
    }
  ],
  "configName": "string",
  "id": 0,
  "method": "GET",
  "methodParams": {},
  "payloadFormat": "JSON",
  "url": "string",
  "version": 0
}
  1. Send the request.

Expected Response

You have successfully submitted the request when you receive a 200 OK response. Here is a sample of the minimum response schema:

JSON
{
  "authParams": {},
  "authType": "API_KEY",
  "authenticationMethods": [
    {
      "parameters": {},
      "type": "API_KEY"
    }
  ],
  "configName": "string",
  "id": 0,
  "method": "GET",
  "methodParams": {},
  "payloadFormat": "JSON",
  "url": "string",
  "version": 0
}

Errors

If there was a problem with your request, you will receive one of the following error codes:

  • 400 Invalid request
  • 401 Invalid or missing credentials
  • 403 User not authorized to perform this operation
  • 404 Not Found

Fields and Objects

FieldDescription
authenticationMethodsA list of authentication methods that consists of type and parameters fields. Typically, only one form of authentication is used (though it is possible to have two API keys or both an API key and OAuth2 authentication). Supported types are API_KEY, BASIC, OAUTH2, MTLS and AD_OAUTH2_CERT.
authenticationMethods.parametersThe webhookAuthenticationMethod parameters. The fields of a parameters object vary for each authentication method. All fields are strings unless noted otherwise. See Authentication Method Fields for more information on the fields for each authentication method.
configNameA unique name used to identify the push configuration.
idA unique identifier of the push configuration. Assigned by the push configuration API service and used for updates only.
methodThe HTTP method associated with the webhook endpoint. If not provided, will default to POST. Supported values: "GET", "POST", "PUT", "PATCH".
methodParamsA map of optional method parameters. If provided, these will appear as query parameters on the URL.
urlThe URL of the webhook endpoint.
versionAn optional version of the push configuration.

Retrieve a Webhook Configuration by Name

Requirements

Have the following information:

  • webhookName

Workflow

Complete these steps:

  1. Prepare a GET request to /api/v4/webhooks/name/{webhookName}.
  2. Send the request.

Expected Response

You have successfully submitted the request when you receive a 200 OK response. Here is a sample of the minimum response schema:

JSON
{
  "authParams": {},
  "authType": "API_KEY",
  "authenticationMethods": [
    {
      "parameters": {},
      "type": "API_KEY"
    }
  ],
  "configName": "string",
  "id": 0,
  "method": "GET",
  "methodParams": {},
  "payloadFormat": "JSON",
  "url": "string",
  "version": 0
}

Errors

If there was a problem with your request, you will receive one of the following error codes:

  • 400 Invalid request
  • 401 Invalid or missing credentials
  • 403 User not authorized to perform this operation
  • 404 Not Found

Retrieve All Webhook Configurations

Workflow

Complete these steps:

  1. Prepare a GET request to /api/v4/webhooks.
  2. Send the request.

Expected Response

You have successfully submitted the request when you receive a 200 OK response. Here is a sample of the minimum response schema:

JSON
{
  "webhookEndpoints": [
    {
      "authParams": {},
      "authType": "API_KEY",
      "authenticationMethods": [
        {
          "parameters": {},
          "type": "API_KEY"
        }
      ],
      "configName": "string",
      "id": 0,
      "method": "GET",
      "methodParams": {},
      "payloadFormat": "JSON",
      "url": "string",
      "version": 0
    }
  ]
}

Errors

If there was a problem with your request, you will receive one of the following error codes:

  • 400 Invalid request
  • 401 Invalid or missing credentials
  • 403 User not authorized to perform this operation
  • 404 Not Found

Authentication Method Fields

API Key authentication

A new HTTP header is created for each supplied api key (max 2).

  • api_key_name: the name of the API Key.
  • api_key_value: the value of the API Key.

Example Payload with API Key Authentication Method

{
   "configName": "{configName}",
   "url": "{url to invoke}",
   "method": "POST",
   "methodParams": {},
   "authType": "API_KEY",
   "authenticationMethods": [
      {
         "parameters": {
            "api_key_name": "{key name}",
            "api_key": "{api key}"
         },
         "type": "API_KEY"
      }
   ]
}

Basic authentication

Applied to the 'Authorization' header with the 'Basic' identifier. Values are concatenated (with a separating colon character) and encoded to base64.

  • username: username for authentication.
  • password: password for authentication.

Example Payload with Basic Authentication Method

{
   "configName": "{config name}",
   "url": "{url to invoke}",
   "method": "POST",
   "methodParams": {},
   "authenticationMethods": [
      {
         "parameters": {
            "password": "{password}",
            "username": "{username}"
         },
         "type": "BASIC"
      }
   ]
}

OAuth2 authentication

The OAuth2 bearer token is generated then applied to the 'Authorization' header with the 'Bearer' identifier. The generated token will be cached, and refreshed after expiry.

  • grantType: Type of authentication granted to the OAuth2 provider. Currently only 'client_credentials' is supported.
  • accessTokenUri: endpoint used to grant the bearer token.
  • clientId: unique client identifier.
  • clientSecret: authentication key for the client; functionally similar to a password.
  • clientAuthenticationScheme: identifies whether the OAuth2 fields are supplied to the authorization granter in the header or the request body. Accepted values are header and form. A header will be added as 'Content-Type: application/x-www-form-urlencoded'.
  • extraParams: Optional - An object containing additional fields to be added to the request to the access token provider.

Example Payload with OAuth2 Authentication Method

{
   "configName": "{config name}",
   "url": "{url to invoke}",
   "method": "POST",
   "authenticationMethods": [
      {
         "type": "OAUTH2",
         "parameters": {
            "accessTokenUri": "{auth endpoint to generate token}",
            "clientSecret": "xxx",
            "clientId": "xxx",
            "clientAuthenticationScheme": "form", //form or header
            "grantType": "client_credentials"
         }
      }
   ]
}

Mutual TLS authentication

Mutual TLS relies on a two-way handshaking when establishing an HTTPS connection. After the client verifies the server certificate (as normal in TLS), the server requests a certificate from the client and verifies it. This way both the client and server are authenticated to each other.

In addition, MTLS also allows the client to "trust" specific endpoints, allowing the webhook to be hosted on a server with a self-signed certificate. The trusted endpoint's CA certificate is provided along with the client cert and key.

MTLS authentication uses a significantly simpler configuration than OAUth2. All that is required is the client certificate chain (usually a single cert, but may have more than one), the private key, and an (optional) trusted CA certificate.

See PEM Format for more information how to encode certificates.

Example Payload with Mutual TLS Authentication Method

{
   "configName": "{config name}",
   "url": "{url to invoke}",
   "method": "POST",
   "authenticationMethods": [
      {
         "type": "MTLS",
         "parameters": {
             "pemCertificateChain": "<pem-formatted client cert(s)>",
             "pemPrivateKey": "<pem-formatted private key>",
             "pemEndpointCertificate": "<pem-formatted trusted CA cert>"
         }
      }
   ]
}

Azure cert-based OAuth2 authentication

This authentication type uses the Azure certificate-based OAuth2 implementation documented here.

The parameters payload for AD_OAUTH2_CERT is an extension of the OAUTH2 payload, with a couple of new fields added to support the certificate.

The AD_OAUTH2_CERT authorization is very complex, and requires strict rules on the values passed in.

See PEM Format for more information how to encode certificates.

Example Payload with Azure Cert-Based OAuth2 Authentication Method

{
   "configName": "{config name}",
   "url": "{url to invoke}",
   "method": "POST",
   "authenticationMethods": [
      {
         "type": "AD_OAUTH2_CERT",
         "parameters": {
           "grantType": "client_credentials",
           "accessTokenUri": "<Url for generating access token>",
           "clientId": "<Microsoft client ID>",
           "tokenName": "client_assertion",
           "scope": [ "<OAuth2 scope>" ],
           "extraHeaders": {},
           "extraParams": {
             "audience": "https://login.microsoftonline.com/<Microsoft Tenant Id>/oauth2/v2.0/token",
             "tenant": "<Microsoft Tenant Id>"
           },
           "clientAuthenticationScheme": "header",
           "authorizationScheme": "header",
           "pemCertificate": "<PEM-formatted cert...>",
           "pemPrivateKey": "<PEM-formatted key...>"
         }
      }
   ]
}

PEM format

Because we are dealing with ReST APIs, all certificate and key information must be provided in PEM format.

PEM is a textual format that is a base-64 encoding of the binary data. All of the certificate processing tools support PEM files for both input and output, so it is simple to extract PEM-based resources from other formats.

For example, to extract a PEM-formatted certificate from a PKCS12 (.pfx) archive, you can use the open-source openssl tool:

openssl pkcs12 -in certname.pfx -nokeys -out cert.pem

Likewise, to extract the private key use:

openssl pkcs12 -in certname.pfx -nocerts -out key.pem -nodes

Encoding of PEM resources

Standard PEM data looks something like this:

-----BEGIN CERTIFICATE-----
MIIDUDCCAjigAwIBAgIQeUL2u4TVSW6mA/vZ9ErD6DANBgkqhkiG9w0BAQsFADAl
MSMwIQYDVQQDExpNU0MtT2NlYW5JbnNpZ2h0c1Byb2plY3Q0NDAeFw0yMjA2Mjgw
[... many, many lines removed...]
zYTtADSP+ntsjphz1/lXZq9pMq/lcNLipxjSlIlEYxH3/UKV
-----END CERTIFICATE-----

There may be multiple sections in a PEM file, with individual resources marked with BEGIN/END blocks as shown above. Unfortunately, because of these markers, the line breaks are important. Since JSON ignores newlines, we will need a way to encode these in our JSON payloads.

We deal with this by encoding newlines with a \n delimiter. Since the base64-encoded contents will ignore whitespace, the block between the begin and end markers can be a single string.

For example, encoding the certificate above with a \n delimiter would use in something like this:

{
  "certificate" :
    "-----BEGIN CERTIFICATE-----\n
    MII ... lots of characters removed ... KJ=\n
    -----END CERTIFICATE-----\n"
}

Additional Information

Webhook Configuration Examples

  • Azure Integration: Using Shared Access Signatures (SAS)
{
   "configName": "{config name}",
   "url": "https://{azure application or service}?sr={service resource}&sig={signature}&se={expiration time}&skn={shared access key name}",
   "method": "POST",
   "methodParams": {},
   "methodHeaders": {},
   "authenticationMethods": [],
   "payloadFormat": "JSON"
}

The URL should not be encoded.

Push Retry Logic

It is expected that webhooks will not always have 100% uptime. To address this our system will queue up messages for later retries if they can't be delivered.

While the client’s webhook is up and receiving requests, pushes will be sent as soon as they are available. When the client’s webhook goes down, the project44 system will detect the outage and begin queuing up any messages targeted for that webhook. It will retry connecting every few minutes to detect when the client webhook is back online. Once back online, the system will resume from where it was last successful and push its queue of messages to the client’s webhook. Messages will be delivered in the same order which they were originally intended to be delivered.

How are different HTTP status codes handled?

The system will not retry all errors because there are certain errors that are expected rejections. Various response codes from the webhook indicate a failure which cannot be resolved by retrying such as the data being rejected. The table below indicates which http status codes and error conditions are treated as a success, retriable error, or non-retriable error. The behavior described applies to any of the retriable responses:

Type of ResponseHTTP Status CodesRetry Behavior
Successful deliveryAny 2xx status code (including but not limited to):
  • 200 - OK
  • 201 - Created
  • 202 - Accepted
  • 204 - No Content
Mark the message as delivered and proceed to the next message(s)
Retriable responses
  • 408 - Request Timeout
  • 429 - Too Many Requests
  • 502 - Bad Gateway
  • 503 - Service unavailable
  • 504 - Gateway Timeout
  • [connection failure]
  • [connection timeout]
Detect that the webhook is down and begin retrying. All other unsent messages will enqueue behind this message and wait until this message succeeds or expires before they are sent.
Non-Retriable responsesAny 3xx status code (redirects will not be followed).

Any other 4xx status codes (including but not limited to):
  • 400 - Bad Request
  • 401 - Unauthorized
  • 403 - Forbidden
  • 404 - Not Found
  • 405 - Method Not Allowed
  • 406 - Not Acceptable
  • 413 - Payload Too Large
Any other 5xx status codes (including but not limited to):
  • 500 - Internal Server Error
Mark the message as failed and proceed to the next message(s). These messages will not be retried.

How Long Will project44 Hold My Data For?

project44 will hold messages in a queue to be retried for up to 48 hours. After this time, the message will expire and the system will move onto the next message in the queue.


Webhook Recommendations

Webhook Response Time

project44 recommends that your webhook returns a response within a few seconds, however we will wait up to 20 seconds before we consider the request timed out. Once the message has timed out, it will be retried in a few minutes and will keep being retrying until the message is successfully delivered or expires after 48 hours. Since messages must be delivered in order, any messages that timeout may delay later messages being sent to the webhook.

The common recommendation is to acknowledge the receipt of messages before any processing on your side.

Concurrent Requests

When possible, project44 may send concurrent requests to your webhook for messages that don't need to be sent in order. For example, position updates for two unrelated shipments may be sent at the same time. This allows for lower latency between project44 and your webhook. project44 recommends your webhook support up to 8 concurrent requests for best throughput and lowest latency data.

Delivery Semantics

project44 recommends your webhook be idempotent. This means that the same message can be sent to your webhook more than once and not cause any duplicate data. Under normal circumstances project44 will not send the same message twice if we get a successful response back but there could be cases where a response was not received, such as an unexpected network failure, that will cause the message to be sent again.