# Get a template

> GET /v2/templates/{templateId}

`GET https://api.zavu.dev/v2/templates/{templateId}`

## Parameters

- `templateId` (path, string, required)

## Responses

### 200

The template.

- `id` (string, required)
- `name` (string, required): Template name. For WhatsApp, must match the approved template name in Meta.
- `language` (string, required): Language code.
- `body` (string, required): Default template body with variables: positional ({{1}}, {{2}}) or named ({{customer_name}}, {{contact.first_name}}). Templates created in Zavu are submitted to Meta as positional; templates imported from a WhatsApp Business Account keep their original format (named or positional). Used when no channel-specific body is set.
- `smsBody` (string): Channel-specific body for SMS messages. Falls back to `body` if not set.
- `telegramBody` (string): Channel-specific body for Telegram messages. Falls back to `body` if not set.
- `instagramBody` (string): Channel-specific body for Instagram messages. Falls back to `body` if not set.
- `category` (string, required): The category the template is billed under. For a template linked to WhatsApp this is the category **Meta currently assigns**, not the one it was submitted with: Meta can recategorize a template at approval or at any point afterwards, and that changes what the message costs. A recategorization reaches this field through the `template.status_changed` webhook, which carries `data.category`, and through `POST /v1/templates/sync`, which reconciles it against Meta. Read one of those rather than assuming the category you sent is the one in force. For a template that was never submitted to WhatsApp, this is the category stored locally, defaulting to `UTILITY`. One of: `UTILITY`, `MARKETING`, `AUTHENTICATION`.
- `status` (string) One of: `draft`, `pending`, `approved`, `rejected`.
- `variables` (string[]): List of variable names for documentation.
- `headerType` (string): Type of header (text, image, video, document).
- `headerContent` (string): Header content (text or media URL).
- `footer` (string): Footer text for the template.
- `buttons` (object[]): Template buttons.
  - `type` (string) One of: `quick_reply`, `url`, `phone`, `otp`, `request_contact_info`.
  - `text` (string)
  - `url` (string)
  - `example` (string): Sample value used to substitute `{{1}}` in the URL when submitting the template to Meta for review. Only present for dynamic URL buttons.
  - `phoneNumber` (string)
  - `otpType` (string): OTP button type. Required when type is 'otp'. One of: `COPY_CODE`, `ONE_TAP`.
  - `packageName` (string): Android package name. Required for ONE_TAP buttons.
  - `signatureHash` (string): Android app signature hash. Required for ONE_TAP buttons.
- `addSecurityRecommendation` (boolean): Add 'Do not share this code' disclaimer. Only for AUTHENTICATION templates.
- `codeExpirationMinutes` (integer): Code expiration time in minutes. Only for AUTHENTICATION templates.
- `whatsapp` (object): WhatsApp-specific template information.
  - `templateName` (string): WhatsApp template name.
  - `namespace` (string): WhatsApp Business Account namespace.
  - `status` (string): WhatsApp approval status.
- `createdAt` (string<date-time>)
- `updatedAt` (string<date-time>)

### 401

Unauthorized.

- `code` (string, required)
- `message` (string, required)
- `details` (object): Machine-readable context. Keys that mean the same thing everywhere: - `errors`: present on every `400 invalid_request` for an invalid body or query parameter, `[{path, message, ...}]`, `path` naming the field (`["to"]`, `["contacts", 2, "recipient"]`, `["limit"]`). - `recommendation`: one sentence saying what to do next. - `dashboardUrl`: the dashboard screen that fixes it. - `connect`: on `409 no_channel`, the channels this project can connect to reach the recipient, each `{type, request, note, available, dashboardUrl?}`; `request` is the exact call (`POST /v2/channels` with its body, or `POST /v2/numbers`), or null for a channel connected from the dashboard (WhatsApp, Instagram, Messenger). `available: false` says why in `note` (one-way SMS closed until business verification is approved). - `address` / `from`: the address the error is about, under the name the request used for it.
  - `errors` (object[])
    - `path` (object[], required)
    - `message` (string, required)
    - `code` (string)

### 404

Template not found, or it belongs to another project.

- `code` (string, required)
- `message` (string, required)
- `details` (object): Machine-readable context. Keys that mean the same thing everywhere: - `errors`: present on every `400 invalid_request` for an invalid body or query parameter, `[{path, message, ...}]`, `path` naming the field (`["to"]`, `["contacts", 2, "recipient"]`, `["limit"]`). - `recommendation`: one sentence saying what to do next. - `dashboardUrl`: the dashboard screen that fixes it. - `connect`: on `409 no_channel`, the channels this project can connect to reach the recipient, each `{type, request, note, available, dashboardUrl?}`; `request` is the exact call (`POST /v2/channels` with its body, or `POST /v2/numbers`), or null for a channel connected from the dashboard (WhatsApp, Instagram, Messenger). `available: false` says why in `note` (one-way SMS closed until business verification is approved). - `address` / `from`: the address the error is about, under the name the request used for it.
  - `errors` (object[])
    - `path` (object[], required)
    - `message` (string, required)
    - `code` (string)

## Example

```bash
curl -X GET "https://api.zavu.dev/v2/templates/template_abc123" \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY"
```

```typescript
import Zavudev from "@zavudev/sdk";

const zavu = new Zavudev({ apiKey: process.env.ZAVUDEV_API_KEY });

const result = await zavu.v2.templates.retrieve("template_abc123");

console.log(result);
```
