Submit a template version for review
/v1/whatsapp/templates/{template_ref}/versions/{version_id}/submitconst draftId = "wav_01krdgeqcxet5s7t44vh8rt9mg";
const check = await bird.whatsapp.templates.versions.submit("order_update", draftId, {
validate_only: true,
});
for (const problem of check.errors) console.log(problem.language, problem.field, problem.message);
if (check.valid) {
const submitted = await bird.whatsapp.templates.versions.submit("order_update", draftId);
console.log(submitted.version?.id);
}draft_id = "wav_01krdgeqcxet5s7t44vh8rt9mg"
check = client.whatsapp.templates.versions.submit("order_update", draft_id, validate_only=True)
for problem in check.errors:
print(problem.language, problem.field, problem.message)
if check.valid:
submitted = client.whatsapp.templates.versions.submit("order_update", draft_id)
print(submitted.version.id if submitted.version else None)ctx := context.Background()
draftID := "wav_01krdgeqcxet5s7t44vh8rt9mg"
check, err := client.Whatsapp.Templates.Versions.Submit(ctx, "order_update", draftID,
bird.WhatsappTemplatesVersionsSubmitParams{ValidateOnly: bird.Bool(true)})
if err != nil {
log.Fatal(err)
}
if check.Errors != nil {
for _, problem := range *check.Errors {
fmt.Println(*problem.Message)
}
}
if check.Valid != nil && *check.Valid {
submitted, err := client.Whatsapp.Templates.Versions.Submit(ctx, "order_update", draftID,
bird.WhatsappTemplatesVersionsSubmitParams{})
if err != nil {
log.Fatal(err)
}
if submitted.Version != nil {
fmt.Println(submitted.Version.Id)
}
}$draftId = 'wav_01krdgeqcxet5s7t44vh8rt9mg';
$check = $bird->whatsapp->templates->versions->submit('order_update', $draftId, (new WhatsAppTemplateSubmit())->setValidateOnly(true));
foreach ($check->getErrors() ?? [] as $problem) {
echo $problem->getLanguage(), ' ', $problem->getField(), ' ', $problem->getMessage(), "\n";
}
if ($check->getValid()) {
$submitted = $bird->whatsapp->templates->versions->submit('order_update', $draftId, new WhatsAppTemplateSubmit());
echo $submitted->getVersion()?->getId(), "\n";
}bird whatsapp templates versions submit <template-ref> <version-id> \
--validate-only=truecurl -X POST "https://us1.platform.bird.com/v1/whatsapp/templates/{template_ref}/versions/{version_id}/submit" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"validate_only": true
}'{
"errors": [
{
"language": "pt-BR",
"field": "components[2].cards[0].components[1].example_parameters[0].url",
"code": "E15025",
"message": "A body block needs text."
}
],
"version": {
"id": "wav_01krdgeqcxet5s7t44vh8rt9mg",
"template_id": "wat_01krdgeqcxet5s7t44vh8rt9mg",
"version_number": 4,
"submitted_at": "2026-07-20T11:04:00Z",
"languages": {
"en": {
"status": "approved",
"components": [
{
"type": "body",
"text": "Your verification code is {{1}}.",
"example_parameters": [
{
"type": "text",
"text": "123456"
}
]
}
]
}
},
"created_at": "2026-07-20T10:31:00Z"
},
"next": [
{
"kind": "operation"
}
]
}
Validates the template draft before freezing it. If validation fails, the
API returns 200 OK with every problem across all languages and creates no
version. If validation passes, the API freezes an immutable version and
returns 202 Accepted. Only the languages whose content differs from their
approved copy are sent to Meta and marked pending; the rest carry their
existing verdict forward untouched, so a version whose languages are all
unchanged comes back already settled. A language an earlier version carried
but the draft dropped is deleted at Meta in the background. It is absent
from the new version, so it has no pending state. The version becomes live when any
language is approved, and no replacement draft opens automatically.
Set validate_only: true to run the same checks without freezing or
submitting a version. Local validation cannot predict Meta's decision. A
202 Accepted response confirms the version was frozen and accepted. Poll the
version or the template's pending_version_id for the verdicts on whichever
languages it marked pending.
Parameters
template_refstringTemplate ID (wat_ prefix) or slug. A value that parses as a valid ID resolves by ID; any other value resolves as a slug.
version_idstringID of the template version (wav_ prefix), as returned by the version list.
Request Payload
validate_onlyCheck the draft without submitting it. Every language is checked and every problem reported, but nothing is frozen and nothing is sent to WhatsApp. A clean result does not guarantee WhatsApp approval: WhatsApp offers no way to ask in advance, so it can still refuse a submission these checks passed. Use a different idempotency key for the validation and the submission. Reusing one key with different request bodies is rejected.
Response Payload
validWhether the version passed every check.
errorsEvery problem found across every language. One round trip identifies all problems. Empty when valid is true.
versionThe version this submit froze, or null when nothing was frozen: a check run, or a submit that found problems.
nextWhat to do next with this outcome. Present on reads that compute it: an empty list means there is nothing to do, and the field is absent entirely on responses that do not report next actions.
A failed check routes back to the languages that need an edit; a clean one routes to the real submit, and then to polling the template for WhatsApp's verdicts.
Related resources
Continue with the documentation, guides and examples for this topic.