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

# WhatsApp CTA-URL tap-to-open link buttons

> Send a labelled tap-to-open link button on a free-form WhatsApp message inside the 24-hour customer-service window — no template review — and track every tap as a short_link.click webhook.

# WhatsApp CTA-URL tap-to-open link buttons

A CTA-URL button is a labelled link button attached below a free-form WhatsApp message: the customer sees your message text with one button under it, and tapping the button opens your URL in their browser. You choose the label and the URL at send time, and because the message ships inside the [24-hour customer-service window](/guides/whatsapp/24h-window), nothing waits for Meta template review.

This guide shows the send request, what a tap produces on your webhook endpoint, the rules the URL and label have to follow, and when a template URL button is the better fit.

## Why no template review is needed

Meta splits WhatsApp outbound into two regimes: pre-approved templates for business-initiated contact, and free-form messages inside the 24-hour customer-service window that the customer opens by messaging you. A CTA-URL button belongs to the free-form regime. It is an interactive message type (`cta_url`) sent exactly like a session text message, with a link button attached, so it is allowed whenever a session text message is allowed and refused whenever one would be refused.

The trade-off is reach. Once the window lapses, only a template can reach the customer, and that includes messages with a CTA-URL button. Plan CTA-URL sends for conversations the customer has recently started.

## The send request

`POST /api/v1/whatsapp/messages/send-interactive` with an `action` of `display_text` + `url` sends a CTA-URL button:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/whatsapp/messages/send-interactive \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155552671",
    "header": "Your order is on the way",
    "body": "Order #10482 left our warehouse this morning and should arrive Thursday.",
    "footer": "Replies to this message go straight to support.",
    "action": {
      "display_text": "Track order",
      "url": "https://shop.example.com/orders/10482/status"
    }
  }'
```

Field rules:

| Field | Required | Rule |
| - | - | - |
| `to` | Yes | Recipient E.164 number or WhatsApp Business Solution UID |
| `header` | No | Up to 60 characters |
| `body` | Yes | 1–1024 characters of message text |
| `footer` | No | Up to 60 characters |
| `action.display_text` | Yes | The button label, 1–20 characters |
| `action.url` | Yes | An `https://` link |

A non-HTTPS URL is rejected with a 422 before anything is sent. The same route also sends tap-to-reply buttons (`action: { buttons }`, up to three) and list menus (`action: { button, sections }`); only the `display_text` + `url` shape produces a CTA-URL button.

A successful send returns the message id and status, and your webhook subscribers receive `message.sent` as with any other send. If the 24-hour window is closed for this customer the send is refused; check [window status](/guides/whatsapp/24h-window#check-the-window-status-pre-flight) before you send, or fall back to a template.

## What a tap produces

WhatsApp does not send a "button tapped" webhook for CTA-URL buttons; the tap simply opens the link in the customer's browser. Orbit makes the tap observable another way: before the message leaves, your `url` is rewritten to a tracked short link, so the button opens your short-link address and the recipient is redirected on to the destination through `GET /l/:code`. The redirect records the click and fires a `short_link.click` webhook on your endpoint:

```json theme={null}
{
  "link_id": "link_abc123",
  "code": "Ab3kx9",
  "url": "https://shop.example.com/orders/10482/status",
  "click_id": "linkClick_def456",
  "message_id": "msg_wa_abc123",
  "campaign_id": null,
  "ip": "203.0.113.7",
  "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15",
  "referrer": null,
  "country": "NL",
  "clicked_at": "2026-10-10T09:14:52Z"
}
```

`message_id` ties the click to the send that carried the button; `url` is your original destination, not the short address. The click lands in the same per-link stats and campaign rollups as every other tracked link; see [Short links, landing pages, and the publish lifecycle](/concepts/short-links) for the model and [Short links with click tracking](/guides/short-links-and-click-tracking) for reading the numbers.

Two behaviors to plan around:

* Links you write into the free-form `body` are shortened and tracked the same way, so a tap on a body link and a tap on the button produce the same event.
* Link tracking is on by default. If your organization turns off the `whatsapp_auto_shorten_urls` setting, the button opens your URL directly and no click events fire.

The customer-visible host of the shortened link is your branded short-link domain when you have set one (**Settings → General → Branded short-link domain**), otherwise the platform default; see [Branded short-link domains](/concepts/short-links#branded-short-link-domains).

## URL and label rules

* **HTTPS only.** `url` must be an `https://` link; the API rejects anything else with a 422.
* **Label the destination honestly.** `display_text` is what the customer taps on. Keep it a short instruction that matches the page it opens ("Track order", "View invoice"), never a disguise for a different destination.
* **Track your own links for your own measurement.** Click tracking exists for attribution, so you can see which message drove the tap. Pointing a tracked button at a destination the customer would not expect from you violates Meta's content rules for WhatsApp and your own compliance posture; see [WhatsApp content policy](/compliance/whatsapp-content-policy).

## Worked example: order update with a tracked CTA

1. The customer messages you ("Where is my order?"), opening the 24-hour window.
2. You send the order update with a CTA-URL button:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/whatsapp/messages/send-interactive \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155552671",
    "body": "Hi Sam, order #10482 left our warehouse this morning. It should arrive Thursday.",
    "action": {
      "display_text": "Track order",
      "url": "https://shop.example.com/orders/10482/status"
    }
  }'
```

3. The response returns the message id with `"status": "sent"`, and your endpoint receives `message.sent` for it. The customer sees the text with a **Track order** button.
4. The customer taps the button. Their browser opens the short-link address, is redirected to `https://shop.example.com/orders/10482/status`, and your endpoint receives the `short_link.click` payload above with `message_id` matching the send.

No separate webhook arrives for the tap itself; the click event from the tracked redirect is the signal. If `short_link.click` never arrives for a send, check that link tracking is on for your organization and that your webhook subscription includes `short_link.click`.

## CTA-URL button vs. template URL button

| Situation | Use |
| - | - |
| The customer messaged you recently and you want per-tap attribution on the link | CTA-URL button |
| You are initiating the conversation, or the 24-hour window has lapsed | Template with a URL button |
| The message is business-initiated but the link differs per recipient | Template URL button with a per-recipient suffix variable: the button URL is fixed in the approved template except for a suffix you fill at send time |
| The label and destination both change per send, inside an open window | CTA-URL button |
| One reviewed message you reuse at scale, outside as well as inside the window | Template |

One rule decides it: an open window plus a link that varies per send points at a CTA-URL button; business-initiated or reusable points at a template.

## See also

* [Send and receive WhatsApp Business messages](/channels/whatsapp) — the channel overview
* [WhatsApp 24h freeform window](/guides/whatsapp/24h-window)
* [Short links, landing pages, and the publish lifecycle](/concepts/short-links)
* [Short links with click tracking](/guides/short-links-and-click-tracking)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.