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

# Add Node

> Insert a new node into a draft campaign's sequence. Also the home page for moving and deleting nodes on the same collection.

**CLI:**

```bash theme={null}
puffle campaign sequence node add --id <id> --type <type>
puffle campaign sequence node add --id <id> --type <type> --position <position> --subject <subject> --body <body> --signature <signature> --include-message <include-message> --is-reply <is-reply> --delay-days <delay-days> --delay-hours <delay-hours> --delay-minutes <delay-minutes>
```

## Overview

Inserts a new node into the campaign sequence. **Draft campaigns only** — every mutation on this collection is gated on `status === "draft"`.

This collection exposes three verbs:

| Verb     | Operation            | Purpose                                                                                               |
| -------- | -------------------- | ----------------------------------------------------------------------------------------------------- |
| `POST`   | `addSequenceNode`    | Insert a new node (this page). Omit `position` to drop it right before the terminal `end` node.       |
| `PATCH`  | `moveSequenceNode`   | Reorder an existing node — see [Move a sequence node](/api-reference/campaigns/update-sequence-node). |
| `DELETE` | `deleteSequenceNode` | Remove a node — see [Delete a sequence node](/api-reference/campaigns/delete-sequence-node).          |

To edit a node's content (subject, body, delay values, AI purpose), use [`updateSequenceNode`](/api-reference/campaigns/update-sequence-node) against the singular `/sequence/nodes/{nodeId}` route. Type is immutable after creation — to change it, delete and re-add.

Every mutation on this collection is backed by an atomic Postgres RPC with row-level locking, so concurrent adds, moves, and deletes can't corrupt the `position` ordering.

## AI agent notes

<Note>
  **Typical build order.**

  1. `POST /api/campaigns` to create a draft.
  2. Loop over your desired nodes and `POST /api/campaigns/{id}/sequence/nodes` for each — omit `position` and every node lands just before the auto-inserted terminal `end`.
  3. When done, `POST /api/campaigns/{id}/launch`.

  **Channel validation.** The parent campaign's `type` determines which node kinds are legal:

  * `linkedin` campaigns accept `connection_request`, `message`, `delay`, `ai`, `end`.
  * `email` campaigns accept `email`, `delay`, `ai`, `end`.

  **Read-back fallback.** The response is normally `{ sequence_nodes: [...] }` — the full list, already ordered. On the rare occasion the post-mutation read-back fails, the server returns `{ mutated: true, node_id }`. In that case refetch via `GET /api/campaigns/{id}`.

  **Position omitted = before the end.** Don't set `position` unless you specifically need to insert somewhere other than the natural end-of-sequence slot. The server handles ordering.

  **AI nodes.** Adding `{ type: "ai" }` creates the base row; populate `purpose` and `output_type` with a follow-up `PUT /api/campaigns/{id}/sequence/nodes/{nodeId}` call.
</Note>


## OpenAPI

````yaml post /api/campaigns/{id}/sequence/nodes
openapi: 3.0.3
info:
  title: Puffle API
  version: 1.0.0
  description: >-
    HTTP API for the Puffle GTM platform - Feed and Lead Finder search
    preparation, campaign-backed Outbound execution, Puffle Agent runs, sender
    management, and Unibox reply workflows. Designed for operation by both
    humans and autonomous AI agents. Agents should start at the [Agent
    Playbook](/guides/agent-playbook) which prescribes a workspace-context check
    (`GET /api/context`) and core user journeys with exact call ordering.
  contact:
    name: Puffle Support
    url: https://puffle.ai
servers:
  - url: https://app.puffle.ai
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Campaigns
    description: >-
      Campaign-backed Outbound execution. These endpoints manage draft,
      launching, active, paused, and completed Outbound runs with sequence
      nodes, contacts, and sender accounts.
  - name: Accounts
    description: Signed-in user account, settings, and workspace context endpoints.
  - name: Billing
    description: Billing customer portal and account billing endpoints.
  - name: Senders
    description: >-
      Connected sender accounts, email inboxes, sending domains, DNS
      verification, warmup, and sender capacity.
  - name: Socials
    description: >-
      Read connected LinkedIn and X accounts, review current and archived posts,
      and reconcile publication status. Creating, editing, scheduling,
      publishing, OAuth connection, analytics, and mentions remain
      dashboard-managed workflows and are not part of the public Bearer-token
      API.
paths:
  /api/campaigns/{id}/sequence/nodes:
    post:
      tags:
        - Campaigns
      summary: Add Node
      description: >-
        Insert a new node into the campaign sequence. Draft campaigns only. If
        `position` is omitted, the node is placed immediately before the
        terminal `end` node.
      operationId: addSequenceNode
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            description: Campaign UUID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - connection_request
                    - message
                    - email
                    - delay
                    - ai
                    - end
                position:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  nullable: true
                subject:
                  type: string
                  nullable: true
                body:
                  type: string
                  nullable: true
                signature:
                  type: string
                  nullable: true
                include_message:
                  type: boolean
                  nullable: true
                is_reply:
                  type: boolean
                  nullable: true
                delay_days:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  nullable: true
                delay_hours:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  nullable: true
                delay_minutes:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  nullable: true
              required:
                - type
              additionalProperties: {}
      responses:
        '200':
          description: >-
            Node inserted. Returns the fresh ordered list, or a mutation
            fallback when read-back fails.
          content:
            application/json:
              schema:
                anyOf:
                  - type: object
                    properties:
                      sequence_nodes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              description: String value with endpoint-specific validation.
                            campaign_id:
                              type: string
                              description: String value with endpoint-specific validation.
                            position:
                              type: integer
                              minimum: 0
                              maximum: 9007199254740991
                            type:
                              type: string
                              enum:
                                - connection_request
                                - message
                                - email
                                - delay
                                - ai
                                - end
                            subject:
                              type: string
                              nullable: true
                            body:
                              type: string
                              nullable: true
                            body_html:
                              type: string
                              nullable: true
                            signature:
                              type: string
                              nullable: true
                            from_name:
                              type: string
                              nullable: true
                            reply_to:
                              type: string
                              nullable: true
                            cc:
                              type: string
                              nullable: true
                            bcc:
                              type: string
                              nullable: true
                            attachments:
                              type: array
                              items: {}
                              nullable: true
                            include_message:
                              type: boolean
                              nullable: true
                            is_reply:
                              type: boolean
                              nullable: true
                            delay_days:
                              type: integer
                              minimum: 0
                              maximum: 9007199254740991
                              nullable: true
                            delay_hours:
                              type: integer
                              minimum: 0
                              maximum: 9007199254740991
                              nullable: true
                            delay_minutes:
                              type: integer
                              minimum: 0
                              maximum: 9007199254740991
                              nullable: true
                            ai_node:
                              type: object
                              properties:
                                output_type:
                                  type: string
                                  enum:
                                    - email
                                    - message
                              required:
                                - output_type
                              additionalProperties: {}
                              nullable: true
                          required:
                            - id
                            - campaign_id
                            - position
                            - type
                          additionalProperties: false
                    required:
                      - sequence_nodes
                    additionalProperties: false
                  - type: object
                    properties:
                      mutated:
                        type: boolean
                        enum:
                          - true
                      node_id:
                        type: string
                        description: String value with endpoint-specific validation.
                    required:
                      - mutated
                    additionalProperties: false
        '400':
          description: Validation failure, malformed RPC input, or non-draft campaign.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '401':
          description: Missing or invalid authentication.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '404':
          description: Campaign doesn't exist or isn't owned by the caller.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '500':
          description: Unexpected server error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: pk_live_...

````