API reference/Outreach/Flows
Get a flow
One flow with its steps, the step keys that need a text (text_steps) and the steps in words (in_words).
A flow is the skeleton of a sequence without its texts: which steps, on which channel, in which order and branch, after how many days. Any channel in any order: emails you send yourself, a call or another human task, and LinkedIn steps, with or without a LinkedIn invite, for example an email, a call and an email, or a call, a LinkedIn message and an email. A flow with nothing on LinkedIn (only emails and human tasks) needs no LinkedIn account, no LinkedIn profile of the person (an email address does) and no month of LinkedIn outreach (uses_linkedin). You write the texts per person when you start (POST /outreach/linkedin/sequences with flow and texts, or start_flow on the assistant server), and the sequence then has exactly the steps of the flow. There are ready-made flows (invite_note_then_message, invite_then_message, invite_note_two_follow_ups, invites_only, invite_then_inmail, like_then_invite, email_then_invite, email_then_call, emails_only) and the workspace’s own, at most 100. These routes are the tools list_flows, get_flow, save_flow, delete_flow and assign_flow of the assistant server. Free.
Authentication#
Send Authorization: Bearer gtk_…. Create the key under API keys in the menu. Every gtk_ key can call these routes, also while the Signals API is closed. A missing, invalid or revoked key is 401.
Path parameters#
keystring· required — The key of the flow (cfo_after_funding, or a ready-made one).
Response#
objectstring· required — Alwaysflow. One of:flow.keystring· required — The key.name / descriptionstring / string | null· required — How the user sees it.presetboolean· required — A ready-made flow of mySDR: it cannot be changed or deleted; start from it withbased_on.based_onstring | null· required — The flow it started from.archivedboolean· required — The user archived it in mySDR (under Flows): it no longer shows among their active flows.reply_handlingobject· required — What happens after a reply, besides the human tasks inon_reply; only the user sets it, under Reply handling on the Flows page:notify_positive(a positive reply posts to their Slack or Teams) andagent_closes_negative(you close a negative reply yourself: GET /outreach/replies then saysagent_closes).approval_requiredboolean· required — Whether the texts prepared for a lead in this flow must be approved before they start (the default; only the user sets it, under Approval on the Flows page). If so, a start skips anyone whose prepared texts are not approved yet (texts_not_approved), unless the call hastexts_approvedafter the user said yes;flow_texts_to_approveon GET /tables/leads lists them.stepsobject[]· required —key(the name of its text intexts),type(email,linkedin_invite,linkedin_message,inmail,withdraw_invite,human_task,linkedin_like),branch(start,after_accept,if_connected,not_accepted,on_reply),note(on the invite),wait_days,text(whether you write a text for it),sent_by(agentfor an email you send yourself,humanfor a human task, otherwisemysdr),taskon a human task, andconnections_only: trueon a LinkedIn message instart(it only goes to existing connections).channelsstring[]· required — The channels of the flow in the order they first come:email,call(a human task) andlinkedin.uses_linkedinboolean· required — The flow does something on LinkedIn (an invite, a message, an InMail or a like). False: it needs no LinkedIn account, no LinkedIn profile of the person (an email address does) and no month of LinkedIn outreach.has_inviteboolean· required — The flow has a LinkedIn invite, and so branches after it. False: everyone gets the steps ofstartin order.human_task_stepsstring[]· required — The human tasks of the flow: the sequence waits on their outcome (POST /human-tasks/{id}/complete); those inon_replycome after a reply.text_stepsstring[]· required — The step keys that need a text when you start.email_stepsstring[]· required — The emails you send yourself, instartor in a branch after the invite: their text and subject may come at the start or when the step is due.inmail_stepsstring[]· required — The InMails mySDR sends, instart(to anyone who is not a connection) or to people who did not accept: each needs a text (texts) and a subject (subjects) at the start.ready_needsobject· required — What Ready for campaign asks you to prepare with POST /outreach/flows/assign:texts(a text per step key) andsubjects(a subject per email and InMail step). An email step in a lead'ssent_stepsneeds nothing.in_wordsstring[]· required — The steps in plain sentences, to show the user.created_at / updated_at / viastring | null· required — When it was saved, and by which key (Claude); null for a ready-made one.is_defaultboolean— The default flow of the workspace: every lead without a flow of its own follows it. On GET, and after a save withmake_default.dashboard_urlstring· required — The flow in mySDR.
Credits#
Free. This call never uses credits.
Errors#
- 400
invalid_request— A key that is not valid. - 404
not_found— The workspace has no flow with this key. - 401
authentication_error— The Authorization header is missing, or the key is unknown or revoked. - 403
permission_error— API access is not part of your plan, or your account is suspended. - 429
rate_limit_error— More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header. - 503
service_unavailable— The API is temporarily unavailable. Retry later. - 500
internal_error— Something went wrong on our side.
Example
curl "https://mysdr.app/api/v1/outreach/flows/cfo_after_funding" \
-H "Authorization: Bearer $MYSDR_API_KEY"{
"object": "flow",
"key": "cfo_after_funding",
"name": "CFOs after funding",
"description": "For CFOs at companies that just raised.",
"preset": false,
"based_on": "invite_note_two_follow_ups",
"steps": [
{
"key": "invite",
"type": "linkedin_invite",
"branch": "start",
"note": true,
"wait_days": 0,
"text": true,
"subject": false,
"sent_by": "mysdr"
},
{
"key": "message_1",
"type": "linkedin_message",
"branch": "after_accept",
"wait_days": 0,
"text": true,
"subject": false,
"sent_by": "mysdr"
},
{
"key": "follow_up_1",
"type": "linkedin_message",
"branch": "after_accept",
"wait_days": 3,
"text": true,
"subject": false,
"sent_by": "mysdr"
},
{
"key": "connected_1",
"type": "linkedin_message",
"branch": "if_connected",
"wait_days": 0,
"text": true,
"subject": false,
"sent_by": "mysdr"
},
{
"key": "withdraw",
"type": "withdraw_invite",
"branch": "not_accepted",
"wait_days": 16,
"text": false,
"subject": false,
"sent_by": "mysdr"
}
],
"channels": [
"linkedin"
],
"uses_linkedin": true,
"has_invite": true,
"text_steps": [
"invite",
"message_1",
"follow_up_1",
"connected_1"
],
"email_steps": [],
"inmail_steps": [],
"human_task_steps": [],
"ready_needs": {
"texts": [
"invite",
"message_1",
"follow_up_1",
"connected_1"
],
"subjects": []
},
"in_words": [
"invite: an invite with a note.",
"message_1: a message right after the invite is accepted.",
"follow_up_1: a message 3 days after the previous step.",
"connected_1: for an existing connection, a message at the start.",
"withdraw: not accepted after 16 days, the invite is withdrawn and the sequence ends.",
"An email in a branch follows that branch: it only goes out once it is clear whether the invite was accepted.",
"A reply stops the sequence for that person."
],
"created_at": "2026-10-28T08:00:00.000Z",
"updated_at": "2026-10-28T08:00:00.000Z",
"via": "Claude",
"archived": false,
"reply_handling": {
"notify_positive": false,
"agent_closes_negative": false
},
"approval_required": true,
"dashboard_url": "https://mysdr.app/en/gtm/flows?flow=cfo_after_funding"
}