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

# Retry Inbox Warmup

> Re-attempt warmup enablement for an inbox stuck in pending / not_started.

**CLI:**

```bash theme={null}
puffle email account retry-warmup --id <id>
```

## Overview

Retry path for inboxes whose initial warmup-enable call failed after the DB row was already written. The route:

1. Loads the account and verifies ownership (plus pulls its linked `email_domains` row for context).
2. Gates on `status: "pending"` AND `warmup_status: "not_started"` — any other combination returns 409.
3. Calls the warmup enablement path (idempotent; already-warming emails are accepted as success).
4. Transitions the row to `status: "warming"` / `warmup_status: "warming"` via compare-and-swap, so concurrent retries can't double-apply.

## AI agent notes

<Note>
  **Warmup is a multi-day process.** A successful retry only moves the account into `warming` — it still has to accrue reputation over \~2–3 weeks before it graduates to `active` and can send. Track progress via `getWarmupAnalytics`.

  **Idempotent.** If warmup was already running from a prior partial attempt, the retry still returns 200 and transitions the DB row forward. Safe to call until success.

  **Gate carefully.** Retry is only valid when `status === "pending"` AND `warmup_status === "not_started"`. If the account already warmed up, banned out, or graduated to `active`, this endpoint returns 409 — use `getWarmupAnalytics` to read current state instead.

  **Status-vs-502 split.**

  * `502` means the warmup provider rejected the call — try again after a short backoff.
  * `500` with the message "Warmup was enabled but failed to update account status" means the provider accepted but our DB write failed. Safe to retry immediately; a second warmup call is a no-op.

  **Chains with:** `getWarmupAnalytics` to watch reputation climb; `launchCampaign` once `status === "active"`.
</Note>


## OpenAPI

````yaml patch /api/email/accounts/{id}/retry-warmup
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/email/accounts/{id}/retry-warmup:
    patch:
      tags:
        - Senders
      summary: Retry Inbox Warmup
      description: >-
        Re-attempt warmup enablement for an email account stuck in `status:
        pending` + `warmup_status: not_started`. This usually happens when the
        initial warmup call at account creation failed after the DB row was
        written. The retry is idempotent, so it is safe to call even if a prior
        attempt half-succeeded. On success the row atomically transitions to
        `status: warming` / `warmup_status: warming` via a compare-and-swap; if
        a concurrent call already made that transition this endpoint re-reads
        the row and still returns 200.
      operationId: retryAccountWarmup
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            minLength: 1
            description: >-
              Supabase UUID of the email account. Must be owned by the caller
              and currently in `status: pending` + `warmup_status: not_started`.
      responses:
        '200':
          description: Warmup re-enabled. Returns the refreshed account row.
          content:
            application/json:
              schema:
                type: object
                properties:
                  account:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      user_id:
                        type: string
                        format: uuid
                      type:
                        type: string
                        enum:
                          - email
                      email_address:
                        type: string
                        format: email
                        nullable: true
                      status:
                        type: string
                        enum:
                          - pending
                          - warming
                          - active
                          - error
                          - disconnected
                      warmup_status:
                        type: string
                        enum:
                          - not_started
                          - warming
                          - warmed
                          - active
                          - banned
                          - suspended
                          - paused
                      agentmail_inbox_id:
                        type: string
                        nullable: true
                      daily_limit:
                        type: integer
                        exclusiveMinimum: true
                        maximum: 9007199254740991
                        nullable: true
                        minimum: 0
                      created_at:
                        type: string
                        format: date-time
                      updated_at:
                        type: string
                        format: date-time
                        nullable: true
                      email_domains:
                        type: object
                        properties:
                          id:
                            type: string
                            format: uuid
                          domain:
                            type: string
                          status:
                            type: string
                        required:
                          - id
                          - domain
                          - status
                        additionalProperties: false
                        nullable: true
                    required:
                      - id
                      - user_id
                      - type
                      - email_address
                      - status
                      - warmup_status
                      - daily_limit
                      - created_at
                      - updated_at
                    additionalProperties: {}
                    description: >-
                      Account row after the retry. On success, `status` is
                      `warming` and `warmup_status` is `warming`.
                required:
                  - account
                additionalProperties: false
        '400':
          description: Account exists but has no `email_address` — cannot enable warmup.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '401':
          description: Missing or invalid Bearer token.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '404':
          description: Account doesn't exist or isn't owned by the caller.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '409':
          description: >-
            Conflict. Either the account is not in a retryable state (`status
            === 'pending'` and `warmup_status === 'not_started'` are required),
            or Instantly is already running its warmup account update job and
            the caller should retry shortly.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '429':
          description: >-
            Instantly is rate limiting warmup enablement. The caller should
            retry after a short backoff.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '500':
          description: >-
            Warmup was enabled but the DB update failed; next retry is safe and
            will be a no-op on the warmup side. Or a generic DB fetch failure.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
        '502':
          description: >-
            The warmup provider rejected the enablement call (transient infra or
            auth issue). Retry after a short backoff.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
                additionalProperties: false
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: pk_live_...

````