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

# Replace the template

> Replace the whole template (existing variant keys kept, new ones minted)



## OpenAPI

````yaml /openapi-v3.yaml put /send/campaigns/{campaign_id}/templates
openapi: 3.1.0
info:
  title: Origami API v3
  version: '3.0'
  description: >
    The Origami **v3 API** is the current public surface: named, typed

    operations in three sections (**Account**, **Leads**, **Send**) plus

    one shared **Job** resource for all async work. The same catalog

    drives HTTP (`https://origami.chat/api/v3`), the hosted MCP server

    (`https://origami.chat/mcp`), and the `origami` CLI.


    **Wire conventions.** Fields are `snake_case`. Every object carries

    an `object` type field. Every list is

    `{ "object": "list", "items": [...], "next_cursor": string|null, "url":
    string }`

    and pages with `cursor` + `limit` (max 100). Unknown request fields

    are rejected with `400 VALIDATION_ERROR` — a camelCase body fails

    loudly instead of being silently stripped.


    **Async work.** Async operations return `202` with a Job. Poll

    `GET /jobs/{job_id}` honoring `next_poll_at` / `Retry-After`, or

    subscribe to `job.*` webhooks. `succeeded` means the work

    *including enrichment* is done, so result counts are final.


    **Auth.** `Authorization: Bearer og_live_...`. Keys carry a role

    (`member` default, or `admin`). Scope a request to a child project

    with `x-origami-project: <project_id>`. The header applies to

    Leads, Send, Jobs, and — within Account — chats and exclusion

    lists. It is ignored by project management, org reads, senders,

    domains, mailboxes, webhooks, and API-key routes.


    **Idempotency.** Any POST may send `Idempotency-Key: <uuid>`. Reuse

    with a different body → `409 IDEMPOTENCY_MISMATCH`. A racing retry

    → `409 IDEMPOTENCY_PENDING` (honor `Retry-After`).


    v1 and v2 remain available but are deprecated for new integrations.

    See the v2 → v3 migration guide for the 1:1 flow map.
servers:
  - url: https://origami.chat/api/v3
security:
  - bearerAuth: []
tags:
  - name: jobs
    description: Shared async Job resource
  - name: account
    description: Org, projects, chats, senders, domains, exclusions, webhooks, keys
  - name: leads
    description: Lists, columns, rows, searches, enrichment
  - name: send
    description: 'Campaigns: the linear send recipe'
paths:
  /send/campaigns/{campaign_id}/templates:
    put:
      tags:
        - send
      summary: Replace the whole template (existing variant keys kept, new ones minted)
      operationId: send.campaigns.templates.put
      parameters:
        - name: campaign_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                sequences:
                  type: array
                  items:
                    type: object
                    properties:
                      variant_key:
                        type: string
                        pattern: ^[a-z0-9][a-z0-9-]{0,39}$
                      variant_name:
                        type: string
                        maxLength: 60
                      description:
                        type: string
                        maxLength: 2000
                      instructions:
                        type: string
                        maxLength: 4000
                      paused:
                        type: boolean
                      steps:
                        type: array
                        items:
                          type: object
                          properties:
                            channel:
                              type: string
                              enum:
                                - email
                                - linkedin_message
                                - linkedin_connect
                                - linkedin_comment
                                - linkedin_react
                                - manual
                            subject:
                              type: string
                              maxLength: 300
                            body:
                              type: string
                              maxLength: 20000
                            delay_days:
                              type: integer
                              minimum: 0
                              maximum: 30
                            personalized:
                              type: array
                              items:
                                anyOf:
                                  - type: string
                                    minLength: 1
                                  - type: object
                                    properties:
                                      text:
                                        type: string
                                        minLength: 1
                                      name:
                                        type: string
                                        minLength: 1
                                        maxLength: 80
                                      instruction:
                                        type: string
                                        minLength: 1
                                        maxLength: 1000
                                    required:
                                      - text
                                    additionalProperties: false
                              maxItems: 20
                            subject_personalized:
                              type: array
                              items:
                                anyOf:
                                  - type: string
                                    minLength: 1
                                  - type: object
                                    properties:
                                      text:
                                        type: string
                                        minLength: 1
                                      name:
                                        type: string
                                        minLength: 1
                                        maxLength: 80
                                      instruction:
                                        type: string
                                        minLength: 1
                                        maxLength: 1000
                                    required:
                                      - text
                                    additionalProperties: false
                              maxItems: 20
                            target_post:
                              type: object
                              properties:
                                mode:
                                  type: string
                                  enum:
                                    - latest
                                    - alias
                                    - writer_pick
                                alias:
                                  type: string
                                  pattern: ^post_[1-9][0-9]*$
                              required:
                                - mode
                              additionalProperties: false
                            on_missing_post:
                              type: string
                              enum:
                                - hold
                                - skip
                            reaction:
                              type: string
                              enum:
                                - like
                                - celebrate
                                - support
                                - love
                                - insightful
                                - funny
                            reaction_mode:
                              type: string
                              enum:
                                - fixed
                                - match_post
                          required:
                            - channel
                            - body
                            - delay_days
                          additionalProperties: false
                        minItems: 1
                        maxItems: 15
                    required:
                      - steps
                    additionalProperties: false
                  maxItems: 10
                sign_off_phrase:
                  type: string
                  maxLength: 200
                  nullable: true
              required:
                - sequences
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Validation error (unknown fields are rejected)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Conflict (TEMPLATE_SPANS_INVALID)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      description: Closed error envelope — no additional top-level keys.
      additionalProperties: false
      properties:
        error:
          type: string
        code:
          type: string
          description: UPPER_SNAKE_CASE machine code
        details:
          type: object
        handoff:
          type: object
          description: >-
            In-app recovery link when the user can fix the situation in the
            dashboard
          properties:
            kind:
              type: string
              enum:
                - connect-accounts
                - reconnect-account
                - billing
                - upgrade-plan
                - sca-confirm
            url:
              type: string
            label:
              type: string
      required:
        - error
        - code
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'API key: Authorization: Bearer og_live_...'

````