Midoffice Order Status Webhook

Order changes Webhook

POST

If you work with your Agency/TMC as a midoffice, Emerging Travel Group can send HTTP POST to your endpoint in case of creation/cancellation/change of any order of your Agency/TMC. If you would like Emerging Travel Group to POST the status of the order, you need to provide an endpoint URL to the API Support Team.

For Webhook POSTs, Emerging Travel Group listens for the following codes from your server and reacts accordingly:

  • If Emerging Travel Group receives a 200 (Success) code it will determine the webhook POST is successful and not retry.
  • If Emerging Travel Group receives a 500 (Server Error) code, Emerging Travel Group will retry POSTing according to the schedule below.

If your application is unable to process the webhook request, Emerging Travel Group will retry according to the following schedule:

  • after 30 seconds
  • after 60 seconds
  • after 90 seconds
  • after 120 seconds
  • after 150 seconds
  • after 300 seconds
  • after 1 hour
  • every 12 hours for 7 days (total of 14 attempts)

Payload

When an order is created/cancelled/changed by a partner with the specified Midoffice, a callback is triggered and sent to the endpoint specified by the Midoffice.

agreement_number String optional
Contract’s agreement number.
partner_order_id String required

Identifier of the booking (at the partner) made by the partner.

ℹ️
  • The minimum length is 1 character.
  • The maximum length is 256 characters.
type String required

The type of event that caused the callback.

ℹ️

The possible values:

  • updated.
  • cancelled.
  • created.

Payload example

{
  "type":"updated",
  "agreement_number":"B2B-12345/1",
  "partner_order_id":"asd123"
}

Secure data

signature String required
The hexadecimal digits generated by the HMAC algorithm.
timestamp Int required
The date and time of creating a webhook token in the Unix Timestamp format. You can find it in the token signature when decoding. The minimum date is January 1, 1970.
token String required
The randomly generated string with a length of 50.

Secure data example

{
  "signature": {
    "signature": "7865d225dbee1b54909er153d193e0b57b707ebe81ff5b2e1b71ebaf749bec23",
    "timestamp": 1574146939,
    "token": "d3395025-1ee7-49a2-bd86-e4bd6b9908b2"
  }
}

Whole fields example

{
  "data": {
    "partner_order_id": "qwerty123",
    "status": "completed"
  },
  "signature": {
    "signature": "7865d225dbee1b54909er153d193e0b57b707ebe81ff5b2e1b71ebaf749bec23",
    "timestamp": 1574146939,
    "token": "d3395025-1ee7-49a2-bd86-e4bd6b9908b2"
  }
}

Signature verification

To verify the webhook issued by the ETG:

  1. Concatenate the timestamp and token values. The “token” means the one sent by the ETG in the webhook data.

  2. Encode the resulting string with the HMAC algorithm:

    1. Use your API Key token as a key.
    2. Use the SHA256 digest mode.
  3. Use the hexdigest() method to make a resulting string.

  4. Compare the resulting string to the signature.

  5. Optional. Cache the token locally and don’t honor any subsequent request with the same token. This will prevent replay attacks.

  6. Optional. Check that the timestamp is within the token lifetime.

Examples

Python

import hashlib, hmac
def verify(api_key, token, timestamp, signature):
    hmac_digest = hmac.new(key=api_key,
                           msg='{}{}'.format(timestamp, token),
                           digestmod=hashlib.sha256).hexdigest()
    return hmac.compare_digest(unicode(signature), unicode(hmac_digest))

Ruby

require 'openssl'
def verify(api_key, token, timestamp, signature)
  digest = OpenSSL::Digest::SHA256.new
  data = [timestamp, token].join
  signature == OpenSSL::HMAC.hexdigest(digest, api_key, data)
end

PHP

function verify($apiKey, $token, $timestamp, $signature)
{
  // check if the timestamp is fresh
  if (abs(time() - $timestamp) > 15) {
    return false;
  }
  // returns true if signature is valid
  return hash_hmac('sha256', $timestamp . $token, $apiKey) === $signature;
}

Node.js

const crypto = require('crypto')
const verify = ({ apiKey, timestamp, token, signature }) => {
    const encodedToken = crypto
        .createHmac('sha256', apiKey)
        .update(timestamp.concat(token))
        .digest('hex')
    return (encodedToken === signature)
}