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

# Update Template

> Update an existing WhatsApp message template. Full-replace semantics, controlled via the Prefer header.

## What it does

Edits the content (components) of an existing template. On Meta the edit is **full-replace**: the component set you send becomes the new state, and any component you don't send is removed. After a successful edit the status returns to `PENDING` (re-review) and the local DB is synced. `name` and `language` cannot be changed. The response body is controlled via `Prefer`.

Internally, the template's current category is first fetched from Meta (for auth / standard component structure), then the edit is submitted.

<Tip>
  **Template update = PUT semantics:** always send the full component set, or missing components are deleted (or you get a `409`).
</Tip>

<Warning>
  **Golden rule:** to preserve existing components, send the full set. Sending only `body` drops the other components and is rejected (see Demo 6). Editing is allowed only when the template is `APPROVED`, `REJECTED`, or `PAUSED`.
</Warning>

***

## Endpoint

```text theme={null}
POST /public/api/v1/wa/{app_id}/templates/{source_id}
```

### Headers

<ParamField header="Authorization" type="string" required>
  Secret key in `Bearer sk_...` format. See [Secret Key authentication](/essentials/authentication#secret-key).
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Always `application/json`.
</ParamField>

<ParamField header="Prefer" type="string">
  `return=representation` (default) returns the updated template; `return=minimal` returns no body. The applied preference is reported via the `Preference-Applied` header.
</ParamField>

### Path parameters

<ParamField path="app_id" type="string" required>
  Application ID.
</ParamField>

<ParamField path="source_id" type="string" required>
  The template's Meta ID.
</ParamField>

***

## Request Body

`name` and `language` cannot be sent. The inner objects (`header` / `body` / `footer` / `buttons`) use the same schema as [Create Template](/public-api-reference/template/create-template#request-body). Full-replace: send every component you want to keep (at minimum `body`).

<ParamField body="body" type="object" required>
  Body component. Must always be sent (structurally required).
</ParamField>

<ParamField body="header" type="object | null">
  Header component (send it if you want to keep it).
</ParamField>

<ParamField body="footer" type="object | null">
  Footer component.
</ParamField>

<ParamField body="buttons" type="array | null">
  Buttons (max 10).
</ParamField>

<ParamField body="messageSendTtlSeconds" type="integer | null">
  Message time-to-live.
</ParamField>

<ParamField body="category" type="string | null">
  Category change ([Template Category](/public-api-reference/template/reference/enums#template-category)). Effective only for `REJECTED`/`PAUSED`; for `APPROVED` Meta rejects it; subject to review.
</ParamField>

***

## Response

With `Prefer: return=representation` (default), the response is `{ "data": {...}, "isSuccess": true }` — the full template re-fetched from Meta after the edit (with components), `status: "PENDING"`. With `return=minimal`, it is `{ "isSuccess": true }`.

<ResponseField name="isSuccess" type="boolean">
  `true` when the update was accepted.
</ResponseField>

<ResponseField name="data" type="object | null">
  The updated template (`TemplateResponseModel`): `sourceId`, `name`, `language`, [`category`](/public-api-reference/template/reference/enums#template-category), [`status`](/public-api-reference/template/reference/enums#template-status), `components`, [`qualityScore`](/public-api-reference/template/reference/enums#template-quality-score), `rejectedReason`, [`parameterFormat`](/public-api-reference/template/reference/enums#template-parameter-format). `null` when `Prefer: return=minimal`.
</ResponseField>

***

## Examples

<AccordionGroup>
  <Accordion title="Demo 1 — full update (representation)">
    ```text theme={null}
    POST /public/api/v1/wa/{app_id}/templates/842802041844912
    Authorization: Bearer sk_...
    Prefer: return=representation
    Content-Type: application/json
    ```

    ```json theme={null}
    {
      "header": { "format": "TEXT", "text": "Order #{{1}} update", "examples": ["12345"] },
      "body": { "text": "Hi {{1}}, your order {{2}} is now {{3}}. Thank you.", "examples": ["John", "#12345", "shipped"] },
      "footer": { "text": "Connexease" },
      "buttons": [ { "type": "QUICK_REPLY", "text": "Track" } ]
    }
    ```

    ```json theme={null}
    {
      "data": {
        "sourceId": "842802041844912",
        "name": "order_confirmation",
        "language": "en",
        "category": "UTILITY",
        "status": "PENDING",
        "components": [
          { "type": "HEADER", "format": "TEXT", "text": "Order #{{1}} update", "example": { "headerText": ["12345"] } },
          { "type": "BODY", "text": "Hi {{1}}, your order {{2}} is now {{3}}. Thank you.", "example": { "bodyText": [["John", "#12345", "shipped"]] } },
          { "type": "FOOTER", "text": "Connexease" },
          { "type": "BUTTONS", "buttons": [ { "type": "QUICK_REPLY", "text": "Track" } ] }
        ],
        "qualityScore": "UNKNOWN",
        "rejectedReason": "NONE",
        "parameterFormat": "POSITIONAL"
      },
      "isSuccess": true
    }
    ```
  </Accordion>

  <Accordion title="Demo 2 — minimal (Prefer: return=minimal)">
    ```text theme={null}
    POST /public/api/v1/wa/{app_id}/templates/842802041844912
    Authorization: Bearer sk_...
    Prefer: return=minimal
    Content-Type: application/json
    ```

    ```json theme={null}
    {
      "header": { "format": "TEXT", "text": "Order #{{1}} update", "examples": ["12345"] },
      "body": { "text": "Hi {{1}}, your order {{2}} is now {{3}}. Thank you.", "examples": ["John", "#12345", "shipped"] },
      "footer": { "text": "Connexease" },
      "buttons": [ { "type": "QUICK_REPLY", "text": "Track" } ]
    }
    ```

    ```json theme={null}
    { "data": null, "isSuccess": true }
    ```
  </Accordion>

  <Accordion title="Demo 3 — change category (REJECTED/PAUSED)">
    ```text theme={null}
    POST /public/api/v1/wa/{app_id}/templates/1234567890
    Authorization: Bearer sk_...
    Content-Type: application/json
    ```

    ```json theme={null}
    { "category": "UTILITY", "body": { "text": "Hi {{1}}, your order {{2}} has been received. We'll update you soon.", "examples": ["John", "#12345"] } }
    ```

    ```json theme={null}
    {
      "data": { "sourceId": "1234567890", "name": "promo_blast", "language": "en", "category": "MARKETING", "status": "PENDING", "qualityScore": "UNKNOWN", "rejectedReason": "NONE", "parameterFormat": "POSITIONAL" },
      "isSuccess": true
    }
    ```
  </Accordion>

  <Accordion title="Demo 4 — error: non-editable status (template PENDING) → 409">
    ```json theme={null}
    {
      "errors": { "code": "META_096", "group": "CONFLICT", "description": "Template update failed. Template is not in an editable status (editable only when APPROVED, REJECTED or PAUSED; it may be PENDING after a recent edit)." },
      "isSuccess": false
    }
    ```
  </Accordion>

  <Accordion title="Demo 5 — error: 24h edit limit → 429">
    ```json theme={null}
    {
      "errors": { "code": "META_097", "group": "LIMIT_EXCEEDED", "description": "Template update failed. Details: You can only edit an active template once in 24 hours." },
      "isSuccess": false
    }
    ```
  </Accordion>

  <Accordion title="Demo 6 — error: sending only body and breaking structure → 409">
    ```text theme={null}
    POST /public/api/v1/wa/{app_id}/templates/842802041844912
    Authorization: Bearer sk_...
    Content-Type: application/json
    ```

    ```json theme={null}
    { "body": { "text": "Hello {{1}}, your order {{2}} has been confirmed.", "examples": ["John", "#12345"] } }
    ```

    ```json theme={null}
    {
      "errors": { "code": "META_096", "group": "CONFLICT", "description": "Template update failed. Details: The status for this message template can't be changed. You can only delete or add templates." },
      "isSuccess": false
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Errors

<ResponseField name="errors" type="object">
  Error details with `code`, `group`, and `description`; `isSuccess` is `false`.
</ResponseField>

### Auth / tenant

| HTTP | Code                              | When                                          |
| ---- | --------------------------------- | --------------------------------------------- |
| 401  | `ORGANIZATION_SECRET_010` / `011` | Secret key missing / invalid.                 |
| 404  | `APPLICATION_004`                 | `app_id` does not belong to the organization. |

### Pre-fetch (while fetching the current template)

| HTTP | Code       | When                              |
| ---- | ---------- | --------------------------------- |
| 404  | `META_075` | `source_id` not found.            |
| 401  | `META_034` | Token invalid during fetch (190). |
| 403  | `META_035` | Fetch permission denied.          |
| 429  | `META_036` | Fetch rate limit.                 |
| 502  | `META_004` | General fetch error.              |

### Request validation (422)

| HTTP | When                                                                                                                                             |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| 422  | Body starts/ends with a variable, examples count mismatch, button rule violation, `messageSendTtlSeconds` out of range, invalid `category` enum. |

### Update

| HTTP | Code       | When (Meta)                                                     |
| ---- | ---------- | --------------------------------------------------------------- |
| 401  | `META_092` | Token invalid (190).                                            |
| 403  | `META_093` | Permission denied (10 / 200–299).                               |
| 429  | `META_094` | Rate limit (4 / 80007).                                         |
| 400  | `META_095` | Invalid parameter (100, no subcode).                            |
| 409  | `META_096` | Non-editable status (2388003) / structural rejection (2388039). |
| 429  | `META_097` | 24h edit limit (2388124).                                       |
| 409  | `META_017` | Same name+language conflict (2388024).                          |
| 422  | `META_022` | Character limit (2388040).                                      |
| 422  | `META_023` | Header format (2388047).                                        |
| 422  | `META_024` | Body format (2388072).                                          |
| 422  | `META_025` | Footer format (2388073).                                        |
| 422  | `META_026` | Variable / text ratio (2388293).                                |
| 422  | `META_027` | Variable in first/last position (2388299).                      |
| 422  | `META_028` | WABA migration (2388103).                                       |
| 422  | `META_029` | Other policy/validation (unknown 2388xxx).                      |
| 502  | `META_091` | General/fallback (or Meta `success:false`).                     |
