Webhook Documentation
We are in active development, so your feedback is critical to us. Please reach out if you run into any issues or have a feature you would like to see implemented.
Understanding Hooks
A Hook acts as a proxy for webhooks between you and your customers. You primarily interact with your hook by sending HTTP POST requests to the Hook URL. The first thing to decide when creating a hook is which direction the traffic will flow.
Inbound vs. Outbound
We handle both sending (outbound) and receiving (inbound) webhooks, as each have different challenges.
Inbound
Inbound hooks are designed to provide a buffer between your users and your backend. Inbound webhooks typically come from many sources and are relayed to one endpoint. Because of this, you must specify a Target URL in the Hook settings.
When Hook Relay gets cozy with you and your inbound webhooks, we ensure that your servers are never overloaded. If you have any connection problems or downtime, you can rest easy knowing you will get your webhooks after coming back online.
Outbound
You won't have to deal with slow consumers taking up outgoing connections when you delegate your outgoing webhooks to Hook Relay. Outbound webhooks are usually sent to multiple consumers, so you must provide the Target URL in the request header.
Go ahead and send us all the webhook requests you can. We will respond right away and make sure the payload gets delivered to your users. You can even use our API to provide receipts of your webhook deliveries.
Webhook Requests
Each hook has a single Hook URL that looks something like this:
https://us-west-api.hookrelay.dev/hooks/r3j8kxgen2gzqhgdwom45v7q/f0b61a6f4297365387de9321You will POST directly to the Hook URL for outbound webhooks or hand it to your customers for inbound webhooks.
When we receive a POST, we create a delivery and queue up the request to be sent to the Target URL. We respond immediately with a JSON payload containing the delivery ID:
{
"id": "01EC8Z3JAQ0W2ZAQGG2S3XNMWJ"
}
You can use this ID to track your webhook by looking up the status of your delivery.
If your hook has multiple target URLs (see Target URLs), the response will contain the IDs of the delivery to each URL.
{
"ids": [
"01FF63MQE89MECNQ6MVVEQYGHQ",
"01FF63MQGRA8GRZ8FACCDGEQV7"
]
}
Deliveries
Deliveries are a container for webhook "requests." We create a delivery for each POST received by a Hook. A delivery keeps track of the inbound request, the target's response, and any retry history. You can visit the delivery page for any request to see detailed information about each request and response.
Streams
Streams let you segment your hook deliveries. To include a stream value, append an identifier as an optional path to your Hook URL, for example:
We will keep track of customer1's deliveries and provide you with extra tools for tracking and filtering.
Retries
If we have any issues relaying your target request, we will keep retrying (with exponential falloff). If we can not reach the target within your account's retry limit, we mark the delivery as "failed" and stop trying.
NOTE: A successful response must have a 200 level status code. Receiving any other response code (or a connection error) will result in a retry.
You can cancel a retrying delivery at any point. You may also retry a canceled delivery at any point as well.
Target URL
The Target URL is where we will relay requests. If you are receiving inbound webhook requests, it might make sense to provide a default target URL. You can do this in your hook's settings. Provide one or more target URLs, and we will pass on your webhook requests to each of the URLs:
You can also vary the Target URL (say, for outgoing webhooks) by specifying it in a "HR_TARGET_URL" header in the hook request. To set multiple target URLs, use the "HR_TARGET_URLS" header instead, with the URLs passed as a JSON array.
# Single target URL
curl --request POST \
--url 'https://hookrelay.dev/hooks/74j1zpo8m9m31/1c394b57bdba0b9847' \
--header 'Content-Type: application/json' \
--header 'HR_TARGET_URL: http://target.url' \
--data '{"msg":"hi"}'
# Response:
# {
# "id": "01EC8Z3JAQ0W2ZAQGG2S3XNMWJ"
# }
# Multiple target URLs
curl --request POST \
--url 'https://hookrelay.dev/hooks/74j1zpo8m9m31/1c394b57bdba0b9847' \
--header 'Content-Type: application/json' \
--header 'HR_TARGET_URLS: ["http://one.target.url", "http://two.target.url"]' \
--data '{"msg":"hi"}'
# Response:
# {
# "ids": [
# "01FF63MQE89MECNQ6MVVEQYGHQ",
# "01FF63MQGRA8GRZ8FACCDGEQV7"
# ]
# }
NOTE: Even if your hook has a default Target URL, a target specified in the header will always take precedence.
Report URL
If you provide us with a Report URL in your hook settings, we will send
you updates (in the form of a webhook) for every delivery attempt. You
will recieve a POST request with a body containing the same contents as a
typical Delivery API lookup response
but with the responses
data stripped.
Pausing & Disabling
Pausing will still accept requests, but it will not relay them to the Target URL. This can be useful if your endpoint is down, yet you still want to accept webhook requests.
You can flag your hook as disabled if you want to ignore all requests into your hook.
Both Disabling and Pausing can be achieved via hook settings.
Account Management
Access is granted via an account. We provision a default account when you first sign-up. You can add (or remove) an account at any time, but you must always have at least one account. Subscriptions and payment info are also associated with an account.
Switching Accounts
While viewing your data, you are always within the context of a current account. If you want to view hooks for another account, then you must switch accounts. We provivde a quick account switcher in the main menu. You can also switch accounts via the accounts area.
Regions
When you create an account, you have the option to specify a region. Your data will be stored in the selected region. A region closer to your location will also benefit from lower latency for requests. You cannot change a region after Account creation.
Users
If you are an owner or have the admin role for an account, you can invite users to your account. You can update and remove any invited users to your account via the account details:
Billing & Pricing
View the billing settings for your current account via the "Billing" main menu option. If you want to see billing info for another account, you must switch to that account.
Pricing is based on the amount of recorded "deliveries". A typical request will consume 2 deliveries. Both the incoming request and outgoing attempt counts as a delivery. If you have a delivery that requires retries, each retry will also count as a "delivery".
Rest API
All paths below are relative to our API domain:
https://app.hookrelay.dev
Authentication
We use (Bearer) token-based authentication for all our API routes. You can provision an API token within our "API tokens" area. Access this section via the menu dropdown. Once you give your new token a name, it will be presented to you:
You can revoke or reprovision a new token at any time. As you can see in the screenshot, just include the token in the Authorization header and data away!
Pagination
For any endpoints that require pagination, you can request more
results by passing an item id as a cursor. Cursors should always be
passed as query parameters. We accept cursors for results up to
an id (?ending_before=abc123
), and beginning at an id
(?starting_after=abc123
.)
Accounts
Operations around accounts you are a member of.
Get an Account
Example response
{
"id": "75r4e01zq24z0hwd6yxjpgvo",
"links": {
"hooks": "/api/v1/accounts/zprgwxnvm9eozhk2178j304k/hooks",
"self": "/api/v1/accounts/zprgwxnvm9eozhk2178j304k"
},
"name": "My Account"
}
List all Accounts
Example response
{
"data": [
{
"id": "75r4e01zq24z0hwd6yxjpgvo",
"links": {
"hooks": "/api/v1/accounts/zprgwxnvm9eozhk2178j304k/hooks",
"self": "/api/v1/accounts/zprgwxnvm9eozhk2178j304k"
},
"name": "My Account"
},
"..."
],
"has_more": true
}
Deliveries
Look up a delivery when you want to show the status of a webhook to a customer.
Get a Delivery
Example response
{
"attempts": 1,
"completed_at": "2020-12-02T15:37:42Z",
"created_at": "2020-12-02T15:37:42Z",
"failure_reason": "Could not connect",
"id": "2a360b1d10fff55b91498e45",
"last_attempted_at": "2020-12-02T15:37:42Z",
"report_url": "http://example.com/aeiou",
"request": {
"body": "body",
"headers": { "Content-Type": "application/json" },
"jmespath_error": "jmespath_error",
"target_url": "http://example.com/aeiou"
},
"responses": [
{
"body": "body",
"code": 0,
"created_at": "2000-01-23T04:56:07.000+00:00",
"error": "error",
"headers": { "Content-Type": "application/json" }
},
"..."
],
"status": "success",
"stream": "user-1234"
}
List Deliveries
Query Params
- ending_before
- Return results up to this ID
- starting_after
- Begin results starting from this ID
- limit
- Constrain count of results.
- status
- Filter by delivery status
- started_at
- Limit deliveries to time range. Accepts ISO 8601 formatting.
-
examples
P8D
Relative 8 days ago
2021-12-14 14:14:08.000000000 -08:00
Relative timed date
2021-12-10T00:00/2021-12-12T00:00
Absolute time range
- stream
- Limit deliveries to those with the requested stream
Example response
{
"data": [
{
"attempts": 1,
"completed_at": "2020-12-02T15:37:42Z",
"created_at": "2020-12-02T15:37:42Z",
"failure_reason": "Could not connect",
"id": "2a360b1d10fff55b91498e45",
"last_attempted_at": "2020-12-02T15:37:42Z",
"report_url": "http://example.com/aeiou",
"request": {
"body": "body",
"headers": { "Content-Type": "application/json" },
"jmespath_error": "jmespath_error",
"target_url": "http://example.com/aeiou"
},
"responses": [
{
"body": "body",
"code": 0,
"created_at": "2000-01-23T04:56:07.000+00:00",
"error": "error",
"headers": { "Content-Type": "application/json" }
},
{
"body": "body",
"code": 0,
"created_at": "2000-01-23T04:56:07.000+00:00",
"error": "error",
"headers": { "Content-Type": "application/json" }
}
],
"status": "success",
"stream": "user-1234"
},
"..."
],
"has_more": true
}
Retry a Delivery
Example response
{
"delivery": {
"account_id": "prgwxnvm9eozh0k2178j304k",
"hook_id": "24a06755c07d2e7faf965e2d",
"id": "01HJ6Z72A3AG5YX2SHAT9A6MRK"
},
"status": "queued"
}
Hooks
Fully manage your hooks via API.
Create a Hook
Example response
{
"id": "2a360b1d10fff55b91498e45",
"links": {
"account": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo",
"deliveries": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/2a360b1d10fff55b91498e45/deliveries",
"self": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/4e7b6cc56fab423204025385"
},
"name": "My Hook",
"report_url": "https://3ab577f377a4.ngrok.io/no_content"
}
Delete a Hook
Get a Hook
Example response
{
"id": "2a360b1d10fff55b91498e45",
"links": {
"account": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo",
"deliveries": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/2a360b1d10fff55b91498e45/deliveries",
"self": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/4e7b6cc56fab423204025385"
},
"name": "My Hook",
"report_url": "https://3ab577f377a4.ngrok.io/no_content"
}
List all Hooks
Query Params
- ending_before
- Return results up to this ID
- starting_after
- Begin results starting from this ID
- limit
- Constrain count of results.
Example response
{
"data": [
{
"id": "2a360b1d10fff55b91498e45",
"links": {
"account": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo",
"deliveries": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/2a360b1d10fff55b91498e45/deliveries",
"self": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/4e7b6cc56fab423204025385"
},
"name": "My Hook",
"report_url": "https://3ab577f377a4.ngrok.io/no_content"
},
"..."
],
"has_more": true
}
Update a Hook
Example response
{
"id": "2a360b1d10fff55b91498e45",
"links": {
"account": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo",
"deliveries": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/2a360b1d10fff55b91498e45/deliveries",
"self": "/api/v1/accounts/75r4e01zq24z0hwd6yxjpgvo/hooks/4e7b6cc56fab423204025385"
},
"name": "My Hook",
"report_url": "https://3ab577f377a4.ngrok.io/no_content"
}
User
Info about the currently logged in User.
Show User
Example response
{
"accounts": [
{
"id": "75r4e01zq24z0hwd6yxjpgvo",
"links": {
"hooks": "/api/v1/accounts/zprgwxnvm9eozhk2178j304k/hooks",
"self": "/api/v1/accounts/zprgwxnvm9eozhk2178j304k"
},
"name": "My Account"
},
"..."
],
"id": "2a360b1d10fff55b91498e45",
"name": "Bobby Tables"
}