---
title: "Submit a draft template"
method: POST
path: "/api/v1/templates/{id}/submit"
tags: ["templates"]
---

# Submit a draft template

`POST /api/v1/templates/{id}/submit`

## Request

- Base URL: `https://app.blueticked.com`
- URL: `https://app.blueticked.com/api/v1/templates/{id}/submit`
- Auth: HTTP bearer

Send an existing draft to Meta for review. The draft itself is submitted, so no second template is created.

Use it for a draft saved in the dashboard, or one POST /api/v1/templates left at `draft` when Meta refused it: correct the draft in the dashboard, then submit it here. POST /api/v1/templates always creates a new template, so retrying that call leaves the old draft behind.

The draft is checked the way the dashboard checks it before anything reaches Meta; a problem answers 400 `validation_failed` with what to change. A template that is not a draft (`pending`, `approved`, `rejected`, `paused`) answers 409 `conflict` with its `status` in `details`; to change a submitted template, create a new one. A draft that another submit is sending right now also answers 409 `conflict` (`details.reason` `template_not_draft`): only one submit of a draft reaches Meta. With the same Idempotency-Key, a retry of a success gets the first answer back.

It goes through the draft's own WhatsApp number, or the connected number of its business when it has none; a number that is not connected answers 503 `channel_unavailable`. Meta refusing the template answers 502 `provider_error` with Meta's words.

The response is the template with `status: "pending"`; poll GET /api/v1/templates/{id} for Meta's decision. A test key runs every check and stops before Meta: the draft is unchanged and the response carries `test_mode: true` and `submitted_to_meta: false`.

## Path parameters

- `id` string, required

## Headers

- `Idempotency-Key` string

## Response `200`

Success

- object
  - `id` string, uuid, required
  - `channel_id` string, uuid, nullable
  - `name` string, required
  - `category` 'marketing' | 'utility' | 'authentication', required
  - `language` string, required
  - `body` string, required
  - `footer` string, nullable, required
  - `buttons` unknown[], required
    - unknown
  - `status` 'draft' | 'pending' | 'approved' | 'rejected' | 'paused' | 'disabled', required
  - `external_id` string, nullable
  - `rejection_reason` string, nullable, required
  - `submitted_at` string, date-time, required
  - `approved_at` string, date-time, nullable, required
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `request_id` string, required
  - `test_mode` boolean: Present, and true, only on a test key's answer.
  - `submitted_to_meta` boolean: Present, and false, only on a test key's answer: the draft was checked and not sent to Meta.

## Other responses

- `400`: Validation failed
- `401`: Unauthorized: missing or invalid API key
- `402`: Insufficient wallet balance
- `403`: Forbidden: scope, plan limit, or suspension
- `404`: Not found
- `409`: Conflict (idempotency-key reuse or resource in use)
- `422`: Understood but refused: the request is well-formed, the action is not permitted for this resource
- `429`: Rate limited
- `500`: Internal error
- `502`: An upstream provider refused or failed the request
- `503`: Channel or send queue unavailable

---

[API](https://skmtc.dev/blueticked/apis/blueticked-api.md) · [All operations](https://skmtc.dev/blueticked/apis/blueticked-api/llms.txt) · [OpenAPI document](https://skmtc.dev/blueticked/apis/blueticked-api/revisions/07132284f4ff?raw)
