Rotate the webhook signing secret
curl --request POST \
--url http://localhost:3051/api/v1/me/webhook-secrets/rotate \
--header 'Authorization: Bearer <token>'import requests
url = "http://localhost:3051/api/v1/me/webhook-secrets/rotate"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('http://localhost:3051/api/v1/me/webhook-secrets/rotate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "3051",
CURLOPT_URL => "http://localhost:3051/api/v1/me/webhook-secrets/rotate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
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 := "http://localhost:3051/api/v1/me/webhook-secrets/rotate"
req, _ := http.NewRequest("POST", 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.post("http://localhost:3051/api/v1/me/webhook-secrets/rotate")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("http://localhost:3051/api/v1/me/webhook-secrets/rotate")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"secret": "<string>",
"secrets": [
{
"id": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z",
"status": "active"
}
]
}Webhooks
Rotate webhook signing secret
Issue a new signing secret and return it. The previous secret keeps signing alongside it for 24 hours, so deliveries stay verifiable while you roll the new value out; during that window webhook-signature carries both values, space delimited, and a receiver accepts whichever matches. Rotate immediately if a secret leaks.
POST
/
api
/
v1
/
me
/
webhook-secrets
/
rotate
Rotate the webhook signing secret
curl --request POST \
--url http://localhost:3051/api/v1/me/webhook-secrets/rotate \
--header 'Authorization: Bearer <token>'import requests
url = "http://localhost:3051/api/v1/me/webhook-secrets/rotate"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('http://localhost:3051/api/v1/me/webhook-secrets/rotate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "3051",
CURLOPT_URL => "http://localhost:3051/api/v1/me/webhook-secrets/rotate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
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 := "http://localhost:3051/api/v1/me/webhook-secrets/rotate"
req, _ := http.NewRequest("POST", 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.post("http://localhost:3051/api/v1/me/webhook-secrets/rotate")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("http://localhost:3051/api/v1/me/webhook-secrets/rotate")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"secret": "<string>",
"secrets": [
{
"id": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z",
"status": "active"
}
]
}Issues a new signing secret and returns it. The previous secret keeps signing alongside it for
24 hours, so deliveries stay verifiable while you roll the new value out.
During that window
webhook-signature carries both values, space delimited, and a Standard Webhooks
library accepts whichever one matches. Split the header on spaces — the comma belongs inside each
v1,<base64> value.
Rotate immediately if a secret leaks. See
rotating the secret.
These endpoints need the
webhook:manage scope. Your dashboard session carries it, so Account →
Webhooks always works. An API key does not carry it by default — a key that only moderates
content must not be able to read the credential that proves a callback came from us. Contact
support if you need it on a key.