Receiving signals

Introduction

You have to subscribe to a webhook event to receive signals updates from a vehicle.

Updates will be sent at the endpoint provided at subscription time.

📘

Info

If you don't remember what a signal is, visit the Signals guide's page.

The following diagram explains the process of subscribing, receiving events, and unsubscribing via the webhook endpoint.

User Adapter subscription challenge Your callback should return the challenge string in string/text format loop [Every new datapoint] remove subscription POST/webhook("subscribe",topic,callback,secret) GET/callback("subscribe",topic,challenge) string/text(challenge) Success/Failure POST/callback(topic,payload) Success/Failure POST/webhook("unsubscribe",topic,callback,secret) Success/Failure User Adapter

To subscribe to the events, the request will consist of the following:

POST
https://adapter.2hire.io/api/v1/webhook

Body parameters table:

ParameterTypeDescription
'hub.mode'subscribe OR unsubscribesubscribe to subscribe to the channel, unsubscribe in the other case.
'hub.topic'stringThe topic of interest.
'hub.callback'stringYou'll receive the challenge and the webhooks at this URL.
'hub.secret'stringThe secret used to generate the webhook signature.

e.g.

{
    "hub.mode":"subscribe",
    "hub.topic":"vehicle:'UUID':generic:position",
    "hub.callback":"https//:example.com",
    "hub.secret":"A secret of your choice"
}

🚧

Warning

The parameter (hub.mode) is the actual properties name and not a body point notation.


📘

Info

To better understand this pattern visit this link.

There are multiple events you can subscribe to. Check the following section to understand how they are defined.



Topic

This section explains how the topic is defined.

The structure is the following:
vehicle:$vehicleId:$signalType:$signalName

ParameterPositionDescription
vehicle1Always vehicle string.
$vehicleId2The vehicle's id. You can use the wildcard * to subscribe to all the client's vehicles.
$signalType3The signal's type: generic or specific.
$signalName4The signal's name. You can use the wildcard * to subscribe to all the generic signals.

e.g. Using vehicle id 26c1097a-45d7-4719-a195-595c252a16f7 and signal position

vehicle:26c1097a-45d7-4719-a195-595c252a16f7:generic:position



Challenge

The endpoint provided at subscription time will be called to check the URL validity.


The request will consist of the following:

GET
https://example.com

You'll substitute https://example.com with your URL.


Headers table:

HeaderValueDescription
Content-Type'application/json'The body is in JSON format.

Query parameters table:

ParameterTypeDescription
hub.modestringAlways subscribe.
hub.topicstringThe topic of interest.
hub.challengestringA random string generated by our system.
This value should be returned from your system in a string/text format.

Example challenge for vehicle:'UUID':generic:position topic.

UserAdapterGET/callback("subscribe","vehicle:'UUID':generic:position","thisIsARandomString")"thisIsARandomString"UserAdapter


Webhook

You receive signals at the endpoint provided at subscription time.


The call will consist of the following:

POST
https://example.com

You'll substitute https://example.com with your URL.


Headers table:

HeaderTypeDescription
X-Idempotency-KeystringThe message identifier. In case of a retry the same ID will be sent.
X-Hub-SignaturestringThe message signature generated from the client provided secret.
User-Agentstring2AA/WebhookPub/SenderHttp : our user agent.
Content-Type'application/json'The body is in JSON format.

Body table:

NameExampleDescription
topicvehicle:ebd00051-b465-4ce6-82dd-74fbe9725e95:generic:positionThe message identifier. In case of retry it'll be sent the same ID.
payload"timestamp": 1610721676241, "data":{"latitude": 3232, "longitude": 5454}The signal's value.

User's system has to answer within a predefined timeout (10 seconds), and it has to return Status OK (HTTP 200).

In case of error, we'll try again two times.

If the user's system fails to answer several times, we'll stop sending messages for a predefined amount of time.

This happens until the user's system can successfully receive messages. After that, the system resumes normal behaviour.



Messages signature calculation

Message's X-Hub-Signature is generated as follows:

import * as crypto from "crypto";

const generateSignature = (message: string, secret: string, algorithm: string): string => {
    if (!secret) {
      return "";
    }
    const hmac = crypto.createHmac(algorithm, secret);
    hmac.update(message, "utf8");
    return `${algorithm}=${hmac.digest("hex")}`;
}

const signature = generateSignature(body, secret, "sha256");
import hashlib
import hmac

def generate_signature(body: str, secret: str, algorithm) -> str:

    if secret is None:
        return ""

    h = hmac.new(secret.encode('utf-8'), body.encode('utf-8'), algorithm)

    return "sha256=" + h.hexdigest()

signature = generate_signature(body, secret, hashlib.sha256)

It uses the HMAC-SHA256 algorithm to create the signature from the JSON body.

The key is the one provided at subscription time.

📘

Info

If you want to test the contents of this guide, please refer to our testing environment.

📘

Do you need some help?

To help you manage to receive signals from our system, we produced some tutorials and cookbooks to help you understand this topic.
Visit: