curl --request POST \
--url https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"protocol": "https",
"endpoint": "https://hooks.example.com/basaltic",
"raw_message_delivery": false,
"filter_policy": {
"event": [
"order.created",
"order.paid"
],
"environment": [
"production"
],
"amount": [
{
"numeric": [
">=",
100,
"<",
1000
]
}
],
"test": [
{
"exists": false
}
]
},
"delivery_policy": {
"max_attempts": 6,
"min_delay_seconds": 20,
"max_delay_seconds": 1200,
"timeout_seconds": 15
},
"tags": {
"environment": "production",
"team": "backend"
}
}
'import requests
url = "https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions"
payload = {
"protocol": "https",
"endpoint": "https://hooks.example.com/basaltic",
"raw_message_delivery": False,
"filter_policy": {
"event": ["order.created", "order.paid"],
"environment": ["production"],
"amount": [{ "numeric": [">=", 100, "<", 1000] }],
"test": [{ "exists": False }]
},
"delivery_policy": {
"max_attempts": 6,
"min_delay_seconds": 20,
"max_delay_seconds": 1200,
"timeout_seconds": 15
},
"tags": {
"environment": "production",
"team": "backend"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
protocol: 'https',
endpoint: 'https://hooks.example.com/basaltic',
raw_message_delivery: false,
filter_policy: {
event: ['order.created', 'order.paid'],
environment: ['production'],
amount: [{numeric: ['>=', 100, '<', 1000]}],
test: [{exists: false}]
},
delivery_policy: {
max_attempts: 6,
min_delay_seconds: 20,
max_delay_seconds: 1200,
timeout_seconds: 15
},
tags: {environment: 'production', team: 'backend'}
})
};
fetch('https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions', 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://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'protocol' => 'https',
'endpoint' => 'https://hooks.example.com/basaltic',
'raw_message_delivery' => false,
'filter_policy' => [
'event' => [
'order.created',
'order.paid'
],
'environment' => [
'production'
],
'amount' => [
[
'numeric' => [
'>=',
100,
'<',
1000
]
]
],
'test' => [
[
'exists' => false
]
]
],
'delivery_policy' => [
'max_attempts' => 6,
'min_delay_seconds' => 20,
'max_delay_seconds' => 1200,
'timeout_seconds' => 15
],
'tags' => [
'environment' => 'production',
'team' => 'backend'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions"
payload := strings.NewReader("{\n \"protocol\": \"https\",\n \"endpoint\": \"https://hooks.example.com/basaltic\",\n \"raw_message_delivery\": false,\n \"filter_policy\": {\n \"event\": [\n \"order.created\",\n \"order.paid\"\n ],\n \"environment\": [\n \"production\"\n ],\n \"amount\": [\n {\n \"numeric\": [\n \">=\",\n 100,\n \"<\",\n 1000\n ]\n }\n ],\n \"test\": [\n {\n \"exists\": false\n }\n ]\n },\n \"delivery_policy\": {\n \"max_attempts\": 6,\n \"min_delay_seconds\": 20,\n \"max_delay_seconds\": 1200,\n \"timeout_seconds\": 15\n },\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"protocol\": \"https\",\n \"endpoint\": \"https://hooks.example.com/basaltic\",\n \"raw_message_delivery\": false,\n \"filter_policy\": {\n \"event\": [\n \"order.created\",\n \"order.paid\"\n ],\n \"environment\": [\n \"production\"\n ],\n \"amount\": [\n {\n \"numeric\": [\n \">=\",\n 100,\n \"<\",\n 1000\n ]\n }\n ],\n \"test\": [\n {\n \"exists\": false\n }\n ]\n },\n \"delivery_policy\": {\n \"max_attempts\": 6,\n \"min_delay_seconds\": 20,\n \"max_delay_seconds\": 1200,\n \"timeout_seconds\": 15\n },\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"protocol\": \"https\",\n \"endpoint\": \"https://hooks.example.com/basaltic\",\n \"raw_message_delivery\": false,\n \"filter_policy\": {\n \"event\": [\n \"order.created\",\n \"order.paid\"\n ],\n \"environment\": [\n \"production\"\n ],\n \"amount\": [\n {\n \"numeric\": [\n \">=\",\n 100,\n \"<\",\n 1000\n ]\n }\n ],\n \"test\": [\n {\n \"exists\": false\n }\n ]\n },\n \"delivery_policy\": {\n \"max_attempts\": 6,\n \"min_delay_seconds\": 20,\n \"max_delay_seconds\": 1200,\n \"timeout_seconds\": 15\n },\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}"
response = http.request(request)
puts response.read_body{
"subscription": {
"id": "b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"crn": "crn:notifications:sa-saopaulo-1:my-account:topic/orders/subscription/b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"protocol": "https",
"endpoint": "https://hooks.example.com/basaltic",
"status": "confirmed",
"raw_message_delivery": false,
"created_at": "2026-01-18T09:30:00Z",
"updated_at": "2026-01-18T09:31:00Z",
"filter_policy": {
"event": [
"order.created",
"order.paid"
],
"environment": [
"production"
],
"amount": [
{
"numeric": [
">=",
100,
"<",
1000
]
}
],
"test": [
{
"exists": false
}
]
},
"delivery_policy": {
"max_attempts": 6,
"min_delay_seconds": 20,
"max_delay_seconds": 1200,
"timeout_seconds": 15
},
"redrive_policy": {
"dead_letter_queue": {
"id": "c3d4e5f6-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
"crn": "crn:queue:sa-saopaulo-1:my-account:queue/notification-failures",
"name": "notification-failures"
}
},
"confirmation_expires_at": "2026-01-21T09:30:00Z",
"confirmed_at": "2026-01-18T09:31:00Z",
"tags": {
"environment": "production",
"team": "backend"
}
},
"signing_secret": "kJ8vQ2xR5tY7uI0oP3aS6dF9gH1jK4lZ7xC0vB3nM6Q"
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"params": {
"instances": 2,
"pools": 0
}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "ACCESS_DENIED",
"message": "You don't have permission to perform this action",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "CONFLICT",
"message": "Resource with this name already exists",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "This Idempotency-Key was already used with a different request payload",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}Subscribe an endpoint to a topic
The parent topic is selected by topic_id in the path. Foreign topics
require bilateral Subscribe authorization. Email and webhook subscriptions
start in pending_confirmation and receive a confirmation token.
Nothing is delivered until the endpoint owner confirms. Queue
subscriptions are confirmed immediately after target authorization.
Idempotent per (topic, protocol, endpoint): subscribing an
address that already has a subscription returns the existing one,
WITHOUT a signing_secret — re-minting one would invalidate the
signature the subscriber is already verifying against.
signing_secret is returned exactly once, on the first create of
an http/https subscription. Store it, or read it back later from
the signing-secret endpoint.
curl --request POST \
--url https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"protocol": "https",
"endpoint": "https://hooks.example.com/basaltic",
"raw_message_delivery": false,
"filter_policy": {
"event": [
"order.created",
"order.paid"
],
"environment": [
"production"
],
"amount": [
{
"numeric": [
">=",
100,
"<",
1000
]
}
],
"test": [
{
"exists": false
}
]
},
"delivery_policy": {
"max_attempts": 6,
"min_delay_seconds": 20,
"max_delay_seconds": 1200,
"timeout_seconds": 15
},
"tags": {
"environment": "production",
"team": "backend"
}
}
'import requests
url = "https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions"
payload = {
"protocol": "https",
"endpoint": "https://hooks.example.com/basaltic",
"raw_message_delivery": False,
"filter_policy": {
"event": ["order.created", "order.paid"],
"environment": ["production"],
"amount": [{ "numeric": [">=", 100, "<", 1000] }],
"test": [{ "exists": False }]
},
"delivery_policy": {
"max_attempts": 6,
"min_delay_seconds": 20,
"max_delay_seconds": 1200,
"timeout_seconds": 15
},
"tags": {
"environment": "production",
"team": "backend"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
protocol: 'https',
endpoint: 'https://hooks.example.com/basaltic',
raw_message_delivery: false,
filter_policy: {
event: ['order.created', 'order.paid'],
environment: ['production'],
amount: [{numeric: ['>=', 100, '<', 1000]}],
test: [{exists: false}]
},
delivery_policy: {
max_attempts: 6,
min_delay_seconds: 20,
max_delay_seconds: 1200,
timeout_seconds: 15
},
tags: {environment: 'production', team: 'backend'}
})
};
fetch('https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions', 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://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'protocol' => 'https',
'endpoint' => 'https://hooks.example.com/basaltic',
'raw_message_delivery' => false,
'filter_policy' => [
'event' => [
'order.created',
'order.paid'
],
'environment' => [
'production'
],
'amount' => [
[
'numeric' => [
'>=',
100,
'<',
1000
]
]
],
'test' => [
[
'exists' => false
]
]
],
'delivery_policy' => [
'max_attempts' => 6,
'min_delay_seconds' => 20,
'max_delay_seconds' => 1200,
'timeout_seconds' => 15
],
'tags' => [
'environment' => 'production',
'team' => 'backend'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions"
payload := strings.NewReader("{\n \"protocol\": \"https\",\n \"endpoint\": \"https://hooks.example.com/basaltic\",\n \"raw_message_delivery\": false,\n \"filter_policy\": {\n \"event\": [\n \"order.created\",\n \"order.paid\"\n ],\n \"environment\": [\n \"production\"\n ],\n \"amount\": [\n {\n \"numeric\": [\n \">=\",\n 100,\n \"<\",\n 1000\n ]\n }\n ],\n \"test\": [\n {\n \"exists\": false\n }\n ]\n },\n \"delivery_policy\": {\n \"max_attempts\": 6,\n \"min_delay_seconds\": 20,\n \"max_delay_seconds\": 1200,\n \"timeout_seconds\": 15\n },\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"protocol\": \"https\",\n \"endpoint\": \"https://hooks.example.com/basaltic\",\n \"raw_message_delivery\": false,\n \"filter_policy\": {\n \"event\": [\n \"order.created\",\n \"order.paid\"\n ],\n \"environment\": [\n \"production\"\n ],\n \"amount\": [\n {\n \"numeric\": [\n \">=\",\n 100,\n \"<\",\n 1000\n ]\n }\n ],\n \"test\": [\n {\n \"exists\": false\n }\n ]\n },\n \"delivery_policy\": {\n \"max_attempts\": 6,\n \"min_delay_seconds\": 20,\n \"max_delay_seconds\": 1200,\n \"timeout_seconds\": 15\n },\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://notifications.{region}.basaltic.sh/v1/topics/{topic_id}/subscriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"protocol\": \"https\",\n \"endpoint\": \"https://hooks.example.com/basaltic\",\n \"raw_message_delivery\": false,\n \"filter_policy\": {\n \"event\": [\n \"order.created\",\n \"order.paid\"\n ],\n \"environment\": [\n \"production\"\n ],\n \"amount\": [\n {\n \"numeric\": [\n \">=\",\n 100,\n \"<\",\n 1000\n ]\n }\n ],\n \"test\": [\n {\n \"exists\": false\n }\n ]\n },\n \"delivery_policy\": {\n \"max_attempts\": 6,\n \"min_delay_seconds\": 20,\n \"max_delay_seconds\": 1200,\n \"timeout_seconds\": 15\n },\n \"tags\": {\n \"environment\": \"production\",\n \"team\": \"backend\"\n }\n}"
response = http.request(request)
puts response.read_body{
"subscription": {
"id": "b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"crn": "crn:notifications:sa-saopaulo-1:my-account:topic/orders/subscription/b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"protocol": "https",
"endpoint": "https://hooks.example.com/basaltic",
"status": "confirmed",
"raw_message_delivery": false,
"created_at": "2026-01-18T09:30:00Z",
"updated_at": "2026-01-18T09:31:00Z",
"filter_policy": {
"event": [
"order.created",
"order.paid"
],
"environment": [
"production"
],
"amount": [
{
"numeric": [
">=",
100,
"<",
1000
]
}
],
"test": [
{
"exists": false
}
]
},
"delivery_policy": {
"max_attempts": 6,
"min_delay_seconds": 20,
"max_delay_seconds": 1200,
"timeout_seconds": 15
},
"redrive_policy": {
"dead_letter_queue": {
"id": "c3d4e5f6-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
"crn": "crn:queue:sa-saopaulo-1:my-account:queue/notification-failures",
"name": "notification-failures"
}
},
"confirmation_expires_at": "2026-01-21T09:30:00Z",
"confirmed_at": "2026-01-18T09:31:00Z",
"tags": {
"environment": "production",
"team": "backend"
}
},
"signing_secret": "kJ8vQ2xR5tY7uI0oP3aS6dF9gH1jK4lZ7xC0vB3nM6Q"
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request parameters",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"params": {
"instances": 2,
"pools": 0
}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "ACCESS_DENIED",
"message": "You don't have permission to perform this action",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "CONFLICT",
"message": "Resource with this name already exists",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "This Idempotency-Key was already used with a different request payload",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}notifications:Subscribe. See NOTIFICATIONS permissions for the full list, what each one covers, and an example policy.Authorizations
An OAuth 2.0 bearer token, sent as Authorization: Bearer <token>.
This is the recommended way to authenticate.
Get one by exchanging a service account's access key pair at
POST /v1/oauth/token with grant_type=client_credentials. It is the
standard client-credentials grant, so any OAuth-aware library will
obtain and refresh it for you.
curl -s -u "$KEY_ID:$SECRET" -d grant_type=client_credentials \
https://iam.basaltic.sh/v1/oauth/token
Tokens last an hour by default. The same access key pair is separately your AWS SigV4 credential for the S3-compatible object endpoint, which speaks nothing else.
Headers
Optional client-generated key that makes a create replay-safe. Retrying a request with the same key returns the original outcome verbatim instead of creating a duplicate resource. Reusing a key with a different request body is rejected (422); a request whose key is still being processed returns 409. Records are honored for 24 hours. Use a UUID or similarly unique token.
255Path Parameters
"a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
Body
email, https, http, queue "https"
An email address; an http/https URL whose scheme matches the
protocol and resolves to a publicly-routable address; or, for
queue, a queue UUID, CRN or exact name in the subscriber account and serving region. Queue targets are stored and returned as canonical CRNs.
A queue subscription skips the confirmation handshake and is
created already confirmed. The handshake exists to prove that
whoever controls the endpoint consents to receive, which is
necessary for an address or a URL you may not own. A queue is
your own resource, so consent is established instead by
requiring queue:SendMessage on it at subscribe time — an
authorization decision rather than a demonstration of
reachability.
2048"https://hooks.example.com/basaltic"
http/https only.
false
Matches publication attributes, not fields inside the message body. Every named attribute must match at least one alternative (AND across names, OR within each array). Names and string comparisons are case-sensitive. An omitted or empty policy matches every message.
Alternatives are exact strings or numbers, or single-operator objects:
{"prefix": "order."}, {"suffix": ".failed"},
{"anything-but": ["debug", "trace"]}, {"exists": true},
{"exists": false}, or {"numeric": [">=", 100, "<", 1000]}.
Prefix and suffix values must be nonempty. anything-but accepts one
string or number, or a list of 1–50 such values.
Only exists: false matches an absent attribute. Exclusion also requires
presence. Numeric operators are =, <, <=, >, and >=; every
operator/number pair in one numeric matcher must succeed. Attribute
values that cannot be parsed as numbers do not match. Bare numeric
alternatives compare string representations; use numeric for numeric
equality, such as matching both "100" and "100.0".
At most 20 nonblank attribute names and 1–50 alternatives per name.
Each operator object has exactly one operator. Wildcards, regular
expressions, body filtering, and nested operators are not supported.
PATCH replaces the entire policy; {} clears it and omission preserves it.
See Filter policies for worked examples.
Show child attributes
Show child attributes
{
"event": ["order.created", "order.paid"],
"environment": ["production"],
"amount": [{ "numeric": [">=", 100, "<", 1000] }],
"test": [{ "exists": false }]
}
Retry behaviour. Omitted fields fall back to the topic's policy,
then to platform defaults (6 attempts, 20s to 20m exponential
backoff with jitter, 15s per-request timeout). A subscription's
policy is layered on its topic's field by field, so overriding
only max_attempts keeps the topic's backoff curve.
Show child attributes
Show child attributes
Names a queue in the subscriber's own account that receives each
terminally failed delivery — the full original notification plus
a failure block (delivery id, endpoint, attempts, last error,
status code) — as a delivery_failure message. Without one,
terminal failures remain visible in delivery records and Telemetry metrics.
The caller must hold queue:SendMessage on the target when the
policy is set: writes happen later with no principal present, so
consent is established up front, exactly as for a
protocol=queue endpoint. For a queue subscription the target
must differ from the endpoint queue.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
{
"environment": "production",
"team": "backend"
}
Response
Subscription created (or the existing one returned).
Show child attributes
Show child attributes
The HMAC key for verifying webhook deliveries. Returned only on the first create of an http/https subscription — absent for email, and absent when an existing subscription is returned.
"kJ8vQ2xR5tY7uI0oP3aS6dF9gH1jK4lZ7xC0vB3nM6Q"

