cURL
curl --request POST \
--url https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate \
--header 'Authorization: Bearer YOUR_API_KEY'import requests
url = "https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate"
payload = {}
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({})
};
fetch('https://api.teamfollowup.ai/api/native-contacts/lead-webhook/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_URL => "https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate",
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([
]),
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://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate"
payload := strings.NewReader("{}")
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://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate")
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 = "{}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"token": "b20e4f7c118a49d3ae60c5d7f0921a44",
"createdAt": "2026-09-22T08:31:19.000Z"
}
}{
"success": false,
"error": "A phone number is required."
}{
"success": false,
"error": "Unauthorized"
}{
"success": false,
"error": "You do not have access to this sub-account."
}{
"success": false,
"error": "TooManyRequests"
}{
"success": false,
"error": "Contacts request failed."
}Rotate the lead link
Issues a new token and retires the old one at once.
Anything still posting to the old link starts failing immediately, so change your form or Zap in the same sitting. There is no grace period, deliberately: the reason to rotate is that somebody else has the old one.
Cookie-auth callers must send the x-csrf-token header.
Required API key scope: contacts:write.
POST
/
api
/
native-contacts
/
lead-webhook
/
rotate
cURL
curl --request POST \
--url https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate \
--header 'Authorization: Bearer YOUR_API_KEY'import requests
url = "https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate"
payload = {}
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({})
};
fetch('https://api.teamfollowup.ai/api/native-contacts/lead-webhook/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_URL => "https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate",
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([
]),
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://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate"
payload := strings.NewReader("{}")
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://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.teamfollowup.ai/api/native-contacts/lead-webhook/rotate")
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 = "{}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"token": "b20e4f7c118a49d3ae60c5d7f0921a44",
"createdAt": "2026-09-22T08:31:19.000Z"
}
}{
"success": false,
"error": "A phone number is required."
}{
"success": false,
"error": "Unauthorized"
}{
"success": false,
"error": "You do not have access to this sub-account."
}{
"success": false,
"error": "TooManyRequests"
}{
"success": false,
"error": "Contacts request failed."
}Authorizations
Send your API key as Authorization: Bearer YOUR_API_KEY.
Query Parameters
The sub-account. It is the only thing that identifies the tenant on these routes, and it is re-checked against your access on every call. A sub-account that keeps its contacts in a CRM answers 400.
Body
application/json
Request payload. Detailed schema pending — see the route handler.
⌘I
