Webhooks

Use webhooks to get real-time updates

Getting Started with Webhooks

API.audio uses webhooks to notify your application when an event happens in your organization. Webhooks are particularly useful for asynchronous events like when producing audio files that take a long time to process.

What are webhooks?
Webhooks are a way that an application can send automated information to other applications.
With API.audio, you can use webhooks to push real-time notifications to your app and send data to your app when your audio (speech or mastering) file is ready to be served. API.audio uses HTTPS to send these notifications to your app as a JSON payload.

When to use webhooks?
Use webhooks when your use case is related to mass production of audio and serving time isn't critical:

  • In case your file takes longer than 30 seconds (our API connection limit) to be served, using webhooks you'll get notified when your file is ready instead of pooling the status of your file.
  • Generally, scripts longer than 10k characters take longer than 30 seconds to be produced. In those cases, connect to our webhooks feature and get notified when your files are ready
  • If you would like to send your files (no matter how big or small) to a connector/distributor (like Zapier, Slack, Workato, etc.) use the webhooks feature
  • If you wish to create your files asynchronously, start the order of your files and instead of checking back on each of them, you'll get notified when they are ready

Receive webhook events

Steps to receive webhooks

Step 1: Create your custom webhook endpoint as an HTTP endpoint (URL) on your local server. You can do this in one out of 2 ways→

  1. Define default callback URL in the developer console
    Access your developer console and navigate to account settings (https://console.api.audio/account-settings). Save the webhook URL. If there is a webhook URL set for your organization, you will receive notifications for every production request.
1232
  1. Pass the callback_url in the create call
    Simply pass a callback_url parameter in the body object while creating a mastering or speech request. In this case, the event data is sent to this URL instead of the default callback URL.

When an event occurs in API.audio, we'll POST to your URL with a payload of JSON-encoded data.

Step 2: Handle requests from API.audio

Your endpoint must be configured to read event objects for the type of event notifications you wish to receive. API.audio sends events to your webhook endpoint as part of a POST request with a JSON payload.

Each event is structured as an event object with a type, eventId, requestId and related resource nested under data.

{
  "eventId": "a unique event id provided for idempotence",
  "requestId": "the initial request id that user made, mostly for logging purposes",
  "type": "speech or mastering",
  "data": {
    "startedAt": "event start in unix timestamp",
    "createdAt": "event end in unix timestamp",
    "statusCode": "our engines' response code",
    "success": "true or false",
    "downloadUrl": "a short url to download the file",
    "message": "our engines's response message"
  }
}

Step 3: Respond to webhook

To acknowledge that you received the webhook without any problem, your server should return a HTTP 2xx status code. Any other information you return in the request headers or request body will be ignored. Once you reply with an HTTP 2xx/3xx/4xx we will mark the webhook as sent.
If you reply with an HTTP 5xx code, we will mark the webhook as failed.
Your server must respond within 15 seconds to prevent a timeout error.

Step 4: Retries

If we are unable to reach your server for any reason — such as a connection error or timeout — we will attempt to deliver the webhook over the next few days with an exponential backoff. If your server response is a 5xx, internal server error, this means they might be having a temporary downtime. In this case, we try to send the same event up to 5 times. In the case of 2xx, 3xx or 4xx status codes; we don't retry sending.
It is possible to manually retry a failed webhook. You can do so through the developer console or using /webhooks/retry endpoint.

Failures will only affect that particular webhook event, not the webhook endpoint. We will continue to attempt sending new events to your webhook endpoint, even if previous webhook events have failed.

Step 5: Test that your webhook URL is working properly

There are several ways to test that your webhook endpoint is working properly before taking it live:

  1. Create test activity on your account
    1.1 First, add the endpoint to your account.
    1.2 Take some action, for example creating a mastering request through your developer console or locally.

  2. Manually send test events from your account
    2.1 First, add the endpoint to your account.
    2.2 After adding the endpoint, click the Test button.

📘

Note that test webhooks will also show up in the Webhook Event Log in your account.

Events Overview

API.audio current supports webhooks for speech create and mastering create events

Potential Status Codes

An event can be in one of the following states: awaiting, sent, failed and error.

awaiting: The event is added to the queue for execution.
sent: The event is sent and the client server responded a 2xx, 3xx or 4xx status code. the event is manually
retriable in the console or with the http endpoint.
failed: The event is sent and the client server responded a 5xx status code. the retrial mechanism will work. the event is manually retriable in the console or with the http endpoint.
error: The event could not be sent due to an error in the callback URL, either it is not a valid server URL or it is suspected to be malicious. the retrial mechanism won't work, and the event is not manually retriable in the console.

Troubleshooting

We recommend using Mockbin or Webhook.site to troubleshoot webhooks.

Sample Payloads

A sample event payload is structured as such -->

{
  "eventId": "a unique event id provided for idempotence",
  "requestId": "the initial request id that user made, mostly for logging purposes",
  "type": "speech or mastering",
  "data": {
    "startedAt": "event start in unix timestamp",
    "createdAt": "event end in unix timestamp",
    "statusCode": "our engines' response code",
    "success": "true or false",
    "downloadUrl": "a short url to download the file",
    "message": "our engines's response message"
  }
}

Exceptions made for some popular webhook listening services:

Zapier: The URL is turned into an object as follows

{
  "eventId": "a unique event id provided for idempotence",
  "requestId": "the initial request id that user made, mostly for logging purposes",
  "type": "speech or mastering",
  "data": {
    "startedAt": "event start in unix timestamp",
    "createdAt": "event end in unix timestamp",
    "statusCode": "our engines' response code",
    "success": "true or false",
    "downloadUrl": { "url": "a short url to download the file" },
    "message": "our engines's response message"
  }
}

Slack: The event is dumped into a json and sent in text field.

{
  "text": "{'eventId':'a unique event id provided for idempotence','requestId':'the initial request id that user made, mostly for logging purposes','type':'speech or mastering','data':{'startedAt':'event start in unix timestamp','createdAt':'event end in unix timestamp','statusCode':'our engines response code','success':'true or false','downloadUrl':{'url':'a short url to download the file'},'message':'our engines's response message'}}"
}

Verify Signatures

Verify the events that API.audio sends to your webhook endpoints.

API.audio can optionally sign the webhook events it sends to your endpoints by including a signature in each event’s Signature header. This allows you to verify that the events were sent by API.audio, not a third party.

It is called X-Aflr-Secret and it is something like t={x},v1={y}
Here, {x} means the timestamp event is made, and {y} means the SHA256 integrity hash. At the moment, we follow the v1 schema. This allows us to quickly take actions in a scalable manner, in case we find a security leak in our headers.

We highly recommend using our SDKs to support verifying these headers.

Python SDK reference

Javascript SDK reference

If you want to manually verify the signatures, follow these steps:

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. You can discard all other elements.

Step 2: Prepare the signed_payload string

The signed_payload string is created by concatenating:

  • The timestamp
  • The character .
  • The actual JSON payload (i.e., the request body)

Step 3: Determine the expected signature

Compute an HMAC with the SHA256 hash function. Use the project's signing secret as the key, and use the signed_payload string as the message.

Step 4: Compare the signatures

Compare the signature in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.
To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures.

Preventing replay attacks
A replay attack is when an attacker intercepts a valid payload and its signature, then re-transmits them. To mitigate such attacks, API.audio includes a timestamp in the X-Aflr-Signature header. Because this timestamp is part of the signed payload, it is also verified by the signature, so an attacker cannot change the timestamp without invalidating the signature. If the signature is valid but the timestamp is too old, you can have your application reject the payload.

Your tolerance for what it means to be too old is up to you. We recommend using Network Time Protocol (NTP) to ensure that your server's clock is accurate and synchronizes with the time on API.audio’s servers.

API.audio generates the timestamp and signature each time an event is sent to your endpoint. If API.audio retries an event (e.g., your endpoint previously replied with a 5xx status code), then a new signature and timestamp is generated for the new delivery attempt.

Webhook related endpoints

GET /webhooks/logs

description: gets the logs for latest webhook events for the organization, up to 500 entries.

POST /webhooks/retry

parameters: body with event id in it

"body": {
  "eventId": "s4l1h-1s-th3-b3st-0f-b3st"
}

method: post
description: tries to retry an event. the event is sent to the exact same URL, it wont reflect default callback URL changes.

POST /webhooks/test

parameters: none
description: sends an example event to the default callback URL of the client. returns an error if no default callback URL is found.

POST /webhook_url

parameters: body with webhook callback URL in it

"body": {
  "url": "https://amazing.salih.com"
}

description: sets the default webhook callback url for an organization. the url must be a well-formatted https URL.