> ## 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.

# Cancel Flow Enrollments

> Cancel specific enrollment queue items in a flow, or all cancellable queue items when queueItemIds is omitted.



## OpenAPI

````yaml https://gateway.firsttouch.ai/api/public/openapi.json post /api/public/tools/cancel_flow_enrollments
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/cancel_flow_enrollments:
    post:
      tags:
        - FirstTouch tools
      summary: Cancel Flow Enrollments
      description: >-
        Cancel specific enrollment queue items in a flow, or all cancellable
        queue items when queueItemIds is omitted.
      operationId: cancel_flow_enrollments
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/cancel_flow_enrollments_input'
      responses:
        '200':
          description: Tool result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cancel_flow_enrollments_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:
    cancel_flow_enrollments_input:
      type: object
      properties:
        flowPlanId:
          description: >-
            Existing flow plan id. Use the exact flowPlanId returned by
            create_flow_plan, list_flow_plans, or get_flow_workspace.
          type:
            - string
            - 'null'
        queueItemIds:
          description: >-
            Enrollment queue item ids to cancel. Use exact queueItemId values
            from list_flow_plan_enrollments or get_flow_workspace required
            actions; omit to cancel all cancellable queue items in the flow.
          type:
            - array
            - 'null'
          items:
            type:
              - string
              - 'null'
          default: null
      required:
        - flowPlanId
    cancel_flow_enrollments_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

````