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

# QuickLink

> Connect a WhatsApp number with one hosted, short-lived link.

A QuickLink is a hosted Polymorfa page behind a short-lived URL. Whoever opens
the link scans a QR code or enters a pairing code on their phone, confirms the
connection, and the WhatsApp number becomes a session in your project.

Nothing is embedded in your application. The URL is the recipient's only
credential: it works only on the hosted pairing page, for one session, for 15
minutes by default (up to one hour), and it never grants message access.

## Create a QuickLink

You can create the same hosted link from three places.

<Tabs>
  <Tab title="Console">
    Open a project, go to **Numbers**, select **New number**, then choose
    **Send a QuickLink**. Copy the URL, share it, or show it as a QR code for a
    phone camera. Console shows the link moving from **Opened** to **Linked** to
    **Connected**, and adds the number to the list when the recipient confirms.

    To pair a phone that is with you, choose **Link a real number now** instead.
    Console creates a QuickLink and runs its hosted pairing flow inside the dialog.
  </Tab>

  <Tab title="API">
    Call `POST /messaging/quicklinks` from your backend with an team key that
    has `quicklink:manage`, or with a project token that carries the same scope.
    Keys created with the historical `widget:create` name keep working.

    ```bash theme={null}
    curl -X POST https://api.polymorfa.com/messaging/quicklinks \
      -H "Authorization: Bearer $POLYMORFA_ORGANIZATION_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "projectId": "PROJECT_ID",
        "methods": ["qr", "pairing"],
        "businessName": "Acme",
        "callbackUrl": "https://app.acme.example/whatsapp/connected"
      }'
    ```

    ```json theme={null}
    {
      "success": true,
      "data": {
        "id": "ql_0c1d8f2a3b4c5d6e7f80",
        "url": "https://polymorfa.com/connect/…",
        "session": "quicklink-5c9f9f171e29",
        "expiresAt": "2026-09-06T10:15:00.000Z"
      }
    }
    ```

    Send `url` to the person holding the phone. Do not log it.
  </Tab>

  <Tab title="Customers">
    Open a Customer and generate a pairing link. That link is durable and can
    be locked to an expected phone number. When the recipient opens it,
    Polymorfa issues a fresh QuickLink and assigns the verified number to the
    Customer. See [Customer pairing links](/guides/customers/pairing-links).
  </Tab>
</Tabs>

### Request fields

| Field              | Type                                 | Notes                                                                                                             |
| ------------------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `projectId`        | UUID                                 | Project that receives the number. Required for team keys that have more than one project.                         |
| `customerId`       | UUID                                 | Customer that owns the number when Customers is enabled for the project.                                          |
| `methods`          | `("qr" \| "pairing")[]`              | Methods offered on the page. Defaults to the saved settings, then to both.                                        |
| `businessName`     | string                               | Shown to the recipient; overrides the saved business name for this link. 1–120 characters.                        |
| `historySync`      | `"ask" \| "force_on" \| "force_off"` | Chat-history choice for this link; overrides the saved setting.                                                   |
| `callbackUrl`      | URL                                  | Exact HTTPS URL without credentials. Must match a saved callback URL.                                             |
| `theme`            | `"light" \| "dark" \| "system"`      | Appearance for this link; overrides the saved theme.                                                              |
| `accent`           | hex color                            | Six-digit color for this link; overrides the saved accent.                                                        |
| `prefillPhone`     | string                               | Reserves the link for one number and pre-fills the pairing-code method; 6–15 digits with an optional leading `+`. |
| `expiresInSeconds` | integer                              | Link lifetime, 300–3600 seconds. Defaults to 900.                                                                 |

Request values override the saved settings for the business name, theme,
accent, methods, and history sync. Omitted fields use the saved settings, then
the standard defaults. The hosted page also shows the saved headline,
description, success message, logo, and support, privacy, and terms links.

## What the recipient sees

The hosted page shows your business name, logo, and accent, and offers the
enabled methods:

* **Scan QR code** on a laptop or a second device. The page refreshes the code
  automatically until WhatsApp links.
* **Enter a code** on the phone itself. The recipient types their number,
  receives a one-time code, and enters it under **Link with phone number
  instead** in WhatsApp.

Phones open on the pairing-code method by default and laptops on the QR code;
a saved default method overrides that choice. The recipient can switch at any
time. After WhatsApp links, the page lists what your business receives,
offers the chat-history choice when your settings allow it, and asks for
confirmation. Cancelling before confirmation unlinks the device again.

## Track and finish the connection

Use either of these paths to learn the outcome.

**Callback URL.** When the QuickLink was created with `callbackUrl`, the page
returns the recipient there after confirmation or cancellation:

```text theme={null}
https://app.acme.example/whatsapp/connected?session=quicklink-5c9f9f171e29&status=connected&historySync=true
https://app.acme.example/whatsapp/connected?session=quicklink-5c9f9f171e29&status=cancelled
```

Treat the query string as a hint and confirm the session state with
`GET /messaging/sessions/{session}` or the session webhooks.

**Status polling.** `GET /messaging/quicklinks/{id}` returns the current status for
the caller that created the link:

| Status      | Meaning                                                                  |
| ----------- | ------------------------------------------------------------------------ |
| `pending`   | The link exists and has not been opened.                                 |
| `opened`    | The recipient opened the page; the session is starting.                  |
| `linked`    | WhatsApp reports the device linked; the recipient has not confirmed yet. |
| `connected` | The recipient confirmed. `phone` holds the connected number in E.164.    |
| `failed`    | The connection could not be completed. `errorCode` explains why.         |
| `cancelled` | The recipient or the creator cancelled the link.                         |

An expired link returns `404`.

## Cancel a QuickLink

`DELETE /messaging/quicklinks/{id}` invalidates a pending link and removes its
session. Connected links cannot be cancelled; remove the session instead.
Console-created links can be inspected and cancelled only by the member who
created them.

## Saved settings

In the Console, open team or project **Settings → QuickLink**. You can:

* enable or disable QuickLinks for the scope;
* choose the offered methods and which one opens first;
* write the headline, description, and success message the person reads;
* add a support link, and privacy and terms links for the confirmation step;
* upload a logo, reuse the team logo or the project icon, and set the accent,
  theme, corner shape, and footer;
* add allowed callback URLs and choose the chat-history behavior.

Project settings override the team defaults, and the preview shows the hosted
page as the recipient sees it while you type. Fields left empty keep the
standard wording.

Server automation reads the saved settings with `GET /platform/quicklink` and saves
changes with `PUT /platform/quicklink`. Send `projectId` to manage one project; omit
it to manage the team defaults. Reads return `null` when nothing has
been saved for that scope. Team keys need `quicklink:manage`; project
tokens use the same permission inside their project; Console callers use their
active membership.

`PUT /platform/quicklink` accepts any subset of these fields. Send `null` to clear an
optional text or link field.

| Field                 | Type      | Allowed values or limits                                                  |
| --------------------- | --------- | ------------------------------------------------------------------------- |
| `projectId`           | UUID      | Optional project-specific settings target                                 |
| `enabled`             | boolean   | Allows QuickLink creation for the scope                                   |
| `methods`             | array     | `qr`, `pairing`; 1–2 unique values                                        |
| `defaultMethod`       | string    | `qr`, `pairing`, or `null` to choose by device; must be an enabled method |
| `allowedRedirectUris` | URL array | Up to 50 exact HTTPS callback URLs without credentials                    |
| `businessName`        | string    | Up to 120 characters                                                      |
| `headline`            | string    | Up to 80 characters; replaces “Connect WhatsApp”                          |
| `description`         | string    | Up to 280 characters; the intro under the headline                        |
| `successMessage`      | string    | Up to 280 characters; shown after the number connects                     |
| `supportUrl`          | URL       | HTTPS help link shown under the pairing flow                              |
| `privacyUrl`          | URL       | HTTPS privacy policy link on the confirmation step                        |
| `termsUrl`            | URL       | HTTPS terms link on the confirmation step                                 |
| `accent`              | string    | Six-digit hex color such as `#6A3DE8`                                     |
| `theme`               | string    | `light`, `dark`, or `system`                                              |
| `hideWatermark`       | boolean   | Shows or hides the Polymorfa footer                                       |
| `shape`               | string    | `square`, `rounded`, `pill`, or `null`                                    |
| `radiusPx`            | number    | `0`–`999`, or `null`                                                      |
| `logoMode`            | string    | `none`, `custom`, `team`, or `project`                                    |
| `logoStorageId`       | string    | Storage id of an uploaded logo when `logoMode` is `custom`                |
| `historySync`         | string    | `ask`, `force_on`, or `force_off`                                         |

Responses include `logoUrl`, a short-lived read URL for the saved logo, or
`null`.

Send a JSON object no larger than 64 KiB in the request body. The API returns
`400` for malformed JSON, arrays or scalar bodies, unknown fields, unsupported
enum values, fields with the wrong type, and a `defaultMethod` that is not
enabled. An omitted body is an allowed no-op. The previous `/platform/widget` path
and its `modesAllowed`, `allowedOrigins`, and `colors` fields are gone.

## Security model

Team keys and project tokens use QuickLink to connect numbers. Direct QR and
pairing-code retrieval requires explicit access; standard credentials receive
`403`. Open the QuickLink URL to complete pairing.

* The hosted page never receives an team key, project token, or
  client token. The URL token authorizes only the pairing page routes,
  including the page logo.
* Every link expires after 15 minutes, or the lifetime you set up to one hour,
  and stops working once a number connects or the link is cancelled.
* Callback URLs are allowlisted per scope and matched exactly.
* Customer pairing links can require one expected phone number; a mismatch is
  rejected before ownership is assigned.
* Pairing page responses are never cached, and the page sends no referrer.

## Where to go next

<Columns cols={2}>
  <Card title="Sessions" icon="link" href="/console/sessions">
    Manage the connected number after it lands in your project.
  </Card>

  <Card title="Customer pairing links" icon="users" href="/guides/customers/pairing-links">
    Assign connected numbers to Customers with durable, revocable links.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/api/webhooks">
    Observe the resulting session lifecycle.
  </Card>

  <Card title="Client tokens" icon="key" href="/console/client-tokens">
    Browser-safe credentials for messaging, separate from pairing.
  </Card>
</Columns>
