# Payment Links

Create a hosted pay page for an amount — and optionally text or email it to the customer — from your server with an API key. The customer pays on the AuxCORE page; you never handle card data.

For a bill with line items, tax and PDF, use [Invoices](./invoices.md) instead — every invoice gets its own pay page.

---

## Create a payment link

```http
POST /api/v1/public/payment-links
```

`POST /api/v1/public/generate-url` is an older alias with the same behaviour. Send your **secret** key in `x-api-key`. Leave `merchantId` out: the key decides the merchant (ERP keys send `X-Merchant-ID`).

```bash
curl -X POST https://uat.auxcore.net/api/v1/public/payment-links \
  -H "x-api-key: YOUR_SECRET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "email_to_pay",
    "amount": 120.00,
    "description": "Consultation, October",
    "customerName": "Jane Doe",
    "customerEmail": "jane@example.com",
    "orderNumber": "INV-2026-104",
    "expiresInDays": 7
  }'
```

### Request fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | string | Yes | `text_to_pay` (sends an SMS), `email_to_pay` (sends an email) or `invoice` |
| `amount` | number | For fixed amounts | Amount to charge |
| `amountType` | string | No | `fixed` (default) or `open` — the customer enters the amount |
| `usage` | string | No | `one-time` (default) or `reusable` |
| `currency` | string | No | Default `USD` |
| `description` | string | No | Shown to the customer |
| `customerName` | string | No | |
| `customerEmail` | string | For `email_to_pay` | |
| `customerPhone` | string | For `text_to_pay` | Unless `sendSMS` is `false` |
| `sendSMS` | boolean | No | Default `true` for `text_to_pay`. Set `false` to create the link without texting it |
| `sendEmail` | boolean | No | Also email the link |
| `expiresInDays` | integer | No | Whole days from now, greater than 0 |
| `expiresAt` | string | No | Exact expiry (ISO 8601, in the future); wins over `expiresInDays` |
| `orderNumber` | string | No | Your reference |
| `allowPartialPayment` | boolean | No | Let the customer pay in parts. The merchant account must allow partial payments, otherwise `422 PARTIAL_PAYMENT_DISABLED` |
| `waiveConvenienceFee` | boolean | No | Do not charge the merchant's convenience fee on this link |
| `successRedirectUrl` | string | No | Where to send the customer after paying; only URLs on the merchant's own store domain are kept |

### Response

**201 Created** — the link, including:

```json
{
  "success": true,
  "data": {
    "linkId": "PL-1759915200000-3F9A1C2E",
    "type": "email_to_pay",
    "status": "sent",
    "amount": 120,
    "baseAmount": 120,
    "tipAmount": 0,
    "currency": "USD",
    "customerEmail": "jane@example.com",
    "orderNumber": "INV-2026-104",
    "expiresAt": "2026-10-15T09:14:00.000Z",
    "paymentUrl": "https://uat.auxcore.net/pay/PL-1759915200000-3F9A1C2E",
    "shortLink": "https://…"
  }
}
```

- Share `paymentUrl` (or `shortLink`, when the URL shortener returned one) with the customer.
- `status` is `sent` once the SMS or email went out, `pending` when nothing was sent.

### Errors

| Status | `error.code` | Cause |
|--------|--------------|-------|
| `400` | `VALIDATION_ERROR` | Missing `type` or amount, invalid `type`, missing email/phone for the chosen type, bad expiry |
| `403` | `MERCHANT_CLOSED`, `MERCHANT_RESTRICTED` | The merchant account cannot send new payment requests |
| `422` | `LIMIT_EXCEEDED` | `amount` is above the merchant's per-transaction limit |
| `422` | `PARTIAL_PAYMENT_DISABLED` | `allowPartialPayment` without the merchant-level setting |
| `502` | `NOTIFICATION_FAILED` | **The link was created**, but the SMS or email could not be delivered |

On `502 NOTIFICATION_FAILED` the response still carries the link in `data`, including `paymentUrl`. Do not create it again — that makes a second link for the same payment. Share `data.paymentUrl` another way.

---

## Link statuses

| Status | Meaning |
|--------|---------|
| `pending` | Created, not sent |
| `sent` | Delivered by SMS or email |
| `opened` | The customer opened the pay page |
| `partially_paid` | Part of the amount is paid (`allowPartialPayment`) |
| `paid` | Paid in full |
| `expired` | Past `expiresAt` |
| `cancelled` | Cancelled by the merchant |

---

## Confirm the payment

Payments made on the link are ordinary transactions. Subscribe to the transaction webhooks with [`POST /register-webhook`](../getting-started/webhooks.md#register-with-an-api-key-public-api) to hear about them as they happen.

The customer-facing routes under `/api/v1/public/payment-links/:linkId/*` (pay, ACH, Apple Pay, saved cards) are called by the hosted page itself and need no API key. They are listed in the [endpoint reference](../reference/endpoints.md#invoicing-payment-links-public-api).

---

## Next steps

- [Invoices →](./invoices.md)
- [Sending →](./sending.md)
- [Webhook Events →](../reference/webhook-events.md)
