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

# Create Thread

> Create a draft one-off email thread in Unibox.

**CLI:**

```bash theme={null}
puffle thread create --account-id <account-id> --participant-email <participant-email> --participant-name <participant-name> --draft-subject <draft-subject> --draft-body-text <draft-body-text> --draft-body-html <draft-body-html> --draft-cc <draft-cc> --draft-bcc <draft-bcc>
```

## Overview

Creates a draft one-off email thread in Unibox. This does **not** send the email by itself. To send the message, call [Send message](/api-reference/unibox/send-thread-message) with the returned `thread.id`.

Use this endpoint when you want to start a new direct email conversation outside a campaign. Campaign sends still belong to the Campaigns API and sequence engine.

## Request Body

| Field               | Type   | Required                 | Description                                                                                                                                                                                      |
| ------------------- | ------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `participant_email` | string | Required to send         | Recipient email address. The API stores it lowercase.                                                                                                                                            |
| `account_id`        | string | Optional                 | Email sender account ID. If provided, it must belong to the workspace, be an email account, have a configured sending inbox, and be ready to send. You may also provide this later when sending. |
| `participant_name`  | string | Optional                 | Display name for the recipient.                                                                                                                                                                  |
| `draft_subject`     | string | Optional                 | Draft subject stored on the thread.                                                                                                                                                              |
| `draft_body_text`   | string | Optional                 | Plain-text draft body stored on the thread.                                                                                                                                                      |
| `draft_body_html`   | string | Optional                 | HTML draft body stored on the thread.                                                                                                                                                            |
| `draft_cc`          | string | Optional                 | Comma-separated CC recipients for the draft.                                                                                                                                                     |
| `draft_bcc`         | string | Optional                 | Comma-separated BCC recipients for the draft.                                                                                                                                                    |
| `draft_attachments` | array  | Forbidden when non-empty | Do not attach files while creating a thread. A non-empty array returns `403`; create the draft first, then add attachments in Unibox.                                                            |

At least one draft field must be present. A sendable one-off email needs `participant_email` plus an email sender account, either here as `account_id` or later in the send request.

Attachment upload metadata is available only to authenticated dashboard sessions. No caller can attach files while creating a thread: omit `draft_attachments` or send the dashboard's empty array, create the draft first, then add attachments to it in Unibox. Both Bearer API-key and session requests return `403` for a non-empty array.

## Example

```bash theme={null}
curl -X POST "https://app.puffle.ai/api/threads" \
  -H "Authorization: Bearer $PUFFLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "8a2f0c7a-9d1e-4d8f-9d7d-6a8b8e8f4a11",
    "participant_email": "founder@example.com",
    "participant_name": "Alex Founder",
    "draft_subject": "Quick question",
    "draft_body_text": "Hi Alex, I had a quick question about your outbound workflow."
  }'
```

The response includes the created draft as `thread`.

```json theme={null}
{
  "thread": {
    "id": "3d986dd1-9d70-45b7-8e36-5d5b8b1c9337",
    "channel": "email",
    "status": "draft",
    "account_id": "8a2f0c7a-9d1e-4d8f-9d7d-6a8b8e8f4a11",
    "participant_email": "founder@example.com",
    "draft_subject": "Quick question",
    "draft_body_text": "Hi Alex, I had a quick question about your outbound workflow."
  },
  "existing_threads": {
    "exists": false,
    "total": 0,
    "threads": []
  }
}
```

## Duplicate Recipient Handling

If the same sender already has a non-archived, non-warmup email thread with the recipient, the API returns `409` with `existing_thread` and `existing_threads`. Open that thread and call [Send message](/api-reference/unibox/send-thread-message) instead of creating a duplicate.

## AI agent notes

Use this endpoint before `POST /api/threads/{id}/messages` when starting a one-off email. Do not use it to send campaign sequence messages.


## OpenAPI

````yaml post /api/threads
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/threads:
    post:
      tags:
        - Unibox
      summary: Create Thread
      description: Create Thread
      operationId: createThread
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                account_id:
                  description: >-
                    Email sender account ID, or null when no sender is selected
                    yet.
                  type: string
                  nullable: true
                participant_email:
                  type: string
                  description: Recipient email address.
                participant_name:
                  type: string
                  description: Recipient display name.
                draft_subject:
                  type: string
                  description: Draft email subject.
                draft_body_text:
                  type: string
                  description: Draft plain-text body.
                draft_body_html:
                  description: Draft HTML body.
                  type: string
                  nullable: true
                draft_cc:
                  description: Draft CC recipients.
                  type: string
                  nullable: true
                draft_bcc:
                  description: Draft BCC recipients.
                  type: string
                  nullable: true
                draft_attachments:
                  description: >-
                    Forbidden when non-empty for all callers. Omit this field or
                    send an empty array, then add attachments after creating the
                    thread in Unibox.
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                        minLength: 1
                        description: Attachment file name.
                      url:
                        description: Attachment URL.
                        type: string
                        minLength: 1
                      bucket:
                        type: string
                        minLength: 1
                        description: Storage bucket containing the attachment.
                      path:
                        type: string
                        minLength: 1
                        description: Attachment path within the storage bucket.
                      mime_type:
                        type: string
                        minLength: 1
                      size:
                        type: number
                        minimum: 0
                      content_id:
                        type: string
                        minLength: 1
                      content_disposition:
                        type: string
                        enum:
                          - attachment
                          - inline
                    required:
                      - name
                      - bucket
                      - path
                    additionalProperties: false
              additionalProperties: false
      responses:
        '201':
          description: Thread created.
        '400':
          description: Bad request.
        '401':
          description: Unauthorized.
        '403':
          description: Forbidden.
        '409':
          description: Existing thread conflict.
        '500':
          description: Internal server error.
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: pk_live_...

````