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

# Update Template

> Update an existing template. Supports the same payload structure as template creation.

## Overview

Update an existing WhatsApp message template. The template will be resubmitted to Meta for review.

<Note>
  * Language **cannot be changed** after template creation
  * Category may be restricted for approved templates
  * Media file only required when changing media type
  * Template status changes to `UPDATING` during review
</Note>

***

## Request Body Schema

Same as [Create Template](/pages/endpoints/templates/add), with these differences:

| Field               | Update Restrictions                             |
| ------------------- | ----------------------------------------------- |
| `language`          | **Cannot be changed** (must match original)     |
| `category`          | May be locked if template is approved           |
| `header.media.file` | Required only when changing `header.media.type` |

***

## Example Payloads

### Update Text Content Only

```json theme={null}
{
  "name": "welcome_template",
  "language": "en",
  "category": "MARKETING",
  "body": {
    "text": "Welcome {{1}}! Your account is now active. Enjoy {{2}}% off your first order!",
    "variables": ["Customer", "20"]
  },
  "footer": "Valid for 30 days"
}
```

### Update Header Media Type

When changing media type (e.g., from image to video), the file is **required**:

```json theme={null}
{
  "name": "product_promo",
  "language": "en",
  "category": "MARKETING",
  "header": {
    "type": "media",
    "media": {
      "type": "video",
      "file": "<binary_file_data>"
    }
  },
  "body": {
    "text": "Check out our latest product showcase!",
    "variables": []
  }
}
```

### Keep Same Media Type

When keeping the same media type, file is **optional**:

```json theme={null}
{
  "name": "product_promo",
  "language": "en",
  "category": "MARKETING",
  "header": {
    "type": "media",
    "media": {
      "type": "image"
      // file not required if keeping same type
    }
  },
  "body": {
    "text": "Updated message text here!",
    "variables": []
  }
}
```

### Add Buttons to Existing Template

```json theme={null}
{
  "name": "order_confirmation",
  "language": "en",
  "category": "UTILITY",
  "body": {
    "text": "Your order #{{1}} is confirmed!",
    "variables": ["ORD-12345"]
  },
  "buttons": [
    {
      "type": "URL",
      "text": "Track Order",
      "url": "https://example.com/track"
    },
    {
      "type": "PHONE_NUMBER",
      "text": "Contact Support",
      "phone_number": "+1234567890"
    }
  ]
}
```

***

## Response

### Success (200 OK)

```json theme={null}
{
  "success": true,
  "message": "Template updated successfully and submitted to Meta for review."
}
```

### Validation Error (422)

```json theme={null}
{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "language": ["Language cannot be changed after template creation."],
    "header.media.file": ["The file field is required when changing media type."]
  }
}
```

***

## Template Status Flow

After updating:

1. **PENDING** → Template without `provider_id` (treated as new creation)
2. **UPDATING** → Existing template resubmitted for review
3. **APPROVED** → After Meta approval
4. **REJECTED** → If Meta rejects the changes

Use the [Sync endpoint](/pages/endpoints/templates/sync) to refresh template statuses.

***

## Common Update Scenarios

<AccordionGroup>
  <Accordion title="Changing Template Text">
    Update `body.text` and adjust `body.variables` array to match new placeholders:

    ```json theme={null}
    {
      "name": "existing_template",
      "language": "en",
      "category": "MARKETING",
      "body": {
        "text": "New message with {{1}} and {{2}}",
        "variables": ["value1", "value2"]
      }
    }
    ```
  </Accordion>

  <Accordion title="Removing Header">
    Set `header` to `null` or omit it:

    ```json theme={null}
    {
      "name": "existing_template",
      "language": "en",
      "category": "UTILITY",
      "header": null,
      "body": {
        "text": "Simple message without header",
        "variables": []
      }
    }
    ```
  </Accordion>

  <Accordion title="Changing Button URLs">
    Update the entire `buttons` array:

    ```json theme={null}
    {
      "name": "existing_template",
      "language": "en",
      "category": "MARKETING",
      "body": {
        "text": "Click below for updated link",
        "variables": []
      },
      "buttons": [
        {
          "type": "URL",
          "text": "New Link",
          "url": "https://newdomain.com/page"
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Adding/Removing Footer">
    Simply include or omit the `footer` field:

    ```json theme={null}
    {
      "name": "existing_template",
      "language": "en",
      "category": "UTILITY",
      "body": {
        "text": "Message content here",
        "variables": []
      },
      "footer": "New footer text"
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Important Notes

<Warning>
  **Breaking Changes**

  * Changing `language` will fail validation
  * Approved templates may have category restrictions
  * Template name follows same rules as creation (lowercase + underscores only)
</Warning>

<Tip>
  **Best Practices**

  * Test updates on duplicate templates first
  * Keep variable placeholders consistent
  * Use [Sync endpoint](/pages/endpoints/templates/sync) to monitor approval status
  * Backup original template configuration before major updates
</Tip>

***

For complete payload examples, see [TEMPLATE\_PAYLOADS.md](https://github.com/lancepilot/docs/blob/main/TEMPLATE_PAYLOADS.md).


## OpenAPI

````yaml POST /workspaces/{workspace}/templates/{template}
openapi: 3.1.0
info:
  title: Lancepilot API
  description: API for Lancepilot
  version: 1.0.0
  license:
    name: MIT
servers:
  - url: https://lancepilot.com/api/v3
security:
  - bearerAuth: []
paths:
  /workspaces/{workspace}/templates/{template}:
    post:
      tags:
        - Templates
      summary: Update a template
      description: >-
        Update an existing template. Supports the same payload structure as
        template creation.
      parameters:
        - name: workspace
          in: path
          description: ID of the workspace.
          required: true
          schema:
            type: string
            format: uuid
        - name: template
          in: path
          description: ID of the template.
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - language
                - category
                - body
              properties:
                name:
                  type: string
                  example: login_otp_template
                language:
                  type: string
                  example: en
                  description: Language cannot be changed after creation
                category:
                  type: string
                  enum:
                    - MARKETING
                    - UTILITY
                    - AUTHENTICATION
                  description: Category may be restricted based on template status
                header:
                  oneOf:
                    - type: 'null'
                      description: 'Option 1: No header'
                    - type: object
                      description: 'Option 2: Text Header'
                      required:
                        - type
                        - text
                      properties:
                        type:
                          type: string
                          enum:
                            - text
                        text:
                          type: object
                          required:
                            - content
                          properties:
                            content:
                              type: string
                              maxLength: 60
                            variables:
                              type: array
                              items:
                                type: string
                              maxItems: 1
                    - type: object
                      description: 'Option 3: Media Header'
                      required:
                        - type
                        - media
                      properties:
                        type:
                          type: string
                          enum:
                            - media
                        media:
                          type: object
                          required:
                            - type
                          properties:
                            type:
                              type: string
                              enum:
                                - image
                                - video
                                - document
                            file:
                              type: string
                              format: binary
                              description: Required only when changing media type
                body:
                  type: object
                  required:
                    - text
                  properties:
                    text:
                      type: string
                      maxLength: 1024
                    variables:
                      type: array
                      items:
                        type: string
                footer:
                  type: string
                  maxLength: 60
                buttons:
                  type: array
                  items:
                    type: object
                    required:
                      - type
                    properties:
                      type:
                        type: string
                        enum:
                          - URL
                          - PHONE_NUMBER
                          - QUICK_REPLY
                      text:
                        type: string
                      phone_number:
                        type: string
                        description: Required for PHONE_NUMBER
                      url:
                        type: string
                        format: uri
                        description: Required for URL
                      variables:
                        type: array
                        items:
                          type: string
                        maxItems: 1
                        description: Only for URL buttons with {{1}} variable
                unsubscribeButton:
                  type: boolean
                blockButton:
                  type: boolean
                addSecurityRecommendation:
                  type: boolean
                  description: Required for AUTHENTICATION category
                codeExpirationMinutes:
                  type: integer
                  minimum: 1
                  maximum: 1440
                  description: Required for AUTHENTICATION category
                copyCodeButton:
                  type: boolean
                  description: Required for AUTHENTICATION category
      responses:
        '200':
          $ref: '#/components/responses/Update200'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '422':
          description: Validation failed
components:
  responses:
    '401':
      description: ''
      content:
        application/json:
          schema:
            type: object
            properties:
              message:
                type: string
                example: Unauthenticated.
            required:
              - message
    '404':
      description: ''
      content:
        application/json:
          schema:
            type: object
            properties:
              message:
                type: string
                example: Resource not found.
              status:
                type: integer
                example: 404
            required:
              - message
              - status
    Update200:
      description: ''
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: integer
                example: 200
              message:
                type: string
                example: Resource updated successfully.
              data:
                type: object
                description: Updated resource data.
            required:
              - status
              - message
              - data
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````