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

# Dynamic Links

> Payment links where the buyer enters the amount.

# Dynamic Links

A dynamic link is a payment link without a fixed amount. The buyer enters the amount they wish to pay before selecting a payment method.

## When to use dynamic links

* **Donations**: Let supporters choose their contribution amount.
* **Tips or gratuities**: Let customers decide how much to tip.
* **Flexible invoicing**: When the amount varies per transaction.
* **Pay-what-you-want**: For products or services with flexible pricing.

## Creating a dynamic link

Omit the `amount` field from the request:

```bash theme={null}
curl -X POST "https://api.wava.co/v1/links" \
  -H "merchant-key: YOUR_MERCHANT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Donation to Foundation XYZ",
    "currency": "COP",
    "redirect_link": "https://mysite.com/thanks"
  }'
```

The response includes `expires_at` (`null` when no TTL is set):

```json theme={null}
{
  "data": {
    "link": "https://checkout.wava.co/link/xyz789abc012",
    "hash": "xyz789abc012",
    "expires_at": null
  }
}
```

When the buyer opens the link, they see an amount input field before proceeding to payment method selection.

<Note>
  The only difference between a regular payment link and a dynamic link is whether you include the `amount` field in the request. Everything else — response format, webhooks, redirects, TTL — works the same way.
</Note>

## Link expiration

Dynamic links support the same `ttl_minutes` parameter as fixed-amount links. See the [Payment Links overview](/documentation/links/overview) for full details on expiration behavior, including in-flight payment handling.

## Reading link metadata

`GET /v1/links/public/:hash` returns the link's current state, including expiration:

```json theme={null}
{
  "data": {
    "amount": null,
    "currency": "COP",
    "description": "Donation to Foundation XYZ",
    "collect_shopper_data": false,
    "expires_at": "2026-06-18T14:30:00.000Z",
    "expired": false
  }
}
```

| Field        | Description                                                       |
| ------------ | ----------------------------------------------------------------- |
| `expires_at` | UTC expiration timestamp, or `null`                               |
| `expired`    | `true` if the link has passed its `expires_at`; `false` otherwise |

If the link is inactive or expired, the endpoint returns `410` with `PAYMENT_LINK_INACTIVE` or `PAYMENT_LINK_EXPIRED` respectively.

## Collecting shopper contact data

By default, dynamic links only ask buyers for the information their payment method requires (phone number for Nequi, national ID for Daviplata, etc.). If you need the buyer's name, email, or phone number to identify the payer in your backoffice, use the `user_data_required` flag (or the legacy `collect_shopper_data` alias):

```bash theme={null}
curl -X POST "https://api.wava.co/v1/links" \
  -H "merchant-key: YOUR_MERCHANT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Donation to Foundation XYZ",
    "currency": "COP",
    "redirect_link": "https://foundation.org/thanks",
    "user_data_required": true
  }'
```

When this flag is `true`, the checkout page shows a contact form (first name, last name, email, phone) before the buyer proceeds to payment method selection. The submitted data is stored with the order.

### Behavior

| `user_data_required`        | What the buyer sees                       |
| --------------------------- | ----------------------------------------- |
| `false`                     | Goes straight to payment method selection |
| `true`                      | Contact form → payment method selection   |
| omitted (dynamic link)      | `false` by default                        |
| omitted (fixed-amount link) | `true` by default                         |

### Field reference

| Field                  | Type    | Notes                                                                                              |
| ---------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `user_data_required`   | boolean | Works on **any** link type (dynamic or fixed-amount). Explicit value overrides the type default    |
| `collect_shopper_data` | boolean | Legacy alias — only meaningful for dynamic links. Prefer `user_data_required` for new integrations |

### Rules

* `user_data_required` is valid on both dynamic and fixed-amount links.
* If omitted: dynamic links default to `false`; fixed-amount links default to `true`.
* The resolved value is returned by `GET /v1/links/public/:hash` as `user_data_required` (boolean), so the checkout never needs to infer the default.

<Tip>
  Use `collect_shopper_data` when you need to reconcile payments against a known buyer (e.g., donations, event registrations) and your payment gateway alone doesn't provide enough buyer identification.
</Tip>
