Webhooks

Receiving webhooks from the GraphQL API

Depending on your use case for the GraphQL API you may wish to have your application notified when data has been updated or a certain event occurs within the Ideavate platform.

We support these notifications in the form of webhook POST requests to your application.

We have harnessed the power and flexibility of GraphQL and provide a mechanism whereby you can choose which exact information you want to receive in the notification.

The process within the platform is as follows:

  1. Trigger is fired within Ideavate platform

  2. The platform makes a GraphQL query on your behalf

  3. The platform POSTs the GraphQL response to your server

This way you can choose to receive as much or as little information as you require.

GraphQL webhooks vs subscription

Whilst GraphQL has the concept of subscriptions, currently there is no standard way to deliver those subscription updates to you via HTTP. GraphQL subscriptions are usually managed via websockets which are not a good fit for typical users of our API.

You can think of our GraphQL webhook implementation as being like a statically configured GraphQL subscription that is delivered via HTTP POST.

Triggers

Webhooks are triggered when a particular action occurs on an entity in the Ideavate platform.

The triggers are named using the convention . e.g. when a User is added a UserAdded trigger occurs.

Available triggers include:

GraphQL entityActionTrigger name

User

Added

UserAdded

User

Deleted

UserDeleted

Account

Updated

AccountAdded

Document

Added

DocumentAdded

ToDo

Added

ToDoAdded

ToDo

Done

ToDoDone

EnergySwitch

Added

EnergySwitchAdded

EnergySwitch

Updated

EnergySwitchUpdated

We can enable triggers for most entities and actions so if the one you want isn't in the above table then let us know and we will enable it for you.

Request format

Requests are made as HTTP POST with an application/json body. The JSON body will contain the following properties:

PropertyTypeDescription

webhook.id

string

A unique ID for this webhook request. Can be used for deduplication.

webhook.trigger

string of trigger name

The trigger that caused this webhook request.

webhook.date

string of ISO8601 date time

The date when the webhook was triggered.

query.api

string

The GraphQL endpoint that the query was executed against.

query.query

string

The GraphQL query that was executed.

query.variables

object

The GraphQL variables used in the query.

data

object

The GraphQL response itself. The structure will depend on the configured query. Please refer to the main Data Model documentation.

A sample request made after an energy switch is triggered is as follows:

POST /ideavate/callback HTTP/1.1
Connection: close
Host: server.customer.com
Content-Length: 1083
X-Signature: sha1=663b472bc3213d6a60f622687060610d71ca2530
User-Agent: ideavate@live/2.0.0
Content-Type: application/json
Accept: application/json, text/plain, */*

{
"data": {
    "getEnergySwitch": {
      "__typename": "EnergySwitch",
      "id": "602cd86f3755d621aff583ee",
      "date": "2018-01-01T00:00:00.000Z",
      "user": {
        "id": "5e33114d08cb368661c5108d",
        "tenantId": null
      },
      "userSwitchReferenceId": "E123456",
      "postcode": "OX184EN",
      "provider": {
        "code": "pfp-energy_pfp-energy",
        "name": "PFP Energy"
      },
      "tariffName": "PFP Energy - Green Variable v1 Paperless",
      "projectedSpend": {
        "currency": "GBP",
        "amount": 123.540000915527
      },
      "savings": {
        "currency": "GBP",
        "amount": 228.449996948242
      },
      "fuelType": "Elecgas",
      "fuelsSwitched": 2,
      "commission": {
        "fuelsWaitingForUpdate": 0,
        "fuelsWithSwitchTerminated": 0,
        "fuelsWithCommissionExpected": 2,
        "fuelsWithCommissionReceived": 0,
        "statusDate": "2018-01-22T00:00:00.000Z",
        "status": "commissionExpected"
      }
    }
  },
  "query": {
    "api": "https://api.ideavate.co/v1/graphql",
    "query": "query ($id: ID!) { getEnergySwitch(id: $id) { __typename ... on OperationFailure { description(locale: en_GB) } ... on EnergySwitch { id date user { id tenantId } userSwitchReferenceId postcode provider { code name } tariffName projectedSpend { currency amount } savings { currency amount } fuelType fuelsSwitched commission { fuelsWaitingForUpdate fuelsWithSwitchTerminated fuelsWithCommissionExpected fuelsWithCommissionReceived statusDate status } } }}",
    "variables": {
      "id": "602cd86f3755d621aff583ee"
    }
  },
  "webhook": {
    "id": "egohOhl0CgOx1FztKdKBjYU1TWWzy2kqBqqmWBhUQRU=",
    "date": "2021-02-17T08:48:47.284Z",
    "trigger": "EnergySwitchAdded"
  }
}

The HMAC-SHA1 shared secret used for this example request was sharedSecret.

JSON formatting

For readability the JSON body of this request has been pretty formatted. For real requests the ordering and whitespace are not guaranteed.

Verifying requests

You should validate that the POST requests you receive are genuine requests from the Ideavate platform.

To do so, it is recommended that you make use of the request signing feature. When enabled, the JSON body of the request will be signed using a shared key. The hex encoded HMAC-SHA1 is placed in the X-Signature HTTP request header.

On receipt of a request you should then calculate the HMAC-SHA1 for the received request body using the shared key, and compare it to the one given in the X-Signature header.

Expected response

Your server is expected to return an HTTP 200 response within 30 seconds (lower timeouts can be configured if you wish).

Requests returning a non-200 response will be retried for 72 hours before permanently failing.

Provisioning webhooks

We will need the following information to get the webhook provisioned in the platform:

DescriptionNotes

Triggers to receive requests for

You can have different queries for each trigger, or have a common query.

HTTPS URL to receive POST request

This must be an HTTPS endpoint with a certificate from a commonly trusted Certificate Authority. The URL can contain query parameters if needed.

GraphQL query to be executed

See recommended queries below.

Shared key for HMAC-SHA1 signature

Recommended.

EnergySwitch

Full details of a new switch:

query($id: ID!) {
  getEnergySwitch(id: $id) {
    __typename
    ... on OperationFailure {
      description(locale: en_GB)
    }
    ... on EnergySwitch {
      id
      date
      user {
        id
        tenantId
      }
      userSwitchReferenceId
      postcode
      provider {
        code
        name
      }
      tariffName
      projectedSpend {
        currency
        amount
      }
      savings {
        currency
        amount
      }
      fuelType
      fuelsSwitched
      commission {
        fuelsWaitingForUpdate
        fuelsWithSwitchTerminated
        fuelsWithCommissionExpected
        fuelsWithCommissionReceived
        statusDate
        status
      }
    }
  }
}

Minimal details of a switch where you plan to make GraphQL requests to lookup more details:

query($id: ID!) {
  getEnergySwitch(id: $id) {
    __typename
    ... on OperationFailure {
      description(locale: en_GB)
    }
    ... on EnergySwitch {
      id
      date
    }
  }
}

Updated switch with latest commission status:

query($id: ID!) {
  getEnergySwitch(id: $id) {
    __typename
    ... on OperationFailure {
      description(locale: en_GB)
    }
    ... on EnergySwitch {
      id
      commission {
        fuelsWaitingForUpdate
        fuelsWithSwitchTerminated
        fuelsWithCommissionExpected
        fuelsWithCommissionReceived
        statusDate
        status
      }
    }
  }
}

Last updated