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

# Templates

> Send pre-approved message templates with typed parameters

export const TypeTooltip = ({name, type, children}) => {
  const [visible, setVisible] = React.useState(false);
  const [pos, setPos] = React.useState({
    top: 0,
    left: 0
  });
  const triggerRef = React.useRef(null);
  const show = () => {
    if (triggerRef.current) {
      const rect = triggerRef.current.getBoundingClientRect();
      setPos({
        top: rect.bottom + 6,
        left: rect.left
      });
    }
    setVisible(true);
  };
  const hide = () => setVisible(false);
  return <>
      <span ref={triggerRef} onMouseEnter={show} onMouseLeave={hide} style={{
    cursor: "pointer",
    position: "relative",
    display: "inline"
  }}>
        {children || <code>{name}</code>}
      </span>
      {visible && <span style={{
    position: "fixed",
    top: pos.top,
    left: pos.left,
    zIndex: 9999,
    padding: "8px 12px",
    borderRadius: "8px",
    fontSize: "13px",
    lineHeight: "1.5",
    fontFamily: "'Azeret Mono', monospace",
    whiteSpace: "pre",
    backgroundColor: "var(--tw-prose-pre-bg, #1e1e1e)",
    color: "var(--tw-prose-pre-code, #e5e5e5)",
    border: "1px solid var(--border, rgba(128,128,128,0.2))",
    boxShadow: "0 4px 16px rgba(0,0,0,0.3)",
    pointerEvents: "none"
  }}>
          {type}
        </span>}
    </>;
};

Templates are the only way to send outside the 24-hour customer service window. Create them in the WhatsApp Business Manager, wait for approval, then fill in the variables with the SDK's builder.

## The builder

The `template` helper returns an immutable builder — chain `.body()`, `.header()`, `.button()`, and `.carousel()` to add components:

```ts theme={null}
import { template, text } from "@photon-ai/whatsapp-business";

const msg = template("order_confirmation", "en_US")
  .body(text("Alice"), text("#A42"), text("$129.00"));

await client.messages.send({ to: "+15551234567", template: msg });
```

Each chain call returns a new builder — the original is untouched, so you can build partial templates and reuse them.

## Parameter helpers

Every variable in your template matches one of these factories. The type name is the `type` field on the parameter.

| Helper              | Use for                     |
| ------------------- | --------------------------- |
| `text(value)`       | Plain text variables.       |
| `image(media)`      | Header images.              |
| `video(media)`      | Header video.               |
| `document(media)`   | Header documents.           |
| `location(loc)`     | Header location.            |
| `payload(value)`    | Quick-reply button payload. |
| `couponCode(value)` | Coupon code button.         |
| `actionJson(value)` | Catalog / flow action JSON. |

```ts theme={null}
import { template, text, image } from "@photon-ai/whatsapp-business";

const msg = template("shipping_update", "en_US")
  .header(image({ id: mediaId }))
  .body(text("Alice"), text("1Z999AA10123456784"));
```

## Header, body, buttons

```ts theme={null}
const msg = template("promo_launch", "en_US")
  .header(text("Spring sale"))
  .body(text("Alice"), text("30%"))
  .button(0, payload("apply_code"))      // quick-reply button
  .urlButton(1, text("spring-30"));      // dynamic URL suffix
```

`button(index, ...)` — quick-reply button, payload parameter.
`urlButton(index, ...)` — URL button, text parameter appended to the approved base URL.

Indexes correspond to the button positions defined when the template was approved.

## Carousel templates

Carousels are body templates with per-card components:

```ts theme={null}
import { template, text, image } from "@photon-ai/whatsapp-business";

const msg = template("weekly_picks", "en_US")
  .body(text("Alice"))
  .carousel([
    {
      cardIndex: 0,
      components: [
        { type: "header", parameters: [{ type: "image", image: { id: card1Id } }] },
        { type: "body", parameters: [{ type: "text", text: "Item 1" }] },
      ],
    },
    {
      cardIndex: 1,
      components: [
        { type: "header", parameters: [{ type: "image", image: { id: card2Id } }] },
        { type: "body", parameters: [{ type: "text", text: "Item 2" }] },
      ],
    },
  ]);
```

Each card's `components` list uses the same `TemplateComponentInput` shape the body builder produces — you can construct them with `template(...)` sub-builders or inline them.

## Raw template input

The builder always satisfies <TypeTooltip name="TemplateInput" type={`interface TemplateInput {
readonly components?: readonly TemplateComponentInput[];
readonly languageCode: string;
readonly name: string;
}`} />, so if you prefer a declarative object you can skip the builder and pass one directly:

```ts theme={null}
await client.messages.send({
  to: "+15551234567",
  template: {
    name: "order_confirmation",
    languageCode: "en_US",
    components: [
      {
        type: "body",
        parameters: [
          { type: "text", text: "Alice" },
          { type: "text", text: "#A42" },
        ],
      },
    ],
  },
});
```

Use whichever reads better in context — the wire format is identical.
