# Crear link de pago único

Crea un link de pago único en dólares con la API de vexorpay.

> [!WARNING]
> El SDK `vexor` de npm (Stripe, MercadoPago, PayPal, Square, Talo) está **deprecado**: ya no se mantiene y no debe usarse. vexorpay es hoy una **API REST de links de pago en USD sobre Polar (Merchant of Record), sin SDK oficial**. Migración: <https://developers.vexorpay.com/docs/migracion-desde-el-sdk>

Fuente: <https://developers.whop.vexorpay.com/docs/api/create-payment-link>

El link es reutilizable: puedes compartirlo con varios clientes y, si quieres un cobro único por pedido, usar el [checkout por compra](/docs/api/checkout).

Para cobrar de forma periódica (suscripciones/planes), usa la [creación de link recurrente](/docs/api/create-recurring-payment-link).

## Canal de cobro (Polar)

El link se crea en **Polar**, el Merchant of Record: Polar cobra al comprador, calcula y
factura el impuesto y acredita la venta en tu saldo de Polar. Por eso
necesitas Polar conectado desde el dashboard (si no, la API
responde `400 account_not_connected`). La respuesta trae `checkoutUrl` apuntando al checkout de Polar.

- `image_file_id` se sube a Polar como imagen del producto (JPG, PNG, GIF o WebP de hasta 10 MB; si no, el link se crea sin foto).
- Una clave de prueba (`vxp_test_...`) no crea links en producción: responde `400 polar_test_key_not_supported`.
- Si la organización de Polar todavía no puede cobrar (falta verificación), responde `409 polar_not_ready`. Completa la verificación en Polar y vuelve a intentar.

Los links se editan con [`PATCH`](/docs/api/payment-links#actualizar-un-link), se
archivan con [`DELETE`](/docs/api/payment-links#eliminar-un-link) y se cobran con
[`checkout`](/docs/api/checkout), con las reglas que se explican en cada página.

## Request

`POST /api/v1/payment-links`

### Headers

| Header | Valor |
| --- | --- |
| `Authorization` | `Bearer vxp_live_tu_clave` |
| `Content-Type` | `application/json` |
| `Idempotency-Key` | opcional — para repetir sin duplicar |
| `Vexor-Account` | opcional — id del usuario conectado, para crear el link en su nombre ([cuentas conectadas](/docs/api/connected-accounts)) |

### Body

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `amount` | number | **sí** | Monto en dólares. Mínimo USD 4. |
| `title` | string | no | Título del cobro. |
| `description` | string | no | Descripción del cobro. |
| `image_file_id` | string | no | Foto del producto. Debe ser un archivo tuyo (subido desde el dashboard). Se sube a Polar y se muestra en el checkout. |
| `reference` | string | no | Referencia tuya (n° de orden, SKU…). Se incluye en las ventas y los webhooks para reconciliar. |
| `metadata` | object | no | Pares clave/valor libres que viajan con el link. |
| `type` | string | no | `one_time` (default). Ver [link recurrente](/docs/api/create-recurring-payment-link). |

### Ejemplo

**curl**

```bash
curl https://api.vexorpay.com/api/v1/payment-links \
  -X POST \
  -H "Authorization: Bearer vxp_live_tu_clave" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 19,
    "title": "Ebook UX en 30 días",
    "reference": "CATALOGO-UX",
    "metadata": { "categoria": "ebook" }
  }'
```

**Node.js**

```js
const res = await fetch('https://api.vexorpay.com/api/v1/payment-links', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer vxp_live_tu_clave',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 19,
    title: 'Ebook UX en 30 días',
    reference: 'CATALOGO-UX',
    metadata: { categoria: 'ebook' },
  }),
})

const data = await res.json()
```

**PHP**

```php
<?php

$client = curl_init('https://api.vexorpay.com/api/v1/payment-links');
curl_setopt_array($client, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer vxp_live_tu_clave',
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'amount' => 19,
    'title' => 'Ebook UX en 30 días',
    'reference' => 'CATALOGO-UX',
    'metadata' => ['categoria' => 'ebook'],
  ]),
]);

$data = json_decode(curl_exec($client), true);
```

**Python**

```python

response = requests.post(
    'https://api.vexorpay.com/api/v1/payment-links',
    headers={
        'Authorization': 'Bearer vxp_live_tu_clave',
        'Content-Type': 'application/json',
    },
    json={
        'amount': 19,
        'title': 'Ebook UX en 30 días',
        'reference': 'CATALOGO-UX',
        'metadata': {'categoria': 'ebook'},
    },
)
data = response.json()
```

**Go**

```go
body, _ := json.Marshal(map[string]any{
    "amount":    19,
    "title":     "Ebook UX en 30 días",
    "reference": "CATALOGO-UX",
    "metadata":  map[string]any{"categoria": "ebook"},
})

req, _ := http.NewRequest("POST", "https://api.vexorpay.com/api/v1/payment-links", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer vxp_live_tu_clave")
req.Header.Set("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
```

### Respuesta exitosa

`201 Created`

```json
{
  "id": "66f1c1e2c8a4b0d1f2e3a4b5",
  "amountCents": 1900,
  "currency": "usd",
  "title": "Ebook UX en 30 días",
  "description": null,
  "image": null,
  "reference": "CATALOGO-UX",
  "metadata": { "categoria": "ebook" },
  "status": "active",
  "slug": "a1b2c3d4e5",
  "sandbox": false,
  "url": "https://www.vexorpay.com/p/a1b2c3d4e5",
  "checkoutUrl": "https://buy.polar.sh/polar_cl_...",
  "type": "one_time",
  "createdAt": "2026-01-02T12:00:00.000Z",
  "updatedAt": "2026-01-02T12:00:00.000Z"
}
```

`checkoutUrl` es el checkout de Polar del link: compártelo o redirige al comprador ahí. Para una sesión de checkout por compra (con `reference`, email precargado o un plan puntual) usa [`POST /v1/payment-links/{id}/checkout`](/docs/api/checkout).

## Errores

| Error | HTTP | Causa |
| --- | --- | --- |
| `unauthorized` | 401 | Falta el header `Authorization`. |
| `invalid_key` | 401 | La API key es inválida o fue revocada. |
| `invalid_amount` | 400 | El monto es menor a USD 4 o no es un número válido. |
| `account_not_connected` | 400 | No conectaste Polar (o la conexión se revocó): conéctalo desde el dashboard. |
| `polar_test_key_not_supported` | 400 | Una clave de prueba (`vxp_test_...`) no puede crear links en producción. Usa una clave de producción. |
| `polar_not_ready` | 409 | La organización de Polar todavía no puede cobrar: completá su verificación en Polar y reintentá. |
| `idempotency_conflict` | 409 | La `Idempotency-Key` ya se usó con un body distinto. |
| `polar_provisioning_failed` | 500 | Polar rechazó la creación del link. No quedó nada publicado: reintentá. |
| `rate_limited` | 429 | Superaste el límite de 100 requests por minuto. |
