curl --request POST \
--url https://api.tented.ai/v1/email-flows/{flowId}/steps \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"step": {
"type": "send_email",
"step_id": "<string>",
"label": "<string>",
"email_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"operational": true,
"create_email_step_id": "<string>",
"next_step_id": "<string>"
},
"position": "end",
"before_step_id": "<string>",
"after_step_id": "<string>"
}
'import requests
url = "https://api.tented.ai/v1/email-flows/{flowId}/steps"
payload = {
"step": {
"type": "send_email",
"step_id": "<string>",
"label": "<string>",
"email_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"operational": True,
"create_email_step_id": "<string>",
"next_step_id": "<string>"
},
"position": "end",
"before_step_id": "<string>",
"after_step_id": "<string>"
}
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({
step: {
type: 'send_email',
step_id: '<string>',
label: '<string>',
email_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
operational: true,
create_email_step_id: '<string>',
next_step_id: '<string>'
},
position: 'end',
before_step_id: '<string>',
after_step_id: '<string>'
})
};
fetch('https://api.tented.ai/v1/email-flows/{flowId}/steps', 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.tented.ai/v1/email-flows/{flowId}/steps",
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([
'step' => [
'type' => 'send_email',
'step_id' => '<string>',
'label' => '<string>',
'email_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'operational' => true,
'create_email_step_id' => '<string>',
'next_step_id' => '<string>'
],
'position' => 'end',
'before_step_id' => '<string>',
'after_step_id' => '<string>'
]),
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.tented.ai/v1/email-flows/{flowId}/steps"
payload := strings.NewReader("{\n \"step\": {\n \"type\": \"send_email\",\n \"step_id\": \"<string>\",\n \"label\": \"<string>\",\n \"email_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"operational\": true,\n \"create_email_step_id\": \"<string>\",\n \"next_step_id\": \"<string>\"\n },\n \"position\": \"end\",\n \"before_step_id\": \"<string>\",\n \"after_step_id\": \"<string>\"\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.tented.ai/v1/email-flows/{flowId}/steps")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"step\": {\n \"type\": \"send_email\",\n \"step_id\": \"<string>\",\n \"label\": \"<string>\",\n \"email_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"operational\": true,\n \"create_email_step_id\": \"<string>\",\n \"next_step_id\": \"<string>\"\n },\n \"position\": \"end\",\n \"before_step_id\": \"<string>\",\n \"after_step_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tented.ai/v1/email-flows/{flowId}/steps")
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 \"step\": {\n \"type\": \"send_email\",\n \"step_id\": \"<string>\",\n \"label\": \"<string>\",\n \"email_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"operational\": true,\n \"create_email_step_id\": \"<string>\",\n \"next_step_id\": \"<string>\"\n },\n \"position\": \"end\",\n \"before_step_id\": \"<string>\",\n \"after_step_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"flow_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>",
"name": "<string>",
"status": "draft",
"description": "<string>",
"triggers": [
{
"type": "added_to_static_list",
"list_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
],
"steps": [
{
"type": "send_email",
"step_id": "<string>",
"label": "<string>",
"email_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"operational": true,
"email_source": "existing",
"create_email_step_id": "<string>",
"next_step_id": "<string>"
}
],
"disqualification_rules": {
"conditions": "<array>",
"kind": "group",
"operator": "and"
},
"reentry_policy": "allow",
"manual_membership_enabled": true,
"settings": {},
"details": {
"total_entered": 123,
"active_count": 123,
"waiting_count": 123,
"completed_count": 123,
"dropped_count": 123,
"most_recent_entry_at": "2023-11-07T05:31:56Z"
},
"archived_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}Add a step
Insert a single step without rewriting the rest of the graph. Position it with at most one of position, before_step_id, or after_step_id. Inserting does not rewire edges — update neighboring steps’ links separately if needed.
curl --request POST \
--url https://api.tented.ai/v1/email-flows/{flowId}/steps \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"step": {
"type": "send_email",
"step_id": "<string>",
"label": "<string>",
"email_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"operational": true,
"create_email_step_id": "<string>",
"next_step_id": "<string>"
},
"position": "end",
"before_step_id": "<string>",
"after_step_id": "<string>"
}
'import requests
url = "https://api.tented.ai/v1/email-flows/{flowId}/steps"
payload = {
"step": {
"type": "send_email",
"step_id": "<string>",
"label": "<string>",
"email_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"operational": True,
"create_email_step_id": "<string>",
"next_step_id": "<string>"
},
"position": "end",
"before_step_id": "<string>",
"after_step_id": "<string>"
}
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({
step: {
type: 'send_email',
step_id: '<string>',
label: '<string>',
email_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
operational: true,
create_email_step_id: '<string>',
next_step_id: '<string>'
},
position: 'end',
before_step_id: '<string>',
after_step_id: '<string>'
})
};
fetch('https://api.tented.ai/v1/email-flows/{flowId}/steps', 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.tented.ai/v1/email-flows/{flowId}/steps",
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([
'step' => [
'type' => 'send_email',
'step_id' => '<string>',
'label' => '<string>',
'email_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'operational' => true,
'create_email_step_id' => '<string>',
'next_step_id' => '<string>'
],
'position' => 'end',
'before_step_id' => '<string>',
'after_step_id' => '<string>'
]),
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.tented.ai/v1/email-flows/{flowId}/steps"
payload := strings.NewReader("{\n \"step\": {\n \"type\": \"send_email\",\n \"step_id\": \"<string>\",\n \"label\": \"<string>\",\n \"email_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"operational\": true,\n \"create_email_step_id\": \"<string>\",\n \"next_step_id\": \"<string>\"\n },\n \"position\": \"end\",\n \"before_step_id\": \"<string>\",\n \"after_step_id\": \"<string>\"\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.tented.ai/v1/email-flows/{flowId}/steps")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"step\": {\n \"type\": \"send_email\",\n \"step_id\": \"<string>\",\n \"label\": \"<string>\",\n \"email_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"operational\": true,\n \"create_email_step_id\": \"<string>\",\n \"next_step_id\": \"<string>\"\n },\n \"position\": \"end\",\n \"before_step_id\": \"<string>\",\n \"after_step_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tented.ai/v1/email-flows/{flowId}/steps")
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 \"step\": {\n \"type\": \"send_email\",\n \"step_id\": \"<string>\",\n \"label\": \"<string>\",\n \"email_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"operational\": true,\n \"create_email_step_id\": \"<string>\",\n \"next_step_id\": \"<string>\"\n },\n \"position\": \"end\",\n \"before_step_id\": \"<string>\",\n \"after_step_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"flow_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "<string>",
"name": "<string>",
"status": "draft",
"description": "<string>",
"triggers": [
{
"type": "added_to_static_list",
"list_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
],
"steps": [
{
"type": "send_email",
"step_id": "<string>",
"label": "<string>",
"email_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"operational": true,
"email_source": "existing",
"create_email_step_id": "<string>",
"next_step_id": "<string>"
}
],
"disqualification_rules": {
"conditions": "<array>",
"kind": "group",
"operator": "and"
},
"reentry_policy": "allow",
"manual_membership_enabled": true,
"settings": {},
"details": {
"total_entered": 123,
"active_count": 123,
"waiting_count": 123,
"completed_count": 123,
"dropped_count": 123,
"most_recent_entry_at": "2023-11-07T05:31:56Z"
},
"archived_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}{
"error": "<string>",
"error_code": "<string>",
"message": "<string>",
"code": "<string>",
"details": {},
"limit": 123,
"current": 123
}Authorizations
Workspace API key, e.g. Authorization: Bearer tented_.... Create keys in Workspace Settings → API Keys.
Path Parameters
Flow ID.
Body
A flow step. A flow may contain up to 100 steps. Steps link via next_step_id (or the branch fields on condition_check); omitting a link ends the flow.
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
- Option 6
- Option 7
- Option 8
- Option 9
- Option 10
Show child attributes
Show child attributes
Insert at the start or end.
start, end Insert before this step.
Insert after this step.
Response
Step added.
Flow ID.
Always triggered_flow.
Flow name.
Lifecycle state. Structure is editable only while draft or paused.
draft, active, paused, archived Description.
Entry triggers.
A flow entry trigger. A flow may define up to 25 triggers. Triggers fire on new events only — activating a flow never retroactively enrolls contacts.
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
- Option 6
Show child attributes
Show child attributes
Step graph.
A flow step. A flow may contain up to 100 steps. Steps link via next_step_id (or the branch fields on condition_check); omitting a link ends the flow.
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
- Option 6
- Option 7
- Option 8
- Option 9
- Option 10
Show child attributes
Show child attributes
Contacts matching these rules are dropped (evaluated continuously). null when unset.
- Option 1
- Option 2
Show child attributes
Show child attributes
Whether contacts may re-enter after exiting.
allow, no_reentry Whether contacts can be added via the API.
Free-form flow settings (max 16 KB).
Aggregate membership counters.
Show child attributes
Show child attributes
When the flow was archived.
Creation time.
Last update.