curl --request POST \
--url https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Acme — AI playbook"
}
'import requests
url = "https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save"
payload = { "name": "Acme — AI playbook" }
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({name: 'Acme — AI playbook'})
};
fetch('https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save', 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.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save",
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([
'name' => 'Acme — AI playbook'
]),
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.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save"
payload := strings.NewReader("{\n \"name\": \"Acme — AI playbook\"\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://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Acme — AI playbook\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save")
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 \"name\": \"Acme — AI playbook\"\n}"
response = http.request(request)
puts response.read_body{
"id": "t-7",
"name": "Outbound playbook v2",
"description": "Tone and pacing for cold outreach",
"body": "## Voice\nFriendly, concise, never desperate.\n\n## Pacing\nTwo touches per week max.",
"type": "team",
"lastUpdatedAt": "2026-05-10T14:32:11Z",
"authorUserId": 4821,
"isAiGenerated": false,
"sourceOfferId": null,
"styleFiles": [
{
"id": 12345,
"fileName": "tone-guide.pdf"
}
]
}Save the playbook draft
Coming soon. This endpoint will be available by late October 2026.
ai-sdr:operate scope (or a broader one that includes it).
Save your playbook draft as a team playbook and attach it to this sequence, replacing any attached playbook. The first save creates the playbook; later saves of the same draft update that playbook. Send structure to save your edits, or omit it to save the draft as it is.
curl --request POST \
--url https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Acme — AI playbook"
}
'import requests
url = "https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save"
payload = { "name": "Acme — AI playbook" }
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({name: 'Acme — AI playbook'})
};
fetch('https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save', 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.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save",
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([
'name' => 'Acme — AI playbook'
]),
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.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save"
payload := strings.NewReader("{\n \"name\": \"Acme — AI playbook\"\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://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Acme — AI playbook\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reply.io/v3/sequences/ai-sdr/{sequence_id}/playbook-draft/save")
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 \"name\": \"Acme — AI playbook\"\n}"
response = http.request(request)
puts response.read_body{
"id": "t-7",
"name": "Outbound playbook v2",
"description": "Tone and pacing for cold outreach",
"body": "## Voice\nFriendly, concise, never desperate.\n\n## Pacing\nTwo touches per week max.",
"type": "team",
"lastUpdatedAt": "2026-05-10T14:32:11Z",
"authorUserId": 4821,
"isAiGenerated": false,
"sourceOfferId": null,
"styleFiles": [
{
"id": 12345,
"fileName": "tone-guide.pdf"
}
]
}Authorizations
Authenticate every request with a Bearer token. Pass your Reply API key in the
Authorization header:
Authorization: Bearer <your-api-key>
Get your API key from the Reply dashboard: Settings → API Key.
Path Parameters
Sequence id
x >= 1Body
Saves the draft as a team playbook. Both fields are optional.
Edited draft sections to save. Omit to save the draft as it is.
Show child attributes
Show child attributes
{
"introduction": "Acme helps aerospace startups cut launch costs. Lead with procurement speed.",
"dos": [
"Reference the prospect's latest funding round",
"Keep the first email under 90 words"
],
"angles": ["Slow procurement is delaying launches"],
"donts": ["Don't mention competitors by name"],
"additionalNotes": "Sign off with the sender's first name only.",
"examples": ""
}
Playbook name. Omit to keep the current name; on the first save, the name defaults to one based on the offer's company name.
1 - 128Response
Saved playbook
Detailed representation of a playbook, returned by get/create/update responses.
Composite identifier formatted as {prefix}-{numericId} where the prefix encodes the playbook scope:
g for global, o for organization, t for team (e.g. g-1, o-42, t-7).
Display name of the playbook
Short description of the playbook's purpose
Full playbook body — typically Markdown or plain text instructions the AI SDR follows when this playbook is applied.
Visibility scope of the playbook. Set on create and immutable thereafter.
global, organization, team Timestamp of the last modification
User ID of the playbook author. null for global playbooks and when the original author is no longer a team member.
Whether the playbook was generated by the AI SDR from an offer.
Id of the offer the playbook was generated from. null for playbooks that were not AI-generated.
Style files attached to the playbook. Managed via the /style-files sub-resource — uploads are immediate, deletes are immediate; the field is read-only on the playbook payload.
Show child attributes
Show child attributes