Need Support? phone 1300 803 873 or email [email protected]

Webhooks Integration Guide

Receive event notifications with webhooks

Listen for events on your Inbound account so your 3rd party system can automatically process events that occur in Inbound.

Inbound uses webhooks to notify your application when an event happens in your account. Webhooks will post data to your external system using HTTP whenever a particular event occurs in the Inbound system.

Begin using webhooks with Inbound in just three steps:
  1. Ensure webhooks are available in your account, contact [email protected] to request it to be enabled.
  2. Navigate to Administration -> Webhooks -> Webhook subscriptions
  3. Create your subscription to the events you are interested in

Action in Inbound which generate webhook events

This event is triggered whenever a booking is created, updated or cancelled for your account (for a facility this is any booking to your facility, for a transporter this is any booking made under your account). The event will include all details about the booking, excluding the actual attachments. Retrieval of attachments is coming soon.  
FieldDescriptionComments
idUnique ID for this event.
eventName of the event that generated this message.App.BookingCreatedOrUpdated always for this event type.
attemptNumber of attempts it took to call your webhook endpoint.
data.bookingNumberBooking number for this booking.
data.facilityName of the facility this booking was for.
data.serviceThe name of the service at this facility this booking was for.
data.bookingDateDate the booking was made for.Format will be yyyy-mm-dd.
data.startTimeWindowThe start time of the timeslot the booking was made for.Format will be hh:mm (24 hour time).
data.secondaryCapacityFieldNameName of the secondary capacity field
data.secondaryCapacityQuantityQuantity of the secondary capacity
data.endTimeWindowThe end time of the timeslot the booking was made for.Format will be hh:mm (24 hour time).
data.statusThe current status of the booking.Will be one of “Open”, “Completed”, “CancelledByFacility”, “CancelledByTransporter”, “CancelledBySystem”.
data.transporterName of the transport company who made this booking.
data.guestNameName of the guest user who made the booking.If a booking is made by a one-off user then they are required to provide their name. (N/A to transporter subscriptions)
data.guestEmailEmail of the guest user who made the booking.If a booking is made by a one-off user then they are required to provide their email. (N/A to transporter subscriptions)
data.preProcessedBoolean value representing whether the booking has been pre-processed or not.(N/A to transporter subscriptions)
data.cancellationReasonReason the booking was cancelled.Bookings cancelled by system, facility or user can have a reason provided.
data.baseAmountPre tax amount charged for this booking.
data.taxAmountTax amount calculated for this booking.
data.totalIncludingTaxTotal amount paid for this booking including any taxes.
data.eBookingExternalReferenceIdIf this booking was created from an e-booking. This will be the external reference Id. If provided.(N/A to facility subscriptions)
data.fieldsArray of Field/Value pairs representing the field data made with this booking.Each service can have a different set of fields that are either mandatory or optional. Contact Inbound for the field names relevant to your setup.
data.attachmentsArray of objects about the attachments attached to a booking.The object in this array will have a fileName, attachmentType (optional), and url. The url will be a time limited secure download URL from where you can retrieve the actual attachment.

Example

{
	"id": "9fb10566-3fbd-4149-a6c5-5c24b7d1381f",
	"event": "App.BookingCreatedOrUpdated",
	"attempt": 2,
	"data": {
		"bookingNumber": "INBFAC2107161",
		"facility": "Inbound Facility",
		"service": "FAK Import Pickup",
		"bookingDate": "2021-07-16",
		"startTimeWindow": "09:00",
		"endTimeWindow": "09:59",
		"status": "CancelledBySystem",
		"transporter": "Inbound Transporter",
		"guestName": null,
		"guestEmail": null,
		"PreProcessed": null,
		"cancellationReason": "Booking automatically cancelled by Inbound – no show",
        "baseAmount": 15.00,
        "taxAmount": 1.5,
        "totalIncludingTax": 16.50,
		"fields": [
			{
				"field": "Vehicle Rego",
				"value": "VEH123"
			},
			{
				"field": "Container No.",
				"value": "MSKU1234565"
			},
			{
				"field": "AIMS Number",
				"value": ""
			},
			{
				"field": "House BL",
				"value": "HOUSEBL12345"
			},
			{
				"field": "Special Instructions",
				"value": ""
			},
			{
				"field": "UOM",
				"value": ""
			},
			{
				"field": "Vessel",
				"value": ""
			},
			{
				"field": "No. of Units",
				"value": ""
			}
		],
        "attachments": [
            {
                "fileName": "Test File 1.pdf",
                "url": "https://securedownload.blob.core.windows.net/inbound-attachments/aaaaaaaa-bbbb-cccc-eeee-ffffffff_Test_File_1.pdf?sv=xxxxxx"
            },
            {
                "fileName": "Test File 2.docx",
                "attachmentType": "Delivery order",
                "url": "https://securedownload.blob.core.windows.net/inbound-attachments/11111111-2222-3333-4444-55555555_Test_File_2.docx?sv=xxxxxx"
            }
        ]
	},
	"creationTimeUtc": "2021-07-17T13:06:44.2650968Z"
}
This event is triggered whenever a draft booking is created or updated for your company.
FieldDescriptionComments
idUnique ID for this event.
eventName of the event that generated this message.App.DraftBookingCreatedOrUpdated always for this event type.
attemptNumber of attempts it took to call your webhook endpoint.
creationTimeUtcDate time of the message creation.In coordinated universal time (UTC)
dataAn array of draft bookings with statusComprised with the draft booking request and the result for each request
data[].transporterCodeThe transporter code that was part of the request
data[].transporterNameName of the transporterIf the requested transporterCode resolved
data[].errorBoolean value representing whether any error has occurred or notTrue or False, see the errorDetails or status of the bookingDetails for details when the value is ‘False’
data[].errorDetailsList of validation errors, if the value of error is true
data[].bookingDetails[]Details of the transporter
data[].bookingDetails[].externalReferenceIdUnique identification that was part of the request
data[].bookingDetails[].estimatedBookingDateEstimated booking date that was part of the request
data[].bookingDetails[].secondaryCapacityFieldNameName of the secondary capacity field
data[].bookingDetails[].secondaryCapacityQuantityQuantity of the secondary capacity
data[].bookingDetails[].errorBoolean value representing whether any error has occurred or notTrue or False, see the errorDetails for details when the value is ‘False’
data[].bookingDetails[].errorDetailsList of validation errors, if the value of error is true
data[].bookingDetails[].actionState the action it performed‘Updated’ if it finds a matching record with the given externalReferenceId, otherwise ‘Created’
data[].bookingDetails[].facilityCodeThe facility code that was part of the request
data[].bookingDetails[].facilityNameName of the facilityIf the requested facilityCode was resolved
data[].bookingDetails[].facilityServiceCodeThe facility service code that was part of the request
data[].bookingDetails[].facilityServiceNameName of the facility serviceIf the requested facilityServiceCode was resolved
data[].bookingDetails[].fieldsList of fields that were part of the request
data[].bookingDetails[].fields[].nameName of the field
data[].bookingDetails[].fields[].valueValue of the field

Example

{
	"id": "3699a8be-c423-4eb5-9ceb-64cffb0e54b1",
	"event": "App.DraftBookingCreatedOrUpdated",
	"attempt": 2,
	"data": [
		{
			"transporterCode": "InboundTransporter",
			"transporterName": "Inbound Transporter",
			"error": false,
			"errorDetails": [],
			"bookingDetails": [
				{
					"facilityCode": "INBFAC",
					"facilityName": "Inbound Facility",
					"facilityServiceName": "FAK Import Pickup",
					"facilityServiceCode": "FAKPICK",
					"externalReferenceId": "REF101",
					"error": false,
					"errorDetails": [],
                    "estimatedBookingDate": "2021-08-01T10:10:00+10:00",
					"action": "Updated",
					"fields": [
						{
							"name": "Your Ref",
							"value": "This is your reference"
						},
						{
							"name": "Vehicle Rego",
							"value": "REGO123"
						},
						{
							"name": "Container No.",
							"value": "MSDU8046775"
						},
						{
							"name": "House BL",
							"value": "TESTHOUSEBL"
						},
						{
							"name": "Special Instructions",
							"value": "Optional special instructions"
						},
						{
							"name": "Vessel",
							"value": "9307023 - OOCL DUBAI"
						}
					],
					"attachments": [
						{
							"fileTypeCode": "POP",
							"fileName": "Test01.pdf"
						},
						{
							"fileTypeCode": "POP",
							"fileName": "Test02.pdf"
						}
					]
				}
			]
		}
	]
}
This event is triggered whenever an additional charge is created or updated for your company.
FieldDescriptionComments
idUnique ID for this event.
eventName of the event that generated this message.App.AdditionalChargeCreatedOrUpdated always for this event type.
attemptNumber of attempts it took to call your webhook endpoint.
creationTimeUtcDate time of the message creation.In coordinated universal time (UTC)
data.additionalChargeIdUnique ID assigned to this additional chargeInteger value and won’t change once additional charge is created
data.facilityName of the facility this additional charge was for.
data.chargeCodeCharge code.The charge code used for this additional charge.
data.chargeCodeDescriptionCharge code description.
data.fieldNameName of the field additional charge is linked toAdditional charges can be linked either directly to a booking or through a particular field (usually HBL or similar). May not be specified if not linked to a field.
data.fieldValueWhen an additional charge is linked through a field such as HBL this is the value that it’s linked to (Eg: this is the actual HBL number).
data.bookingNumberThe current booking number this additional charge is linked to.Can be empty if the booking the charge was originally linked to was cancelled by the charge was already paid.
data.facilityServiceThe type of service that the booking linked to this additional charge was for.
data.bookingDateDate the booking was for.Format will be yyyy-mm-dd.
data.transporterName of the transporter currently responsible for paying the additional charge.This is linked through the booking that was made by this transporter.
data.paidBoolean representing if this additional charge been paidTrue or False
data.paidDateTimeDate and time when the additional charge was paidIn coordinated universal time (UTC)
data.cancelledBoolean representing if this additional charge was cancelledTrue or False
data.cancellationReasonUser entered reason for why the additional charge was cancelled
data.baseAmountPre-tax amount charged for this additional charge.
data.taxAmountTax amount calculated for this additional charge.
data.totalIncludingTaxTotal amount applied to this additional charge including any taxes.
data.commissionTotal amount of commission (ex tax) applicable to this additional charge.

Example

{
    "id": "3699a8be-c423-4eb5-9ceb-64cffb0e54b1",
    "event": "App.AdditionalChargeCreatedOrUpdated",
    "attempt": 2,
    "data": [
        {
            "facility": "Inbound Facility",
            "chargeCode": "STORAGE",
            "chargeCodeDescription": "FAK Storage charges",
            "fieldName": "House BL.",
            "fieldValue": "HBL123456",
            "bookingNumber": "INBFAC20020101",
            "facilityService": "Pickup",
            "bookingDate": "2023-01-10",
            "transporter": "Inbound Transporter",
            "paid": true,
            "paidDateTime": "2023-01-13 23:23:57.089925",
            "cancelled": false,
            "cancellationReason": "",
            "baseAmount": 100,
            "taxAmount": 10,
            "totalIncludingTax": 110,
            "commission": 10,
        }
    ]
}
                                        

There are two approaches to ensuring security of the webhooks coming into your system.

  1. When creating your webhook subscription you have the option of providing a custom HTTP header that will be sent along with the request. You can provide your own custom Authentication/Authorization header with a unique secret key that your receiving system will validate is correct before processing the webhook. This is recommended for all webhook subscriptions and you must ensure your receiving system is a HTTPS endpoint to protect the security of your HTTP headers from evesdropping.
  2. In addition to the custom HTTP header, the system will provide an SHA256 hash of the body of your webhook to ensure it has not been tampered with after being sent by Inbound. The HTTP header will be called “abp-webhook-signature” and have a value similar to “sha256=05-93-50-D7-EE-8E-0C-16-B3-82-D3-D0-A6-5F-DA-8D-CD-43-D1-05-A6-57-F5-28-03-FD-78-AC-55-AB-8C-11”.

    Once you have created your webhook subscription, from within Inbound click “Details” next to the subscription to allow you to retrieve the secret key used to create the SHA hash. (Click View Webhook Secret)

This secret key should be used to generate an SHA256 hash of the body and compare it to the header received with the message. If the hashes do not match then the message may have been tampered with and should be ignored. Example C# code on how to compare the hashes can be found here: https://aspnetboilerplate.com/Pages/Documents/Webhook-System#check-signature

Share the Post:

Ready to take your logsitics business to the next level?

Reach out and request a demo today.