Skip to content

Automated data delivery

Data delivery can be automated using subscriptions.

Subscriptions currently support real-time notifications via webhooks or emails.

Users can specify multiple subscriptions for a project for multiple events. Once a new real-time subscription is specified, events relating to that project will be submitted to the target URL in JSON format via HTTP POST requests in case of a webhook notification, or via email otherwise.

After creating a subscription, users can view the subscription notification history and additional information such as response status and payload in the Gencove web UI.

Currently, legacy webhook format and an updated format are supported. New event types will only support new format.

Once a webhook is received, the receiver is responsible for querying the Gencove API for more details on each object that is referenced. For example, upon receiving a analysis_complete_v2 webhook for a project, the receiver should query the Gencove API for additional sample details and fresh download URLs for deliverables related to those samples.

Available event types and webhook format

The content of the webhook contains a list of event objects where each event has the following keys:

  • event_id, a unique identifier of the event
  • event_type, describing the type of event
  • payload, event-specific webhook contents
  • timestamp

The following events are available:

  • analysis_complete_v2
    • this event describes the completion of analysis on samples belonging to a project. The webhook payload will contain the respective project_id and a list of samples.
  • batch_final_report_complete_v2
    • this event describes the completion of creation of "Backwards-compatible array deliverables"
[
  {
    "event_id": "0b2d7502-86b0-863e-11e2-990d0e134e8a",
    "event_type": "analysis_complete_v2",
    "timestamp": "2021-04-09T12:01:26.346341Z",
    "payload": {
      "project": {
        "id": "1d6daca6-475a-4961-9841-57aac36cbd0f"
      },
      "samples": [
        {
          "id": "45273390-64bd-4a07-a1be-8514d3ba7750",
          "client_id": "HumanS01-001",
          "last_status": {
            "status": "succeeded"
          }
        }
      ]
    }
  }
]
[
  {
    "event_id": "bdc558af-4815-7736-8bab-9be8c5f63fff",
    "event_type": "batch_final_report_complete_v2",
    "timestamp": "2021-04-09T12:01:26.346341Z",
    "payload": {
      "project": {
        "id": "1d6daca6-475a-4961-9841-57aac36cbd0f"
      },
      "batch": {
        "id": "77799c11-aa57-4a06-aa17-978d203f1eb5",
        "name": "Batch 001",
        "last_status": {
          "status": "succeeded"
        }
      }
    }
  }
]

Available legacy event types and webhook format

Please note that users are highly encouraged to use the updated format. We are planning to sunset legacy format at a later date. Please follow our blog or our mailing list for more information about this in the future.

The content of the legacy webhook contains the following keys:

  • event, describing the type of event
  • payload, event-specific webhook contents
  • object_id, a unique identifier for the originating object of the webhook
  • timestamp

Together, object_id and event should be considered unique and duplicates should be handled by the receiver.

The following legacy events are available:

  • analysis_complete

    • this event describes the completion of analysis on samples belonging to a project. The webhook payload will contain the respective project_id and a list of sample_ids.
  • batch_final_report

    • this event described the completion of creation of "Backwards-compatible array deliverables"
{
    "event": "analysis_complete",
    "object_id": "99573a16-98a8-48fc-8caf-e3b4dcdf34e6",
    "timestamp": "2018-11-18T14:09:59.741183",
    "payload": {
        "project_id": "1d6daca6-475a-4961-9841-57aac36cbd0f",
        "sample_ids": [
            "45273390-64bd-4a07-a1be-8514d3ba7750"
        ]
    }
}
{
    "event": "batch_final_report",
    "object_id": "99573a16-98a8-48fc-8caf-e3b4dcdf34e6",
    "timestamp": "2018-11-18T14:09:59.741183",
    "payload": {
        "project_id": "1d6daca6-475a-4961-9841-57aac36cbd0f",
    }
}

Webhook signatures

Gencove can optionally sign webhook events it sends to endpoints. This is done by including a signature in each event’s Gencove-Signature header, allowing you to verify that the events were sent by Gencove.

Before verifying signatures, webhooks need to be enabled and the secret needs to be retrieved for each project via the Gencove API (API reference). Note that each subscription has a separate unique secret.

After this setup, Gencove automatically starts signing each webhook notification it sends to the endpoint of the related project.

Verifying webhook signatures

The Gencove-Signature header contains a timestamp and a signature:

  • the timestamp is an integer representing UNIX time and is prefixed by t=
  • the signature is prefixed by a scheme, which starts with v and is followed by an integer. Currently, the only valid signature scheme is v1.

Example signature: Gencove-Signature: t=1492774577,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Gencove generates signatures using a hash-based message authentication code (HMAC) with SHA-512. To prevent downgrade attacks, you should ignore all schemes that are not v1.

There are multiple ways to verify a signature, there is a command available in the Gencove CLI, it can be done directly from the python console or from any other tool that can generate a HMAC with SHA-512.

Step 1: Extract the timestamp and signatures from the header

Split the header, using the , character as the separator, to get a list of elements. Then split each element, using the = character as the separator, to get a prefix and value pair.

The value for the prefix t corresponds to the timestamp, and v1 corresponds to the signature.

Step 2: Prepare signature_message

This is achieved by concatenating:

  1. The timestamp (as a string)
  2. The character .
  3. The actual JSON payload (i.e., the request’s body)

Step 3: Determine the expected signature

Compute an HMAC with the SHA512 hash function. Use the endpoint’s signing secret as the key and the signature_message string as the message.

Step 4: Compare signatures

Compare the signature in the header to the expected signature. If a signature matches, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.

export SECRET='super-secret'
export HEADER='t=1492774577,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd'
export PAYLOAD='{"k":"v"}'
gencove webhooks verify $SECRET $HEADER $PAYLOAD
import hmac, hashlib

def calculate_signature(secret, timestamp, payload):
    signature_message = "{}.{}".format(timestamp, payload).encode("utf-8")
    return hmac.new(
        secret.encode("utf-8"),
        signature_message,
        hashlib.sha512
    ).hexdigest()
Back to top