> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firsttouch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Add Dynamic Action

> Create or extend one MCP Dynamic Actions enrollment for exactly one contact.

**Required preflight**

- Call get_guide with topic=dynamic_actions before this tool.
- Before calling this tool, call find_contact_data with every known identity unless verified enrichment was returned earlier in the conversation.
- Then call find_mcp_enrollment with the known identifiers; if candidates are returned, ask which enrollment to continue or whether to start a new sequence, and if none is returned, continue with the requested new action.
- Resolve action.assignedUserId with get_current_user and list_team_members before calling this tool.
- When content uses variables, use only fully qualified templates such as {ft.flow.prospect_first_name}; do not use aliases such as {{firstName}}.

<details>
<summary><strong>Workflow and write receipt</strong></summary>
<ul>
<li>This tool adds one action step per call and returns flowPlanId, enrollmentId, nodeId, assignedUserId, approval/task flags, taskIds when task rows are available, taskIdsPending/taskMaterializationStatus for async task materialization, uiLinks, and nextSteps.</li>
<li>Treat enrollmentId + nodeId as the write receipt; if nodeAppended=true, do not retry add_dynamic_action for the same requested step just because taskIds is empty or get_flow_enrollment has not materialized actions/tasks yet.</li>
</ul>
</details>

<details>
<summary><strong>Contact identity</strong></summary>
<ul>
<li>Every appended action requires contact.firstName and contact.lastName in its effective identity.</li>
<li>For a new sequence, provide both names in contact plus contact.email, contact.linkedInUrl, contact.phone, or company.domain; contact.prospectId is also supported when it resolves to a full name.</li>
<li>When continuing a selected enrollment that lacks either name, provide both names in contact to backfill it.</li>
<li>Ask the customer for missing names and do not invoke an enrichment tool automatically.</li>
<li>Use the optional contact and company objects for verified context returned by find_contact_data or explicit enrichment; their fields are all optional.</li>
<li>Populate every other verified known field.</li>
</ul>
</details>

<details>
<summary><strong>Content and email behavior</strong></summary>
<ul>
<li>This tool does not enrich request inputs or generate content; pass final email, LinkedIn send, call, or task text written by the MCP client.</li>
<li>linkedin_profile_view has no content and only supports delay, appendTarget, and assignedUserId.</li>
<li>MCP Dynamic Actions do not use AI to generate email subjects.</li>
<li>For a new email enrollment, omit action.subjectType: it defaults to new_thread and action.subject is required.</li>
<li>For an existing enrollment, action.subjectType is required: choose new_thread and provide action.subject for a separate conversation, or choose reply only when the selected append branch has a prior email;<br />reply inherits that subject and must omit action.subject.</li>
<li>Use find_mcp_enrollment candidate.root to trace the requested append branch.</li>
<li>Use get_flow_enrollment after selecting an enrollment only when complete enrollment/action/task details are needed.</li>
</ul>
</details>

<details>
<summary><strong>Existing enrollment and priority</strong></summary>
<ul>
<li>To continue an existing MCP Dynamic Actions enrollment, pass enrollmentId;<br />existing enrollment identity wins, and supplied contact.email, contact.linkedInUrl, contact.phone, or contact.prospectId can only backfill missing values, not retarget the enrollment.</li>
<li>Other contact and company context only fills missing enrollment properties and never overwrites an existing value.</li>
<li>Set whole-enrollment scheduling priority only when the customer explicitly asks: use 1 for High, 0 or omit for normal, and -1 for Low.</li>
<li>Priority on an existing enrollment updates it.</li>
</ul>
</details>

<details>
<summary><strong>Sender eligibility</strong></summary>
<ul>
<li>Resolve and pass action.assignedUserId before every call: use the current MCP user when no sender is requested, a named member when requested, or one eligible team member when the customer asks for any capable sender.</li>
<li>Email requires Email actions permission and a connected email account.</li>
<li>LinkedIn connect/message/profile requires Social permission plus a live synced LinkedIn account; InMail additionally requires an eligible Premium or Sales Navigator plan.</li>
<li>A linkedin_connect requires the selected sender not to be a saved 1st-degree connection of the contact; if already connected, use linkedin_message instead.</li>
<li>A linkedin_message outside a connection_accepted branch requires the selected sender to be a saved 1st-degree connection; when another team member is connected instead, the validation error identifies that member for reassignment.</li>
<li>When the selected sender is not connected, use linkedin_connect followed by a message on connection_accepted, or use linkedin_inmail if the sender has an eligible Premium or Sales Navigator plan.</li>
<li>Call and manual tasks require their matching permissions.</li>
<li>If the selected user lacks a required capability, this tool rejects the action instead of silently assigning another user.</li>
</ul>
</details>

<details>
<summary><strong>Action requirements and scheduling</strong></summary>
<ul>
<li>Pass exactly one action with type email, linkedin_connect, linkedin_message, linkedin_inmail, linkedin_profile_view, manual_task, or call_task.</li>
<li>Each action type exposes only its supported fields.</li>
<li>Email requires action.prompt and an effective recipient email.</li>
<li>LinkedIn messages require action.message and an effective linkedInUrl.</li>
<li>linkedin_inmail requires non-empty action.prompt and action.subject, and does not accept action.message.</li>
<li>linkedin_profile_view supports one action per default, connection accepted, or connection timeout branch and cannot have content or human approval.</li>
<li>Manual tasks require action.name.</li>
<li>Call tasks require action.message and an effective phone; action.name is not a call script.</li>
<li>Email, LinkedIn send actions, InMail, and call actions default to no human approval; set action.isHumanApprovalRequired=true only when the customer explicitly asks for review/approval.</li>
<li>Omit action.delay or use 00:00:00 for no delay/immediate execution.</li>
<li>For a delay, use d.hh:mm:ss or hh:mm:ss, for example 5.00:00:00 for 5 days; do not use natural language such as &#39;5 days&#39;.</li>
<li>Use action.appendTarget only for LinkedIn connection accepted/timeout branches.</li>
<li>For linkedin_connect, action.connectionTimeout optionally sets the acceptance window using a positive d.hh:mm:ss or hh:mm:ss TimeSpan; omit it for the 14-day default.</li>
</ul>
</details>

<details>
<summary><strong>Shared Flow Plan settings</strong></summary>
<ul>
<li>This tool has no per-action HubSpot enrichment or task-sync flags: those are shared MCP Flow Plan settings configured only with update_flow_plan as mcpDynamicActionsOptions.is_enrich_hubspot and mcpDynamicActionsOptions.is_push_to_hubspot_tasks.</li>
<li>The task setting updates call, manual, and approval task sync together.</li>
<li>The returned flowPlanId is read-only for its name, flow structure, and other normal mutations; do not use it with flow-root, publication, audience, or enrollment mutation tools.</li>
</ul>
</details>



## OpenAPI

````yaml https://gateway.firsttouch.ai/api/public/openapi.json post /api/public/tools/add_dynamic_action
openapi: 3.1.0
info:
  title: FirstTouch Public CRM Tool API
  version: 1.0.0.0
  description: >-
    FirstTouch's Public CRM Tool API exposes the same operations and business
    rules as the full CRM MCP server.


    ## Authentication


    Send your user-scoped key for the selected team in the `X-API-Key` header.
    Every active team member can create and manage only their own keys from
    **Settings > MCP & API** in FirstTouch.


    ## Calling a tool


    Every tool uses `POST /api/public/tools/{tool_name}` with a JSON object
    request body. Successful calls return the tool result directly as JSON.


    Use the gateway origin that serves this document. Do not copy a URL for a
    different environment.


    ```bash

    curl -X POST "<gateway-origin>/api/public/tools/get_current_user" \
      -H "X-API-Key: ftpublic_your_key" \
      -H "Content-Type: application/json" \
      -d '{}'
    ```


    Tool schemas and descriptions below are the source of truth for inputs,
    outputs, costs, and side effects.


    ## MCP agent integration guidance


    These rules are sourced from the MCP server instructions. They are primarily
    intended for agents that coordinate several tools; expand only the topics
    relevant to your workflow.

    <details>

    <summary><strong>Choosing the right workflow</strong></summary>

    <ul>

    <li>Treat tool schemas and descriptions as the source of truth.</li>

    <li>Basic structure: external contacts become an Audience; an Audience is
    the source for a reusable Flow Plan; source mode is different from
    enrollment mode; publishing a Manual Mode Flow Plan does not enroll awaiting
    contacts by itself.</li>

    <li>When the user has multiple external contacts, for example pasted rows, a
    CSV file, or a CRM export, create or select an Audience before creating or
    attaching a Flow Plan. Do not enrich or add dynamic actions one contact at a
    time unless the user explicitly asks for single-contact work.</li>

    <li>Hard override: a request to send, schedule, draft, approve, or follow up
    with one named person is a single-contact dynamic action request, even when
    the user asks for human approval, AI-generated text, variables, or a
    specific email/LinkedIn/call/manual action. Do not create an Audience or
    Flow Plan for this.</li>

    <li>Choose dynamic actions vs flow plans by asking one question: is the user
    describing recipients or describing actions? Describing recipients, such as
    a list, segment, filter, or everyone who matches criteria, means normal
    flow-plan/audience tools. Describing actions, such as &quot;send a connect,
    then in 3 days follow up about X&quot;<br />or &quot;send a follow-up email
    to Brittany Tapparo with human approval and AI text&quot;<br />means
    add_dynamic_action. When still unsure, single contact means dynamic action
    and multiple contacts means flow plan. Tell the user in one line what you
    picked.</li>

    <li>Hard override: if the user names an existing flow, use
    add_manual_flow_enrollment or enroll_awaiting_flow_items;<br />do not create
    a new flow plan or dynamic action. For add_manual_flow_enrollment, pass
    enrollmentMode=enroll when the user explicitly wants immediate
    enrollment;<br />otherwise it follows the flow plan mode.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Social Engagement</strong></summary>

    <ul>

    <li>Social Engagement structure: when the user asks to monitor/listen to
    LinkedIn profile or company page likes/comments and route engagers, for
    example &quot;monitor this profile and send connection requests to everyone
    who engaged&quot;, call manage_social_engagement_monitored_profile
    action=add first. Use response.socialEngagement.flowPlan.id as the existing
    linked Social Engagement flow to inspect/update/publish;<br />do not create
    a separate Social Engagement flow and do not relink config. If the user
    wants listening to start now, pass enableSocialEngagement=true during add or
    use write_social_engagement_config isEnabled=true;<br />publish the linked
    flow before expecting collected engagers to enter it.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Contact discovery and enrichment</strong></summary>

    <ul>

    <li>For contact discovery, assemble ProspectSearchFiltersDto directly from
    the user&#39;s request. Include only fields clearly requested or strongly
    implied; do not invent unsupported filters.</li>

    <li>Before contact discovery, call get_guide with topic=contact_discovery.
    Filter rules: use one two-letter Alpha-2 country code, bare company domains,
    concise titles, region/city with region_mode/city_mode=exclude for location
    exclusions, current_company_name with current_company_name_mode=exclude for
    company-name exclusions, current_company_primary_industry for strict company
    industry filters, and exclude_current_company_primary_industry for strict
    company industry exclusions. Use
    current_company_industry/exclude_current_company_industry only when broader
    inferred or secondary company industry matches are acceptable. Use common
    exact industry values from the guide;<br />call
    get_contact_discovery_industry_values when the needed exact supported
    industry is not listed there.</li>

    <li>For contact discovery previews, suggest discover_contacts with
    pageSize=1. It returns totalResultCount plus the first matching contact,
    reserves 1 credit, and charges 1 FirstTouch credit if a profile row is
    returned.</li>

    <li>A discover_contacts pageSize=1 preview is the first page of the same
    search, not a separate count-only call. If the customer wants more contacts
    after a preview, call discover_contacts with nextToken=response.nextPage and
    request only the additional contacts needed. For example, after previewing 1
    contact for a target of 3, use pageSize=2 with nextToken;<br />do not
    restart the same search without nextToken.</li>

    <li>discover_contacts reserves pageSize credits and charges 1 FirstTouch
    credit per returned profile row, with pageSize limited to 10.</li>

    <li>Any cost returned by MCP tools is in FirstTouch credits, not USD. Do not
    present MCP cost fields as dollar prices unless a response explicitly
    returns a Team Plan Subscription price in USD.</li>

    <li>After discover_contacts, use response.nextSteps to offer a larger page,
    audience creation, another page, background import, flow attachment, or
    enrollment.</li>

    <li>start_contact_discovery_audience_import can fetch up to 100 total
    profiles asynchronously and requires confirmedMaxCredits for additional
    rows.</li>

    <li>Charged enrichment tools consume FirstTouch credits when called.
    enrich_email, enrich_phone, enrich_contact, and enrich_company do not
    automatically apply or synchronize their returned data to any existing
    enrollment, Awaiting candidate, audience, HubSpot record, or saved prospect
    record. After using an enrichment result, explicitly tell the customer that
    nothing was injected automatically. Use the data in an Audience, enrollment,
    or other write only when the customer explicitly requests that separate
    action and the relevant tool permits it.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Single-contact identity and enrollment</strong></summary>

    <ul>

    <li>For one-contact dynamic actions, call get_guide with
    topic=dynamic_actions before add_dynamic_action. The guide is the preflight
    for contact lookup, existing enrollment choice, variable usage, approval
    behavior, enrichment choice, LinkedIn branch handling, and multi-step
    sequencing. Use topic=flow_plan_creation instead for reusable flow-plan
    creation.</li>

    <li>Hard override: before find_mcp_enrollment or add_dynamic_action for a
    single contact, call find_contact_data with every known identity unless a
    verified enrich_contact, enrich_email, enrich_phone, or enrich_company
    result was returned earlier in this conversation. Do this even for a manual
    task or when the supplied identity seems sufficient. Use the
    lookup/enrichment result plus customer-supplied values to populate
    add_dynamic_action.contact and add_dynamic_action.company;<br />do not rely
    on chat memory.</li>

    <li>For a single-contact action request, send enrollmentId when continuing
    an existing sequence, and put every known person field in
    add_dynamic_action.contact and company field in add_dynamic_action.company:
    prospectId, email, linkedInUrl, phone, firstName, lastName, role, location,
    company domain, and other company context. Exact identifiers such as
    enrollmentId, contact.prospectId, contact.email, contact.linkedInUrl, and
    contact.phone are strongest;<br />names and company.domain provide useful
    fallback matching. You do not need to resolve a prospectId when another
    supported identity is available.</li>

    <li>When the customer asks where contacts appear across FirstTouch, first
    use find_contact_data for name-only or ambiguous input. For the selected
    contact, call get_contact_trace with every supported identity already known
    as a separate identities item, up to 10: include each known email, LinkedIn
    URL, phone, HubSpot contact id, and a firstName, lastName, and companyDomain
    item when all three are known. Do not omit a known supported identity just
    because another exact identity is available. Each item contains exactly one
    direct identifier or the complete name-and-domain identity. The trace is a
    union of matches, not one canonical contact;<br />use each returned
    item&#39;s matchedBy values to understand why it was included. Do not pass
    prospectId or enrollmentId, partial name data, or several identity kinds in
    one identities item.</li>

    <li>Every single-contact dynamic action requires contact.firstName and
    contact.lastName in its effective identity. For a new sequence, provide both
    names in contact with the strongest exact target: contact.email,
    contact.linkedInUrl, contact.phone, or company.domain. A contact.prospectId
    is supported when it resolves to a full name. When continuing a selected
    enrollment that lacks either name, ask the customer for both names and pass
    them in contact;<br />do not invoke an enrichment tool just to obtain a
    name. Use enrollmentId to continue an existing sequence.</li>

    <li>Treat a customer-supplied exact action target, such as contact.email,
    contact.linkedInUrl, or contact.phone, as authoritative. A later weaker
    lookup by name, company, or partial identity must not replace that target.
    If lookup or enrichment returns a different exact email, LinkedIn URL, or
    phone, show the mismatch and ask which value to use before calling
    add_dynamic_action.</li>

    <li>After find_contact_data or verified same-conversation enrichment, call
    find_mcp_enrollment for a named or resolved contact with the known
    identifiers. If no candidate is returned and all required identity and
    action data is available, create the new dynamic action immediately: the
    customer&#39;s original request is sufficient confirmation, so do not ask
    them to confirm the same action again. If any candidate is returned, show
    its sourceDescription when present, then ask the customer whether to
    continue a specific enrollment or start a new sequence. Do not infer this
    from status or sourceDescription: completed, canceled, failed, pending, and
    in-progress enrollments all require explicit customer choice before
    add_dynamic_action.</li>

    <li>Hard override: after the customer chooses to continue a returned MCP
    Dynamic Actions enrollment, extend it with add_dynamic_action by passing the
    selected enrollmentId. Existing enrollment identity wins;<br />include newly
    known contact/company fields only to fill missing enrollment data, never to
    change the person. If the selected enrollment lacks either name, ask the
    customer for both before appending them in contact. If a new exact
    contact.email, contact.linkedInUrl, contact.phone, or contact.prospectId
    differs from the selected enrollment, ask whether to start a new sequence
    instead.</li>

    <li>When creating a new single-contact dynamic sequence after a lookup
    returned a candidate, carry forward all useful known candidate fields into
    add_dynamic_action.contact and add_dynamic_action.company. This is
    especially required when action.message, action.prompt, action.subject, or
    action.name uses variables such as {ft.flow.prospect_first_name};<br />pass
    the corresponding contact field instead of relying on chat memory.</li>

    <li>MCP Dynamic Actions do not enrich missing request inputs before adding
    an action: they use data already known in the request, saved prospect
    identity, contact-channel data returned by lookup sources such as
    enrollments or audience contacts, or the selected MCP enrollment. HubSpot
    contact/company enrichment after enrollment creation is separately
    controlled by the shared MCP Flow Plan&#39;s is_enrich_hubspot setting,
    which is enabled by default. It does not replace the required
    contact.firstName, contact.lastName, or action target. For a missing
    contact.firstName or contact.lastName, ask the customer first;<br />use
    explicit lookup/enrichment only after customer confirmation.</li>

    <li>MCP Dynamic Actions do not use AI to generate email content or subjects.
    When enrollmentId is omitted, the new email enrollment defaults to
    new_thread and requires the final action.subject;<br />action.subjectType is
    optional. When extending an existing enrollment, action.subjectType is
    required: use find_mcp_enrollment candidate.root to trace the requested
    append branch and choose new_thread (provide action.subject) or reply (only
    with a prior email on that branch;<br />omit action.subject so it is
    inherited). If the root has a prior email on the requested branch but the
    customer has not said whether this email is a reply or a separate
    conversation, ask before calling add_dynamic_action. Use get_flow_enrollment
    after selecting an enrollment when complete enrollment/action/task details
    or inbound reply content is needed;<br />list enrollment tools expose reply
    counts and latest timestamp only.</li>

    <li>Before calling add_dynamic_action with contact fields merged from
    lookup/enrichment and customer-provided data, summarize the final prospect
    identity and exact action target and ask the customer to confirm. For
    example: &quot;I will send the email to person@example.com for Artem
    Fokin;<br />is that okay?&quot;<br />Do not ask this extra confirmation when
    all required exact targets came directly from the customer and no
    lookup/enrichment data was merged.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Dynamic Action sequencing and cleanup</strong></summary>

    <ul>

    <li>For a multi-step dynamic action sequence for one contact, call
    add_dynamic_action once per step in order, with the returned enrollmentId,
    requested delays, and action.appendTarget when the user wants a LinkedIn
    accepted or timeout branch. Do not call get_guide with
    topic=flow_plan_creation, create_flow_plan, create_audience,
    attach_audience_to_flow, replace_flow_root, or manage_flow_publication for
    one-contact action requests. list_team_members is allowed only to resolve a
    requested sender or assignee. The only exception is update_flow_plan when
    the customer explicitly asks to change the shared MCP Dynamic Actions
    HubSpot settings.</li>

    <li>MCP Dynamic Actions support one LinkedIn connect action per enrollment,
    up to five linkedin_inmail actions per branch, and one linkedin_profile_view
    action per default, accepted, or timeout branch. linkedin_connect waits 14
    days for acceptance by default;<br />when the customer requests another
    timeout, set action.connectionTimeout to a positive TimeSpan in d.hh:mm:ss
    or hh:mm:ss format. linkedin_inmail requires a non-empty action.prompt and
    action.subject;<br />action.message is unsupported. After the first LinkedIn
    chat step on the same branch, every linkedin_inmail or linkedin_message step
    must keep at least three hours of total delay since the previous LinkedIn
    chat step, including intermediate blocking delays and its own action.delay.
    linkedin_profile_view requires a LinkedIn URL, has no content or human
    approval, and runs without a user task. A follow-up after an unresolved
    linkedin_connect defaults to the accepted branch. Use
    action.appendTarget=connection_timeout for timeout fallback, and
    action.appendTarget=connection_accepted when the user explicitly says
    accepted/after they accept.</li>

    <li>After add_dynamic_action returns nodeAppended=true, treat enrollmentId
    and nodeId as the write receipt for that requested step. Empty taskIds or
    temporarily empty get_flow_enrollment actions/tasks can mean async task
    materialization is still pending, or that a delayed/branched task is
    expected later;<br />check taskIdsPending and taskMaterializationStatus,
    poll list_user_tasks/get_flow_enrollment only when taskIdsPending=true, and
    do not retry add_dynamic_action for the same step.</li>

    <li>Use remove_dynamic_action_prospect only to clean up or cancel one MCP
    Dynamic Actions enrollment. Prefer the returned enrollmentId;<br />use
    prospectId only when enrollmentId is not available and it identifies exactly
    one non-canceled MCP Dynamic Actions enrollment. If multiple enrollments may
    exist for the same prospect, call find_mcp_enrollment and ask which
    enrollmentId to cancel. Do not use it for normal flow-plan enrollments.</li>

    <li>Hard override: do not modify the MCP Dynamic Actions flow plan
    structure, name, AI qualification, candidates, publication, audience, or
    enrollments. The only permitted direct mutation is update_flow_plan for its
    shared HubSpot settings: mcpDynamicActionsOptions.is_enrich_hubspot and
    mcpDynamicActionsOptions.is_push_to_hubspot_tasks. is_push_to_hubspot_tasks
    controls call, manual, and approval task sync together. These are shared
    Flow Plan settings, not add_dynamic_action parameters and not per-enrollment
    overrides. Do not pass the MCP flowPlanId to replace_flow_root,
    manage_flow_publication, attach_audience_to_flow,
    add_manual_flow_enrollment, enroll_awaiting_flow_items,
    cancel_flow_enrollments, or other normal flow-plan mutation tools. For
    LinkedIn connection accepted/timeout paths, use add_dynamic_action with
    action.appendTarget;<br />do not rewrite the shared MCP flow plan.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Tasks and human approval</strong></summary>

    <ul>

    <li>For a general request to view pending user or team tasks, or tasks the
    customer can approve, review, or act on, call list_user_tasks without types.
    types is an exact stored task-kind filter: call tasks require logging a
    call, manual tasks require marking manual work done, and section_approval
    tasks require approving grouped actions. All three can contain tasks for the
    customer to review or act on. Use types only when the customer explicitly
    requests a particular task kind.</li>

    <li>After add_dynamic_action, tell the customer which created actions
    require human approval or user task completion before they can run. Do not
    say the whole sequence will run automatically when any response has
    requiresHumanApproval=true or createsUserTask=true.</li>

    <li>After add_dynamic_action, offer the returned uiLinks. If &quot;Open
    task&quot;<br />is present, show it first;<br />otherwise offer &quot;Open
    tasks&quot;<br />when a task is expected, plus &quot;Open flow
    activity&quot;<br />so the customer can review the enrollment/actions in
    FirstTouch.</li>

    <li>After add_dynamic_action creates an immediate action that requires human
    approval, ask the customer to review and confirm the created task. For team
    owners/admins, use list_user_tasks with flowIds=[enrollmentId],
    statuses=[todo], types=[section_approval], includeTeamTasks=true, then
    preview_task. For regular users, use get_flow_enrollment to find the pending
    section_approval task;<br />complete it only if the caller has access,
    otherwise ask the assignee or a team owner/admin to approve it. Call
    complete_task only after the customer explicitly approves.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Reusable flows and audiences</strong></summary>

    <ul>

    <li>For flow-plan creation, call get_guide with topic=flow_plan_creation.
    create_flow_plan requires a complete reusable root tree. Omit options, AI
    qualification, and candidates unless the user explicitly wants to override
    the server defaults.</li>

    <li>For a flow workspace, use candidateDetails.items as the live source of
    truth for configured flow-plan and reassignment candidates. Match by userId.
    Never infer LinkedIn availability from reassignment payload
    candidates[].linkedin_account_id: it is a deprecated, ignored field and may
    be null even when the candidate has a usable LinkedIn account. Check
    candidateDetails.items[].linkedinAccount.status and synchronization fields
    instead.</li>

    <li>Before creating or publishing a reusable flow, directly ask whether the
    user wants Manual Mode or Auto-Enrollment when they have not already
    specified it. Manual Mode uses processingStrategy=manual and requires
    explicit enrollment later. Standard Auto-Enrollment uses
    processingStrategy=default;<br />use processingStrategy=new_members_only
    only when the user explicitly asks for new source members only.</li>

    <li>For complex Flow/Audience interactions, first present a short plan of
    the exact flow, audience, attachment, publish, and enrollment actions you
    intend to perform, then ask the customer to confirm before calling write
    tools.</li>

    <li>For flow updates, prefer update_flow_plan for settings,
    replace_flow_root for node-tree replacement, and manage_flow_publication for
    publish/unpublish.</li>

    <li>After create_flow_plan or get_flow_workspace, use response.nextSteps to
    offer a test enrollment, all awaiting users, or selected users. For Manual
    Mode, suggest enrolling one selected test user before broader rollout when
    appropriate.</li>

    <li>Publishing a Manual Mode flow does not enroll awaiting contacts. Use
    enroll_awaiting_flow_items when the user asks to start awaiting contacts or
    signals in an attached flow.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Senders and capabilities</strong></summary>

    <ul>

    <li>When a customer specifies a sender or action assignee by email, name, or
    user id, call list_team_members and compare the supplied identity with the
    returned members. Select the clearly intended member, even when one supplied
    character is likely wrong;<br />ask the customer only when more than one
    member is plausible or none fits. Pass the selected returned userId as
    action.assignedUserId. For a LinkedIn action, inspect isLinkedinReady;<br
    />if the requested sender is not ready, explain that and ask before using
    allowUnreadyLinkedInAccount. Never infer a sender from the current user, a
    LinkedIn account name, or a LinkedIn Unibox conversation account.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Execution queues and messaging</strong></summary>

    <ul>

    <li>A null enrollment prospect.linkedinUrl is current data, not a prediction
    that a pending or delayed LinkedIn action will fail. LinkedIn actions
    attempt a fresh prospect LinkedIn lookup when they activate. Report a
    missing LinkedIn URL as the cause only when the LinkedIn action has actually
    failed with the corresponding action error;<br />for active/current LinkedIn
    execution state, use list_linkedin_outreach_queue.</li>

    <li>Use list_linkedin_outreach_queue when the customer asks for
    active/current LinkedIn actions, LinkedIn actions waiting to run, LinkedIn
    action/request status, LinkedIn queue, why a LinkedIn action has not sent
    yet, or LinkedIn actions needing review. Prefer view=active for
    active/current/waiting requests because it excludes terminal history;<br
    />use view=all for normal outreach rows across all statuses, and
    view=diagnostic_all only for expanded debug/show-everything inspection
    across non-standard/internal LinkedIn request types. Use
    list_enrollments/list_flow_plan_enrollments for broader flow/enrollment
    pages, not as the first tool for LinkedIn execution queue questions. When
    the customer asks for enrollments/activities and specifically mentions
    LinkedIn actions, check list_linkedin_outreach_queue as well because
    enrollment rows do not expose provider request status, awaiting
    requirements, or request gates.</li>

    <li>Use LinkedIn Unibox tools for synchronized conversation state:
    get_linkedin_unibox_counts and list_linkedin_unibox_conversations inspect
    counts and conversation summaries;<br />get_linkedin_unibox_conversation
    reads full messages without marking them read. To inspect one team
    member&#39;s Unibox conversations, use that member&#39;s linkedinAccount.id
    from list_team_members as linAccountId. These read tools never trigger
    synchronization. Call update_linkedin_unibox_conversation_state only for an
    explicit request to change read, archive, or tag state. It updates only
    supplied fields;<br />tag=hot or nurture sets the one tag and tag=none
    clears it.</li>

    <li>Call send_linkedin_unibox_message only when the customer explicitly
    requested the exact text to be sent or approved an exact draft. Do not treat
    inspection, summarization, or drafting as approval. Do not override the
    sender account&#39;s manual reply mode, and never retry automatically. On an
    ambiguous failure or timeout, re-fetch the conversation and ask the customer
    whether to retry.</li>

    <li>Use list_email_send_queue when the customer asks for submitted email
    sends, email queue status, sent/failed/canceled history, or why an email has
    not sent. Select view=in_queue, awaiting, done, canceled, or failed;<br
    />omitted userIds always means the current caller, while admins/team owners
    may select other team members explicitly. The response includes all five
    counts for the same filters. Treat estimated_execution_time_utc as
    FirstTouch&#39;s expected send time, never inbox delivery. Phase 1 includes
    only actions submitted to the email sending service, so inspect
    get_flow_enrollment, list_enrollments, and list_user_tasks when an expected
    future or pre-dispatch action is absent.</li>

    </ul>

    </details>


    <details>

    <summary><strong>Metrics</strong></summary>

    <ul>

    <li>Use get_team_metrics when the customer asks for team performance,
    actions sent, email/LinkedIn metrics, engagement, replies, sentiment,
    opportunities, meetings booked, or metrics filtered by date range,
    flow/source, or sender/team member. It supports flowPlanIds, userIds,
    fromUtc, toUtc, and optional email/LinkedIn chart buckets. Use
    list_flow_plans with includeMetrics=true for ranking or comparing individual
    flow plans, and use enrollment tools only when the customer asks for the
    underlying contacts/activities behind the counts.</li>

    <li>When finding the top/most/highest flow plan by a metric, use
    list_flow_plans with the relevant orderBy/orderDirection and limit=5 unless
    the customer asks for more. Set includeMetrics/includeCost only when the
    customer needs those values.</li>

    </ul>

    </details>
servers: []
security: []
paths:
  /api/public/tools/add_dynamic_action:
    post:
      tags:
        - FirstTouch tools
      summary: Add Dynamic Action
      description: >-
        Create or extend one MCP Dynamic Actions enrollment for exactly one
        contact.


        **Required preflight**


        - Call get_guide with topic=dynamic_actions before this tool.

        - Before calling this tool, call find_contact_data with every known
        identity unless verified enrichment was returned earlier in the
        conversation.

        - Then call find_mcp_enrollment with the known identifiers; if
        candidates are returned, ask which enrollment to continue or whether to
        start a new sequence, and if none is returned, continue with the
        requested new action.

        - Resolve action.assignedUserId with get_current_user and
        list_team_members before calling this tool.

        - When content uses variables, use only fully qualified templates such
        as {ft.flow.prospect_first_name}; do not use aliases such as
        {{firstName}}.


        <details>

        <summary><strong>Workflow and write receipt</strong></summary>

        <ul>

        <li>This tool adds one action step per call and returns flowPlanId,
        enrollmentId, nodeId, assignedUserId, approval/task flags, taskIds when
        task rows are available, taskIdsPending/taskMaterializationStatus for
        async task materialization, uiLinks, and nextSteps.</li>

        <li>Treat enrollmentId + nodeId as the write receipt; if
        nodeAppended=true, do not retry add_dynamic_action for the same
        requested step just because taskIds is empty or get_flow_enrollment has
        not materialized actions/tasks yet.</li>

        </ul>

        </details>


        <details>

        <summary><strong>Contact identity</strong></summary>

        <ul>

        <li>Every appended action requires contact.firstName and
        contact.lastName in its effective identity.</li>

        <li>For a new sequence, provide both names in contact plus
        contact.email, contact.linkedInUrl, contact.phone, or company.domain;
        contact.prospectId is also supported when it resolves to a full
        name.</li>

        <li>When continuing a selected enrollment that lacks either name,
        provide both names in contact to backfill it.</li>

        <li>Ask the customer for missing names and do not invoke an enrichment
        tool automatically.</li>

        <li>Use the optional contact and company objects for verified context
        returned by find_contact_data or explicit enrichment; their fields are
        all optional.</li>

        <li>Populate every other verified known field.</li>

        </ul>

        </details>


        <details>

        <summary><strong>Content and email behavior</strong></summary>

        <ul>

        <li>This tool does not enrich request inputs or generate content; pass
        final email, LinkedIn send, call, or task text written by the MCP
        client.</li>

        <li>linkedin_profile_view has no content and only supports delay,
        appendTarget, and assignedUserId.</li>

        <li>MCP Dynamic Actions do not use AI to generate email subjects.</li>

        <li>For a new email enrollment, omit action.subjectType: it defaults to
        new_thread and action.subject is required.</li>

        <li>For an existing enrollment, action.subjectType is required: choose
        new_thread and provide action.subject for a separate conversation, or
        choose reply only when the selected append branch has a prior email;<br
        />reply inherits that subject and must omit action.subject.</li>

        <li>Use find_mcp_enrollment candidate.root to trace the requested append
        branch.</li>

        <li>Use get_flow_enrollment after selecting an enrollment only when
        complete enrollment/action/task details are needed.</li>

        </ul>

        </details>


        <details>

        <summary><strong>Existing enrollment and priority</strong></summary>

        <ul>

        <li>To continue an existing MCP Dynamic Actions enrollment, pass
        enrollmentId;<br />existing enrollment identity wins, and supplied
        contact.email, contact.linkedInUrl, contact.phone, or contact.prospectId
        can only backfill missing values, not retarget the enrollment.</li>

        <li>Other contact and company context only fills missing enrollment
        properties and never overwrites an existing value.</li>

        <li>Set whole-enrollment scheduling priority only when the customer
        explicitly asks: use 1 for High, 0 or omit for normal, and -1 for
        Low.</li>

        <li>Priority on an existing enrollment updates it.</li>

        </ul>

        </details>


        <details>

        <summary><strong>Sender eligibility</strong></summary>

        <ul>

        <li>Resolve and pass action.assignedUserId before every call: use the
        current MCP user when no sender is requested, a named member when
        requested, or one eligible team member when the customer asks for any
        capable sender.</li>

        <li>Email requires Email actions permission and a connected email
        account.</li>

        <li>LinkedIn connect/message/profile requires Social permission plus a
        live synced LinkedIn account; InMail additionally requires an eligible
        Premium or Sales Navigator plan.</li>

        <li>A linkedin_connect requires the selected sender not to be a saved
        1st-degree connection of the contact; if already connected, use
        linkedin_message instead.</li>

        <li>A linkedin_message outside a connection_accepted branch requires the
        selected sender to be a saved 1st-degree connection; when another team
        member is connected instead, the validation error identifies that member
        for reassignment.</li>

        <li>When the selected sender is not connected, use linkedin_connect
        followed by a message on connection_accepted, or use linkedin_inmail if
        the sender has an eligible Premium or Sales Navigator plan.</li>

        <li>Call and manual tasks require their matching permissions.</li>

        <li>If the selected user lacks a required capability, this tool rejects
        the action instead of silently assigning another user.</li>

        </ul>

        </details>


        <details>

        <summary><strong>Action requirements and scheduling</strong></summary>

        <ul>

        <li>Pass exactly one action with type email, linkedin_connect,
        linkedin_message, linkedin_inmail, linkedin_profile_view, manual_task,
        or call_task.</li>

        <li>Each action type exposes only its supported fields.</li>

        <li>Email requires action.prompt and an effective recipient email.</li>

        <li>LinkedIn messages require action.message and an effective
        linkedInUrl.</li>

        <li>linkedin_inmail requires non-empty action.prompt and action.subject,
        and does not accept action.message.</li>

        <li>linkedin_profile_view supports one action per default, connection
        accepted, or connection timeout branch and cannot have content or human
        approval.</li>

        <li>Manual tasks require action.name.</li>

        <li>Call tasks require action.message and an effective phone;
        action.name is not a call script.</li>

        <li>Email, LinkedIn send actions, InMail, and call actions default to no
        human approval; set action.isHumanApprovalRequired=true only when the
        customer explicitly asks for review/approval.</li>

        <li>Omit action.delay or use 00:00:00 for no delay/immediate
        execution.</li>

        <li>For a delay, use d.hh:mm:ss or hh:mm:ss, for example 5.00:00:00 for
        5 days; do not use natural language such as &#39;5 days&#39;.</li>

        <li>Use action.appendTarget only for LinkedIn connection
        accepted/timeout branches.</li>

        <li>For linkedin_connect, action.connectionTimeout optionally sets the
        acceptance window using a positive d.hh:mm:ss or hh:mm:ss TimeSpan; omit
        it for the 14-day default.</li>

        </ul>

        </details>


        <details>

        <summary><strong>Shared Flow Plan settings</strong></summary>

        <ul>

        <li>This tool has no per-action HubSpot enrichment or task-sync flags:
        those are shared MCP Flow Plan settings configured only with
        update_flow_plan as mcpDynamicActionsOptions.is_enrich_hubspot and
        mcpDynamicActionsOptions.is_push_to_hubspot_tasks.</li>

        <li>The task setting updates call, manual, and approval task sync
        together.</li>

        <li>The returned flowPlanId is read-only for its name, flow structure,
        and other normal mutations; do not use it with flow-root, publication,
        audience, or enrollment mutation tools.</li>

        </ul>

        </details>
      operationId: add_dynamic_action
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/add_dynamic_action_input'
      responses:
        '200':
          description: Tool result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/add_dynamic_action_output'
        '400':
          description: Malformed tool input or validation failure.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
        '401':
          description: Authentication failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
        '403':
          description: The caller cannot perform this operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
        '404':
          description: The requested resource was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
        '409':
          description: The operation conflicts with current state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
        '429':
          description: The operation was rate limited.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
        '499':
          description: The client canceled the request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
        '500':
          description: Unexpected tool failure.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
      security:
        - X-API-Key: []
components:
  schemas:
    add_dynamic_action_input:
      type: object
      properties:
        action:
          description: >-
            Action to add. Select exactly one typed variant. email requires
            prompt; linkedin_message and call_task require message;
            linkedin_inmail requires prompt and subject; manual_task requires
            name. Every variant requires assignedUserId.
          type:
            - object
            - 'null'
          required:
            - type
          anyOf:
            - properties:
                type:
                  const: email
                prompt:
                  description: >-
                    Final email body. MCP Dynamic Actions do not generate email
                    content.
                  type:
                    - string
                    - 'null'
                subject:
                  description: >-
                    Email subject. Required for a new thread and omitted for a
                    reply, which reuses the previous subject.
                  type:
                    - string
                    - 'null'
                subjectType:
                  description: >-
                    For an existing enrollment, choose new_thread or reply. Omit
                    for a new enrollment, which defaults to new_thread.
                  type:
                    - string
                    - 'null'
                  enum:
                    - reply
                    - new_thread
                    - null
                isHumanApprovalRequired:
                  description: >-
                    Set true only when the customer explicitly requests review
                    before sending.
                  type:
                    - boolean
                    - 'null'
                recipientEmail:
                  description: >-
                    Recipient email when contact or enrollment data does not
                    already contain it.
                  type:
                    - string
                    - 'null'
                delay:
                  description: >-
                    Delay before this action runs after its selected append
                    target becomes active.


                    - Omit or use 00:00:00 for no delay/immediate execution.

                    - Use a TimeSpan string in d.hh:mm:ss or hh:mm:ss format,
                    for example 03:00:00 for 3 hours or 5.00:00:00 for 5 days.

                    - Natural-language values such as &#39;5 days&#39; are not
                    accepted.

                    - After the first LinkedIn chat step on the same branch,
                    every linkedin_inmail or linkedin_message action must keep
                    at least 03:00:00 of total delay since the previous LinkedIn
                    chat step, including intermediate blocking delays and its
                    own action delay.
                  type:
                    - string
                    - 'null'
                appendTarget:
                  description: >-
                    Append branch. Use default unless targeting an existing
                    LinkedIn connection's accepted or timeout branch.
                  type: string
                  enum:
                    - default
                    - connection_accepted
                    - connection_timeout
                assignedUserId:
                  description: FirstTouch user ID assigned to execute this action.
                  type:
                    - string
                    - 'null'
              required:
                - prompt
                - assignedUserId
            - properties:
                type:
                  const: linkedin_connect
                message:
                  description: Optional final LinkedIn connection note.
                  type:
                    - string
                    - 'null'
                connectionTimeout:
                  description: >-
                    How long to wait for the connection request to be accepted
                    before activating the connection timeout branch.


                    - Omit to use the default of 14 days.

                    - Use a positive TimeSpan string in d.hh:mm:ss or hh:mm:ss
                    format, for example 7.00:00:00 for 7 days.
                  type:
                    - string
                    - 'null'
                isHumanApprovalRequired:
                  description: >-
                    Set true only when the customer explicitly requests review
                    before sending.
                  type:
                    - boolean
                    - 'null'
                delay:
                  description: >-
                    Delay before this action runs after its selected append
                    target becomes active.


                    - Omit or use 00:00:00 for no delay/immediate execution.

                    - Use a TimeSpan string in d.hh:mm:ss or hh:mm:ss format,
                    for example 03:00:00 for 3 hours or 5.00:00:00 for 5 days.

                    - Natural-language values such as &#39;5 days&#39; are not
                    accepted.

                    - After the first LinkedIn chat step on the same branch,
                    every linkedin_inmail or linkedin_message action must keep
                    at least 03:00:00 of total delay since the previous LinkedIn
                    chat step, including intermediate blocking delays and its
                    own action delay.
                  type:
                    - string
                    - 'null'
                appendTarget:
                  description: >-
                    Append branch. Use default unless targeting an existing
                    LinkedIn connection's accepted or timeout branch.
                  type: string
                  enum:
                    - default
                    - connection_accepted
                    - connection_timeout
                assignedUserId:
                  description: FirstTouch user ID assigned to execute this action.
                  type:
                    - string
                    - 'null'
              required:
                - assignedUserId
            - properties:
                type:
                  const: linkedin_message
                message:
                  description: >-
                    Final LinkedIn message. MCP Dynamic Actions do not generate
                    message content.
                  type:
                    - string
                    - 'null'
                isHumanApprovalRequired:
                  description: >-
                    Set true only when the customer explicitly requests review
                    before sending.
                  type:
                    - boolean
                    - 'null'
                delay:
                  description: >-
                    Delay before this action runs after its selected append
                    target becomes active.


                    - Omit or use 00:00:00 for no delay/immediate execution.

                    - Use a TimeSpan string in d.hh:mm:ss or hh:mm:ss format,
                    for example 03:00:00 for 3 hours or 5.00:00:00 for 5 days.

                    - Natural-language values such as &#39;5 days&#39; are not
                    accepted.

                    - After the first LinkedIn chat step on the same branch,
                    every linkedin_inmail or linkedin_message action must keep
                    at least 03:00:00 of total delay since the previous LinkedIn
                    chat step, including intermediate blocking delays and its
                    own action delay.
                  type:
                    - string
                    - 'null'
                appendTarget:
                  description: >-
                    Append branch. Use default unless targeting an existing
                    LinkedIn connection's accepted or timeout branch.
                  type: string
                  enum:
                    - default
                    - connection_accepted
                    - connection_timeout
                assignedUserId:
                  description: FirstTouch user ID assigned to execute this action.
                  type:
                    - string
                    - 'null'
              required:
                - message
                - assignedUserId
            - properties:
                type:
                  const: linkedin_inmail
                prompt:
                  description: Final LinkedIn InMail body, limited to 1900 characters.
                  type:
                    - string
                    - 'null'
                subject:
                  description: Final LinkedIn InMail subject, limited to 200 characters.
                  type:
                    - string
                    - 'null'
                isHumanApprovalRequired:
                  description: >-
                    Set true only when the customer explicitly requests review
                    before sending.
                  type:
                    - boolean
                    - 'null'
                delay:
                  description: >-
                    Delay before this action runs after its selected append
                    target becomes active.


                    - Omit or use 00:00:00 for no delay/immediate execution.

                    - Use a TimeSpan string in d.hh:mm:ss or hh:mm:ss format,
                    for example 03:00:00 for 3 hours or 5.00:00:00 for 5 days.

                    - Natural-language values such as &#39;5 days&#39; are not
                    accepted.

                    - After the first LinkedIn chat step on the same branch,
                    every linkedin_inmail or linkedin_message action must keep
                    at least 03:00:00 of total delay since the previous LinkedIn
                    chat step, including intermediate blocking delays and its
                    own action delay.
                  type:
                    - string
                    - 'null'
                appendTarget:
                  description: >-
                    Append branch. Use default unless targeting an existing
                    LinkedIn connection's accepted or timeout branch.
                  type: string
                  enum:
                    - default
                    - connection_accepted
                    - connection_timeout
                assignedUserId:
                  description: FirstTouch user ID assigned to execute this action.
                  type:
                    - string
                    - 'null'
              required:
                - prompt
                - subject
                - assignedUserId
            - properties:
                type:
                  const: linkedin_profile_view
                delay:
                  description: >-
                    Delay before this action runs after its selected append
                    target becomes active.


                    - Omit or use 00:00:00 for no delay/immediate execution.

                    - Use a TimeSpan string in d.hh:mm:ss or hh:mm:ss format,
                    for example 03:00:00 for 3 hours or 5.00:00:00 for 5 days.

                    - Natural-language values such as &#39;5 days&#39; are not
                    accepted.

                    - After the first LinkedIn chat step on the same branch,
                    every linkedin_inmail or linkedin_message action must keep
                    at least 03:00:00 of total delay since the previous LinkedIn
                    chat step, including intermediate blocking delays and its
                    own action delay.
                  type:
                    - string
                    - 'null'
                appendTarget:
                  description: >-
                    Append branch. Use default unless targeting an existing
                    LinkedIn connection's accepted or timeout branch.
                  type: string
                  enum:
                    - default
                    - connection_accepted
                    - connection_timeout
                assignedUserId:
                  description: FirstTouch user ID assigned to execute this action.
                  type:
                    - string
                    - 'null'
              required:
                - assignedUserId
            - properties:
                type:
                  const: manual_task
                name:
                  description: Manual task display name.
                  type:
                    - string
                    - 'null'
                message:
                  description: >-
                    Optional final task instructions. When omitted, the task
                    name is used as its content.
                  type:
                    - string
                    - 'null'
                isBlockingTask:
                  description: Whether this task blocks later actions until completed.
                  type:
                    - boolean
                    - 'null'
                delay:
                  description: >-
                    Delay before this action runs after its selected append
                    target becomes active.


                    - Omit or use 00:00:00 for no delay/immediate execution.

                    - Use a TimeSpan string in d.hh:mm:ss or hh:mm:ss format,
                    for example 03:00:00 for 3 hours or 5.00:00:00 for 5 days.

                    - Natural-language values such as &#39;5 days&#39; are not
                    accepted.

                    - After the first LinkedIn chat step on the same branch,
                    every linkedin_inmail or linkedin_message action must keep
                    at least 03:00:00 of total delay since the previous LinkedIn
                    chat step, including intermediate blocking delays and its
                    own action delay.
                  type:
                    - string
                    - 'null'
                appendTarget:
                  description: >-
                    Append branch. Use default unless targeting an existing
                    LinkedIn connection's accepted or timeout branch.
                  type: string
                  enum:
                    - default
                    - connection_accepted
                    - connection_timeout
                assignedUserId:
                  description: FirstTouch user ID assigned to execute this action.
                  type:
                    - string
                    - 'null'
              required:
                - name
                - assignedUserId
            - properties:
                type:
                  const: call_task
                message:
                  description: >-
                    Final call script or instructions. MCP Dynamic Actions do
                    not generate call content.
                  type:
                    - string
                    - 'null'
                isHumanApprovalRequired:
                  description: >-
                    Set true only when the customer explicitly requests review
                    before completing the call task.
                  type:
                    - boolean
                    - 'null'
                delay:
                  description: >-
                    Delay before this action runs after its selected append
                    target becomes active.


                    - Omit or use 00:00:00 for no delay/immediate execution.

                    - Use a TimeSpan string in d.hh:mm:ss or hh:mm:ss format,
                    for example 03:00:00 for 3 hours or 5.00:00:00 for 5 days.

                    - Natural-language values such as &#39;5 days&#39; are not
                    accepted.

                    - After the first LinkedIn chat step on the same branch,
                    every linkedin_inmail or linkedin_message action must keep
                    at least 03:00:00 of total delay since the previous LinkedIn
                    chat step, including intermediate blocking delays and its
                    own action delay.
                  type:
                    - string
                    - 'null'
                appendTarget:
                  description: >-
                    Append branch. Use default unless targeting an existing
                    LinkedIn connection's accepted or timeout branch.
                  type: string
                  enum:
                    - default
                    - connection_accepted
                    - connection_timeout
                assignedUserId:
                  description: FirstTouch user ID assigned to execute this action.
                  type:
                    - string
                    - 'null'
              required:
                - message
                - assignedUserId
        contact:
          description: >-
            Optional verified contact context, normally forwarded from
            find_contact_data or a customer-requested enrichment result in this
            conversation.


            - All fields are optional.

            - On an existing enrollment, prospectId, email, linkedInUrl, and
            phone may only fill blanks and reject conflicts; firstName,
            lastName, role, and location only fill missing properties.

            - Do not use this tool to enrich missing data.
          type:
            - object
            - 'null'
          properties:
            prospectId:
              description: >-
                Optional persisted FirstTouch prospect id returned by a lookup
                or enrichment tool.
              type:
                - string
                - 'null'
              default: null
            firstName:
              description: Optional verified prospect first name.
              type:
                - string
                - 'null'
              default: null
            lastName:
              description: Optional verified prospect last name.
              type:
                - string
                - 'null'
              default: null
            email:
              description: Optional verified prospect work email.
              type:
                - string
                - 'null'
              default: null
            linkedInUrl:
              description: Optional verified prospect LinkedIn profile URL.
              type:
                - string
                - 'null'
              default: null
            phone:
              description: Optional verified prospect phone number.
              type:
                - string
                - 'null'
              default: null
            role:
              description: Optional verified prospect role or title.
              type:
                - string
                - 'null'
              default: null
            location:
              description: Optional verified prospect location.
              type:
                - string
                - 'null'
              default: null
          default: null
        company:
          description: >-
            Optional verified company context related to contact.


            - All fields are optional.

            - It is stored as enrollment context only and does not prove that
            the contact works for this company.

            - On an existing enrollment, every company field only fills a
            missing property and never overwrites an existing value.
          type:
            - object
            - 'null'
          properties:
            name:
              description: Optional verified company name.
              type:
                - string
                - 'null'
              default: null
            domain:
              description: Optional verified company domain, for example winrate.com.
              type:
                - string
                - 'null'
              default: null
            linkedInUrl:
              description: Optional verified LinkedIn company profile URL.
              type:
                - string
                - 'null'
              default: null
            linkedInId:
              description: Optional verified numeric LinkedIn company id.
              type:
                - integer
                - 'null'
              default: null
            industry:
              description: Optional verified company industry.
              type:
                - string
                - 'null'
              default: null
            size:
              description: Optional verified company size, for example 51-200.
              type:
                - string
                - 'null'
              default: null
            location:
              description: Optional verified company location.
              type:
                - string
                - 'null'
              default: null
            website:
              description: Optional verified company website URL.
              type:
                - string
                - 'null'
              default: null
          default: null
        enrollmentId:
          description: >-
            Optional existing MCP Dynamic Actions enrollment/activity id to
            extend.


            - Use the exact enrollmentId returned by find_mcp_enrollment for the
            customer-selected candidate.

            - If the selected enrollment lacks firstName or lastName, also pass
            both names in contact before appending an action.

            - If find_mcp_enrollment returned any candidates, do not choose this
            value or omit it until the customer explicitly decides whether to
            continue one of those enrollments or start a new sequence.

            - Omit when no MCP enrollment candidate was found to create a new
            enrollment; when the original request already specifies the action
            and all required identity data, do this without asking the customer
            to confirm the same action again.
          type:
            - string
            - 'null'
          default: null
        ownerId:
          description: >-
            Optional default owner user id for the dynamic enrollment.


            - Use the exact current userId from get_current_user or a userId
            returned by list_team_members.

            - Omit to keep the existing owner when extending an enrollment, or
            use the current MCP user for a new enrollment.
          type:
            - string
            - 'null'
          default: null
        priority:
          description: >-
            Optional scheduling priority for the whole dynamic enrollment.


            - Use 1 for High, 0 or omit for normal, and -1 for Low.

            - Higher values are preferred first.

            - Omit for priority 0 on a new enrollment or to preserve priority
            when extending an existing enrollment.

            - When supplied with enrollmentId, this updates the selected
            enrollment priority.
          type:
            - integer
            - 'null'
          default: null
        sourceDescription:
          description: >-
            Optional UI context for the dynamic enrollment, limited to 500
            characters.


            - When useful context is known, write one to three concise sentences
            describing how this contact came to the sender and their relevant
            relationship; do not invent facts or merely repeat the action.

            - Omit when no useful context is known, which preserves the existing
            description when extending an enrollment.

            - Supplying a value for an existing enrollment replaces its prior
            sourceDescription.
          type:
            - string
            - 'null'
          default: null
        allowUnreadyLinkedInAccount:
          description: >-
            Allow creating a LinkedIn action, or appending a follow-up to a
            LinkedIn connection outcome branch, even when the assigned team
            member's LinkedIn account is missing, disconnected, not alive,
            relations sync is incomplete, or the existing connection action is
            failed/canceled due account readiness.


            - Use only after the customer explicitly asks to create the action
            despite LinkedIn account readiness problems.

            - Social actions permission and contact.linkedInUrl are still
            required for LinkedIn actions.

            - For InMail, an already connected account must still have an
            eligible Premium or Sales Navigator plan; this flag only permits
            authoring before account readiness is available.
          type:
            - boolean
            - 'null'
          default: null
      required:
        - action
    add_dynamic_action_output: {}
    PublicApiError:
      type: object
      required:
        - error
        - message
        - traceId
      properties:
        error:
          type: string
        message:
          type: string
        traceId:
          type: string
  securitySchemes:
    X-API-Key:
      type: apiKey
      in: header
      name: X-API-Key

````