Skip to main content
Templates define reusable message content. Create and manage them in the dashboard (/templates) or via the public REST API (/v1/templates) and the MCP server (templates_create / templates_update / templates_delete). When sending, reference the template by templateId and pass a variables object with matching keys.
All requests use the x-api-key: ps_... header (or x-api-key-id). Base URL: https://pilotstatus.com.br/v1.

Category

Set at creation time; cannot be changed later.
  • MARKETING — promotional messages (more sensitive to WhatsApp policies).
  • UTILITY — transactional messages (account updates, alerts, reminders).
  • OTP — one-time / verification code messages.

Template structure

Only body is required.
  • REST API: pass either header.url (public http(s) URL) or header.base64 (data URI) — base64 is re-hosted server-side automatically.
  • MCP: header.url only — base64 is not supported over MCP.
There is no LOCATION header.

Body

  • Up to 1024 characters.
  • Variables written as {{nome}} (named style).
  • The body must not start or end with a variable.
  • Emojis and multiple variables allowed.
Static text up to 60 characters. No variables.

Buttons

Up to 10 buttons total; quick-reply and CTA buttons can be mixed.
  • Dynamic URL button: URL ends with a variable (e.g. https://loja.com/promo/{{link}}) — one variable max, never in the domain. Sample value goes in examples.
  • Copy-code: value goes on the button as example (array, e.g. ["PROMO10"]), alphanumeric only, up to 15 chars. Not for PIX keys or e-mails — put those in the body as a {{variable}} instead.
  • Buttons are allowed together with a video or document (PDF) header.

Variables & examples (required)

When creating/updating via REST or MCP you must include an examples object mapping every variable used (body + header text + dynamic URL) to a real sample value. The copy-code value is the only exception (it lives on the button).
After saving, GET /v1/templates/{id} returns all detected keys in the top-level variables array (a string[]) — supply all of them in variables on send. There is no latestVersion object in the public API response.

Character limits

Create via REST API

  • body may be an object (recommended), a JSON string, or plain text (body-only templates).
  • Edit with PUT /v1/templates/{id} (same shape); remove with DELETE /v1/templates/{id} (also deletes from Meta for Meta templates; returns { deleted: true, id }).
  • GET /v1/templates / GET /v1/templates/{id} return source (META | PILOT_STATUS), metaStatus (APPROVED | PENDING | REJECTED | DISABLED | null), metaLanguage, and sendable — on a Meta number only META templates with metaStatus: "APPROVED" are sendable.

Approval

  • Meta numbers: templates are submitted to Meta for review (“Submit to Meta” in /templates, or on save). Categories, language and status follow Meta’s rules.
  • Unofficial (Pilot Status web) numbers: templates are created locally and immediately usable — no approval step.

Not supported

FLOW, LOCATION (header or button), CAROUSEL, CATALOG/MPM, LIMITED_TIME_OFFER, OTP autofill/one-tap/zero-tap, VOICE_CALL buttons, and the NAMED parameter_format.

Submit & rejection errors

Link/URL buttons accept a single variable that must be at the end of the URL and never in the domain; call buttons need the country code (e.g. +55).

Checked before submitting to Meta

API-side validation

Meta rejected the submission

Rejected after review

Blocks when sending (even approved)

Common error when sending

404 — template without an approved version (doesn’t exist for the key, or Meta template has no approved version yet).