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

> ## Agent Instructions
> Use the public API base URL: https://api.teamfollowup.ai/api.
> Authenticate public API requests with Authorization: Bearer YOUR_API_KEY.
> Use product-owned terms: agents, campaigns, projects (GoHighLevel sub-accounts), contacts, calls, outcomes, skills, cadences, phone numbers.
> Scope requests by locationId rather than projectName.
> Read the guide linked from each API reference group before recommending an endpoint.

# List TFU Live Brain templates

> TFU Live only. The Brain templates: ready-made agents, niche agnostic, to create an agent from (Create agent with brainTemplateId). Each has its workflows (composed of the workflow templates; every one holds Schedule a callback and Stop contact), the tools it equips (texting off), a short starting prompt that speaks with the Layer 1 variables and keeps placeholders only for business facts, the campaign direction it suits, logic (its business logic in a few values) and toFill: the settings the client fills, optional at create, each with its JSON Schema and the settings it fills. See the workflows contract guide.

Required scope: `agents:read`.

Required API key scope: `agents:read`.



## OpenAPI

````yaml /openapi.yaml get /api/tfu-live-agents/brain-templates
openapi: 3.1.0
info:
  title: TFUAI Server API
  version: 1.0.0
  description: >-
    API reference for the TFUAI SaaS server.


    All published endpoints are mounted under `/api`. Responses use a standard
    envelope: `{ "success": true, ... }` on success and `{ "success": false,
    "error": "..." }` on failure.


    Product API modules are being launched module by module. This spec currently
    exposes only contracted public modules.


    Authenticate public API requests with an API key in the `Authorization`
    header: `Authorization: Bearer YOUR_API_KEY`.
servers:
  - url: https://api.teamfollowup.ai
    description: Production API origin. Public API paths are under /api.
security: []
tags:
  - name: Agents
    description: >-
      Build the conversation: identity and settings, script, lead context and
      split testing.
  - name: Analytics
    description: >-
      Understand call volume, pickup, booking and transfer metrics within the
      selected reporting scope.
  - name: Billing
    description: >-
      Balances, spend, purchases and sub-account rebilling. Reference and guides
      only; the builder chatbot has no billing playbook.
  - name: Calls
    description: >-
      Review completed calls, recordings, transcripts and campaign run history;
      distinguish observation from placing a new call.
  - name: Campaigns
    description: >-
      Configure what starts calls, who is eligible, calling windows, caller IDs,
      activation and the actions that follow each outcome.


      What runs after a call lands: for each outcome (booked, opted out, asked
      for a callback…), an ordered chain of actions — tag the contact, move a
      pipeline stage, send an SMS, book an appointment. Stored as a graph:
      `nodes` are the actions, `edges` say what follows what, and
      `dispositionEntries` maps each outcome to the node its chain starts at.


      **Pick the narrowest endpoint that does the job.**


      | To | Call | |

      | --- | --- | --- |

      | See what fires per outcome | `GET .../workflow?view=summary` | Reads as
      plain text, no graph walking |

      | Add steps to an outcome | `POST .../outcomes/{outcome}/nodes` | Server
      derives node ids, edge ids, handles, layout |

      | Change a message, tag or setting | `PATCH .../workflow` | Merges;
      carries no graph, so it cannot damage one |

      | Remove one step | `DELETE .../nodes/{nodeId}` | Also re-links the chain
      around it |

      | Author or replace the whole graph | `PUT .../workflow` | Replaces
      everything you send |


      `PUT` is the only one that can re-wire, position nodes, build an `if`,
      save an unconfigured draft, or copy a whole workflow — and the only one
      that can overwrite a change someone else made after you read it. Use it
      when you are genuinely authoring the graph, and send `expectedVersion`
      when you do. For everything else the narrower endpoints are both easier
      and safer.
  - name: Contacts
    description: >-
      Find contacts and their calls, manage do-not-call status and identify
      internal contacts excluded from reporting.
  - name: In-call Capabilities
    description: >-
      Configure actions and instructions the agent uses during a live call:
      booking, transfers, lookups and custom skills.
  - name: Master agent
    description: >-
      Run a shared agent and campaign across linked projects; manage
      inheritance, local bindings, synchronization and rollout readiness.
  - name: Native Calendar
    description: >-
      The diary of a sub-account with no CRM: its bookable calendars, the free
      slots they offer, and the appointments on them. Availability is computed
      per request against live bookings and is never cached, because a cached
      slot is one somebody else has already taken.
  - name: Native Contacts
    description: >-
      The people a sub-account with no CRM calls, and the fields it keeps on
      them. This is the system of record for those contacts: there is nowhere
      else they exist. A sub-account with a CRM keeps its contacts there and
      every operation here answers 400 for it.
  - name: Phone Numbers
    description: >-
      Find and manage caller IDs, assign numbers to campaigns and understand
      connected Twilio numbers.
  - name: Projects
    description: >-
      Understand project ownership, inspect configuration and validate the local
      resources used by a campaign.
  - name: TFU Live
    description: >-
      Build one TFU Live agent with its Brain, Voice and equipped actions;
      connect it through shared Campaigns.
  - name: Voices
    description: >-
      Browse the voice catalogue and select a voice; configure speech and
      listening behavior in Agents.
paths:
  /api/tfu-live-agents/brain-templates:
    get:
      tags:
        - TFU Live
      summary: List TFU Live Brain templates
      description: >-
        TFU Live only. The Brain templates: ready-made agents, niche agnostic,
        to create an agent from (Create agent with brainTemplateId). Each has
        its workflows (composed of the workflow templates; every one holds
        Schedule a callback and Stop contact), the tools it equips (texting
        off), a short starting prompt that speaks with the Layer 1 variables and
        keeps placeholders only for business facts, the campaign direction it
        suits, logic (its business logic in a few values) and toFill: the
        settings the client fills, optional at create, each with its JSON Schema
        and the settings it fills. See the workflows contract guide.


        Required scope: `agents:read`.


        Required API key scope: `agents:read`.
      operationId: get-tfu-live-agents-brain-templates
      parameters:
        - name: locationId
          in: query
          required: true
          schema:
            type: string
          description: >-
            Sub-account belonging to the authenticated agency and any narrower
            credential location binding.
      responses:
        '200':
          description: >-
            Successful TFU Live response. Setup acceptance is not verified
            readiness or campaign activation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveBrainTemplateListResponse'
              example:
                success: true
                data:
                  brainTemplates:
                    - id: booking_one_calendar
                      name: Appointment booking, one calendar
                      direction: either
                      typicalFor:
                        - outbound
                      description: >-
                        For a business that books appointments on one calendar,
                        on inbound or outbound calls. The AI speaks for the
                        business, finds out what the lead needs, offers open
                        times from that one calendar and books the time the lead
                        picks; a lead who already has an appointment can move it
                        or cancel it there. There is no live transfer: a lead
                        who wants a person later or is busy now is offered an AI
                        callback. A lead who asks not to be contacted is put on
                        do not disturb. Texting is off.
                      logic:
                        booking: single
                        cancel: true
                        transfer: none
                        direction: either
                        texting: false
                      tools:
                        - respond_to_voice
                        - end_call
                        - resume_call_after_drop
                        - search_call_history
                      workflows:
                        book:
                          name: Book appointment
                          description: >-
                            Use when the caller wants to book an appointment, or
                            to move one they already have.
                          steps:
                            - id: slots
                              type: find_slots
                              config:
                                calendarId:
                                  $fill: calendar
                            - id: book
                              type: book_appointment
                              config:
                                mode: book_or_move
                              outputs:
                                booked: []
                                rescheduled: []
                        cancel:
                          name: Cancel appointment
                          description: >-
                            Use when the caller wants to cancel an appointment
                            they have.
                          steps:
                            - id: cancel
                              type: cancel_appointment
                              config:
                                calendarIds:
                                  $fill: calendar
                                  as: list
                              outputs:
                                cancelled: []
                        callback:
                          name: Schedule a callback
                          description: >-
                            Use when the lead wants the AI to call them back
                            later, including a busy lead who agrees to talk at
                            another time. This is not a business appointment.
                          steps:
                            - id: time
                              type: collect_information
                              label: When to call back
                              config:
                                items:
                                  - id: callback_time
                                    label: When to call back
                                    question: >-
                                      When would be a good time for us to call
                                      you back?
                                    type: text
                            - id: schedule
                              type: schedule_ai_call
                              config:
                                timeFrom: callback_time
                        stop:
                          name: Stop contact
                          description: >-
                            Use when the lead asks not to be contacted again, is
                            clearly not interested, or the conversation is spam
                            or a bot. This ends every call and message to them.
                          steps:
                            - id: reason
                              type: collect_information
                              label: Why they are leaving
                              config:
                                items:
                                  - id: reason
                                    label: >-
                                      Why the lead is leaving the journey, in
                                      their own words where they gave them (an
                                      opt-out, no interest, spam or a bot)
                                    type: text
                                    required: false
                            - id: dnd
                              type: dnd
                              config:
                                reason: '{{collected.reason}}'
                      prompt: >-
                        # Identity


                        ## Who you are

                        You're {{agent_name}}, speaking for {{business_name}}.
                        You help people get the appointment they need booked in.


                        ## How you carry yourself

                        You believe the quickest way to help someone is to get
                        them in front of the team, so you make booking easy and
                        never pushy. You'd rather hear a clear no than book
                        someone who won't turn up. You say plainly when
                        something is for the team to answer.


                        ## This call

                        Lead: {{full_name}}

                        Phone: {{phone}}

                        Email: {{email}}

                        Direction: {{direction}}

                        Now: {{current_time}}, timezone {{timezone}}


                        ## Don't

                        - Don't keep pushing for a booking after a clear no.


                        # Steps to follow


                        ## 1. Hook

                        Outbound: Hey, is this {{first_name}}?

                        Inbound: Hey, thanks for calling {{business_name}}, this
                        is {{agent_name}}. How can I help?

                        Goal: they confirm who they are, or say why they called.


                        ## 2. Discovery

                        Line: This is {{agent_name}} with {{business_name}}.
                        What can we help you with?

                        Goal: they say what they need.


                        ## 3. Value proposition

                        Line: Let's get you booked in so the team can take care
                        of it. What day usually works best for you?

                        Goal: they choose a time and it's booked.


                        ## 4. Downsell (in order; each only when the one before
                        didn't happen)

                        1. They're not ready to book: offer a callback.
                           Line: No problem. When would be a better time for us to give you a call?
                           Goal: they agree a time, or say no.

                        ## 5. Wrap up

                        Line: Perfect, you're all set, and you'll get a
                        confirmation with the details. Anything else I can help
                        with?

                        Goal: nothing is left to handle. Then close the
                        conversation.


                        # Conversational FAQ


                        **Can I move or cancel my appointment?**

                        Of course. Tell me which appointment, and I'll sort it
                        out for you.


                        **I'm not interested.**

                        No problem at all. Is it the timing, or just not
                        something you need right now?


                        **Now's not a good time.**

                        No worries. When's a better time for a quick call?


                        **Can you just send me some info?**

                        Happy to help with that. Honestly, a quick chat with the
                        team is the fastest way to get answers that fit you.
                        Want me to set that up?
                      toFill:
                        - id: calendar
                          label: The calendar appointments are booked on
                          kind: calendar
                          value:
                            type: string
                            pattern: ^[a-zA-Z0-9_-]{1,200}$
                            description: >-
                              A calendar id from the sub-account’s calendars
                              lookup.
                          settings:
                            - workflow: book
                              step: slots
                              setting: calendarId
                            - workflow: cancel
                              step: cancel
                              setting: calendarIds
                      placeholders: []
        '400':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: locationId is required.
                code: invalid_request
        '401':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: Unauthorized
                message: Access token is required. Please login
        '403':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: InsufficientScope
                message: This API key does not have the required scope.
                requiredScope: agents:write
        '404':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: Agent not found.
                code: not_found
        '409':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: The agent changed. Read the current version before saving.
                code: conflict
        '422':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              examples:
                invalid_workflow:
                  value:
                    success: false
                    error: Choose the tag this node checks.
                    code: invalid_workflow
                    workflowId: wf_account1
                    stepId: check
                workflow_resource_not_found:
                  value:
                    success: false
                    error: Choose an active calendar verified for this sub-account.
                    code: workflow_resource_not_found
                    workflowId: wf_book0001
                    stepId: slots
                    field: routing[1].calendarId
                workflow_secret_refused:
                  value:
                    success: false
                    error: >-
                      The saved value of the Authorization header was saved for
                      https://api.example.com; this webhook now sends to
                      https://collector.example.net, so enter the value again.
                    code: workflow_secret_refused
                    workflowId: wf_account1
                    stepId: lookup
                    field: headers.Authorization
                invalid_agent:
                  value:
                    success: false
                    error: >-
                      Choose an agent id using up to 100 letters, digits,
                      underscores or hyphens.
                    code: invalid_agent
                setup_incomplete:
                  value:
                    success: false
                    error: >-
                      Fill what this agent still needs before it is set up: Book
                      appointment: Choose the calendar to search.
                    code: setup_incomplete
                    workflowId: wf_book0001
                    stepId: slots
                    field: calendarId
                    setupItems:
                      - kind: workflow_setting
                        workflowId: wf_book0001
                        workflowName: Book appointment
                        stepId: slots
                        node: find_slots
                        field: calendarId
                        message: Choose the calendar to search.
        '429':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: TooManyRequests
                message: Too many write requests, please slow down.
        '502':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: TFU Live request failed.
                code: provider_unavailable
        '503':
          description: >-
            TFU Live request rejected: { success: false, error, code,
            workflowId?, stepId?, field?, setupItems? }. Read the error and
            current agent before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TfuLiveError'
              example:
                success: false
                error: TFU_LIVE_CAMPAIGN_PENDING
                code: TFU_LIVE_CAMPAIGN_PENDING
                message: >-
                  The agent draft was saved. Retry creation with the same agent
                  id and original body to finish attaching its campaign.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: bash
          label: cURL
          source: |-
            curl --request GET \
              --url https://api.teamfollowup.ai/api/tfu-live-agents/brain-templates \
              --header 'Authorization: Bearer YOUR_API_KEY'
components:
  schemas:
    TfuLiveBrainTemplateListResponse:
      type: object
      required:
        - success
        - data
      properties:
        success:
          const: true
        data:
          type: object
          required:
            - brainTemplates
          additionalProperties: false
          properties:
            brainTemplates:
              type: array
              items:
                $ref: '#/components/schemas/TfuLiveBrainTemplate'
      additionalProperties: false
    TfuLiveError:
      type: object
      required:
        - success
        - error
      properties:
        success:
          const: false
        error:
          type: string
          description: >-
            What to do about it, in words. A status-wide gate (authentication,
            scope, rate limit) may use its own error name with a message.
        code:
          type: string
          enum:
            - invalid_workflow
            - setup_incomplete
            - workflow_resource_not_found
            - workflow_resource_unavailable
            - workflow_secret_refused
            - invalid_agent
            - invalid_request
            - unauthorized
            - insufficient_balance
            - forbidden
            - not_found
            - conflict
            - too_large
            - provider_unavailable
            - internal_error
            - AGENT_OPERATION_UNSUPPORTED
            - TFU_LIVE_CAMPAIGN_PENDING
          description: >-
            The kind of refusal: invalid_workflow (a workflow’s structure or a
            node’s settings), setup_incomplete (a setting still to fill or a
            Brain template placeholder still in the prompt, where the agent must
            be complete: preparing it, or a save that sets it up; setupItems
            lists every one), workflow_resource_not_found (a calendar, custom
            field, pipeline stage, team or rep the sub-account lacks, or an
            inactive calendar), workflow_resource_unavailable (503: the
            sub-account’s resources could not be read; retry),
            workflow_secret_refused (a secret header rule), invalid_agent (any
            other part of the agent), else by status. TFU_LIVE_* names a product
            state.
        workflowId:
          type: string
          description: >-
            The workflow a workflow refusal is about. Absent on a workflow being
            created, which has no id yet.
        stepId:
          type: string
          description: The step inside it.
        field:
          type: string
          description: >-
            The setting inside the step: calendarId, routing[1].calendarId,
            items[0].field, destination.teamId, headers.Authorization;
            brain.prompt for a placeholder. On a create from a Brain template,
            the request value: values.<to-fill id>, values or brainTemplateId.
        setupItems:
          type: array
          items:
            type: object
            required:
              - kind
              - message
            additionalProperties: false
            description: >-
              Something the agent still needs before it can be prepared for real
              calls.
            properties:
              kind:
                type: string
                enum:
                  - workflow_setting
                  - prompt_placeholder
                description: >-
                  workflow_setting: a setting still to fill (a calendar, a tag,
                  who takes a transfer, zip codes, a choice’s answers, an item’s
                  label); prompt_placeholder: a Brain template [bracketed]
                  placeholder still in the prompt (legacy: templates no longer
                  hold any).
              workflowId:
                type: string
              workflowName:
                type: string
              stepId:
                type: string
              node:
                type: string
                description: The node type.
              field:
                type: string
                description: >-
                  The setting inside the step (calendarId, destination,
                  items[0].choices), or brain.prompt.
              placeholder:
                type: string
              message:
                type: string
                description: What to do, in words.
          description: >-
            On setup_incomplete: everything the agent still needs, the first of
            which the refusal names.
      additionalProperties: {}
    TfuLiveBrainTemplate:
      type: object
      required:
        - id
        - name
        - description
        - direction
        - logic
        - tools
        - workflows
        - prompt
        - placeholders
        - toFill
      additionalProperties: false
      description: >-
        A ready-made agent, niche agnostic: business logic materialised as a
        configuration of workflows, composed of the workflow templates. Create
        an agent from it with Create agent { id, brainTemplateId, values? }.
      properties:
        id:
          type: string
          description: The brainTemplateId to create from.
        name:
          type: string
          description: Also the new agent’s name when the create names none.
        description:
          type: string
          description: >-
            The business logic it materialises, in words: who it is for, what
            the call does, its fallback, and that texting is off.
        direction:
          type: string
          enum:
            - outbound
            - inbound
            - either
          description: The campaigns it suits.
        logic:
          type: object
          required:
            - booking
            - cancel
            - transfer
            - direction
            - texting
          additionalProperties: false
          description: >-
            The business logic in a few values, for matching an agent’s logic to
            a template.
          properties:
            booking:
              type: string
              enum:
                - none
                - single
                - routed
              description: >-
                none: no booking; single: one calendar; routed: one question’s
                answer picks the calendar, no default calendar.
            cancel:
              type: boolean
              description: Whether a lead can cancel an appointment on the call.
            transfer:
              type: string
              enum:
                - none
                - primary
                - first_with_booking_fallback
              description: >-
                none: no live transfer; primary: a transfer is a main path
                whenever the caller wants a person, side by side with booking;
                first_with_booking_fallback: an interested lead is transferred,
                and booking is offered only when the transfer ends Nobody
                available or Not connected.
            direction:
              type: string
              enum:
                - inbound
                - outbound
                - either
            texting:
              type: boolean
              description: >-
                Whether it texts. False in every template: send_message is not
                equipped.
        tools:
          type: array
          items:
            type: string
          description: The tools that stay tools it equips (runtime ids).
        workflows:
          type: object
          additionalProperties:
            type: object
            required:
              - name
              - description
              - steps
            properties:
              name:
                type: string
              description:
                type: string
              steps:
                type: array
                items:
                  type: object
          description: >-
            Its workflows by a key local to the template. In a step’s config, {
            $fill: id, as? } stands for a setting filled from values.<id>, and {
            $workflow: key } for the id another of its workflows gets in the
            agent. Every workflow id is derived from the agent id.
        prompt:
          type: string
          description: >-
            The starting Brain in the shared format: # Identity (who the agent
            is, how it carries itself, the call's details, a few don'ts), #
            Steps to follow (the Hook said word for word at call start, then
            each step's line and goal) and # Conversational FAQ. It speaks with
            {{agent_name}} (the agent's saved name) and the Layer 1 variables
            ({{first_name}}, {{full_name}}, {{business_name}}, {{direction}} and
            the rest). It states no business fact and holds no placeholder: the
            builder writes the business's own lines and FAQs.
        typicalFor:
          type: array
          items:
            type: string
            enum:
              - inbound
              - outbound
          description: >-
            The call direction whose usual agent this template is: when an
            agent's Brain leaves more than one template possible, the direction
            its calls go picks this one.
        placeholders:
          type: array
          items:
            type: string
          description: >-
            Always empty: a template states no business fact, so its prompt
            holds no [bracketed] placeholder. Kept for compatibility.
        toFill:
          type: array
          description: >-
            The settings the client fills for their business. Optional at
            create: a value given is checked and fills its settings; one not
            given leaves them empty as setup items, and the agent is prepared
            only once every one is filled. Every other setting is valid as
            published.
          items:
            type: object
            required:
              - id
              - label
              - kind
              - value
              - settings
            additionalProperties: false
            properties:
              id:
                type: string
                description: The key in values.
              label:
                type: string
              kind:
                type: string
                enum:
                  - calendar
                  - transfer_destination
                  - text
                  - answer_calendars
                description: >-
                  calendar: a calendar id (lookup kind calendars);
                  transfer_destination: one Transfer destination (a team or rep
                  must be the sub-account’s, lookups teams and reps); text: 1 to
                  150 characters; answer_calendars: 2 to 30 { answer, calendarId
                  } with distinct answers.
              value:
                type: object
                description: The value’s JSON Schema.
              settings:
                type: array
                description: Every setting the value fills.
                items:
                  type: object
                  required:
                    - workflow
                    - step
                    - setting
                  properties:
                    workflow:
                      type: string
                    step:
                      type: string
                    setting:
                      type: string
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: 'Send your API key as `Authorization: Bearer YOUR_API_KEY`.'

````