curl --request GET \
--url https://api-dev.narrative.io/webhooks \
--header 'Authorization: Bearer <token>'import requests
url = "https://api-dev.narrative.io/webhooks"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api-dev.narrative.io/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-dev.narrative.io/webhooks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-dev.narrative.io/webhooks"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-dev.narrative.io/webhooks")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.narrative.io/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body[
{
"summary": "Job subscription with all three filters set",
"value": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"app_id": null,
"name": "job_updates",
"secret": "8b6dba8c-9a8b-4a3a-8469-9dc7a33c3e17",
"status": "active",
"company_id": 42,
"job_ids": {
"values": [
"9a3cf334-4c6d-4d3f-a7d6-22b6e6f2ac1b",
"d35a12c1-7a2f-46b9-8d60-9e0a2a84c205"
]
},
"job_states": {
"values": [
"completed",
"failed"
]
},
"job_types": {
"values": [
"datasets_deliver_data",
"materialize-view"
]
},
"url": "https://webhooks.mycompany.com/events",
"created_at": "2025-04-29T16:12:45.123456",
"updated_at": "2025-04-29T16:12:45.123456"
}
}
]{
"error": "Unauthorized",
"error_description": "You are not authorized to use this endpoint."
}List webhook subscriptions
List your company’s active webhook subscriptions. Archived subscriptions are not returned.
Requires read access to webhooks.
curl --request GET \
--url https://api-dev.narrative.io/webhooks \
--header 'Authorization: Bearer <token>'import requests
url = "https://api-dev.narrative.io/webhooks"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api-dev.narrative.io/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-dev.narrative.io/webhooks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-dev.narrative.io/webhooks"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-dev.narrative.io/webhooks")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.narrative.io/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body[
{
"summary": "Job subscription with all three filters set",
"value": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"app_id": null,
"name": "job_updates",
"secret": "8b6dba8c-9a8b-4a3a-8469-9dc7a33c3e17",
"status": "active",
"company_id": 42,
"job_ids": {
"values": [
"9a3cf334-4c6d-4d3f-a7d6-22b6e6f2ac1b",
"d35a12c1-7a2f-46b9-8d60-9e0a2a84c205"
]
},
"job_states": {
"values": [
"completed",
"failed"
]
},
"job_types": {
"values": [
"datasets_deliver_data",
"materialize-view"
]
},
"url": "https://webhooks.mycompany.com/events",
"created_at": "2025-04-29T16:12:45.123456",
"updated_at": "2025-04-29T16:12:45.123456"
}
}
]{
"error": "Unauthorized",
"error_description": "You are not authorized to use this endpoint."
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Response
OK
Sent back on every delivery in the X-Narrative-Secret header. Compare it against this value to confirm a
callback came from Narrative.
Archiving is one-way. The read endpoints only return active subscriptions, so in practice this is always
active — an archived subscription responds 404.
active, archived The company that owns the subscription.
The endpoint events are delivered to.
An ISO 8601 local date-time with no offset or zone — 2025-04-29T16:12:45.123456. Read it as UTC. This is
deliberately not format: date-time, which means RFC 3339 and would require an offset the server does not send.
Note that the delivered event envelope uses a different format: its created_at does carry a Z.
^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?$"2025-04-29T16:12:45.123456"
An ISO 8601 local date-time with no offset or zone — 2025-04-29T16:12:45.123456. Read it as UTC. This is
deliberately not format: date-time, which means RFC 3339 and would require an offset the server does not send.
Note that the delivered event envelope uses a different format: its created_at does carry a Z.
^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?$"2025-04-29T16:12:45.123456"
The app this subscription follows. Null on job subscriptions.
The label supplied at creation time. Null if none was given.
The job_ids filter, or null if the subscription does not filter by job.
Show child attributes
Show child attributes
{
"values": [
"9a3cf334-4c6d-4d3f-a7d6-22b6e6f2ac1b",
"d35a12c1-7a2f-46b9-8d60-9e0a2a84c205"
]
}
The states filter, or null if the subscription does not filter by state.
Show child attributes
Show child attributes
{ "values": ["completed", "failed"] }
The job_types filter, or null if the subscription does not filter by type.
Show child attributes
Show child attributes
{
"values": ["datasets_deliver_data", "materialize-view"]
}
Was this page helpful?

