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

# Create a Checkout Link

> Generate a shareable checkout URL and send it to your customer

Create a checkout link in one API call, then share the URL with your customer via any channel.

## Prerequisites

* A Quidkey merchant account with `client_id` and `client_secret`
* An active access token (see [Authentication](/api-reference/introduction#authentication))

## Step 1: Authenticate

Get an access token using your credentials.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://core.quidkey.com/api/v1/oauth2/token' \
    -H 'Content-Type: application/json' \
    -d '{
      "client_id": "your-client-id",
      "client_secret": "your-client-secret"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://core.quidkey.com/api/v1/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: 'your-client-id',
      client_secret: 'your-client-secret'
    })
  });

  const { data } = await response.json();
  const accessToken = data.access_token;
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://core.quidkey.com/api/v1/oauth2/token',
      json={
          'client_id': 'your-client-id',
          'client_secret': 'your-client-secret'
      }
  )

  access_token = response.json()['data']['access_token']
  ```
</CodeGroup>

## Step 2: Create the Checkout Link

Call `POST /api/v1/payment-links` with the payment details.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://core.quidkey.com/api/v1/payment-links' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
      "order": {
        "amount": 5000,
        "currency": "EUR",
        "payment_reference": "INV-2024-001"
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://core.quidkey.com/api/v1/payment-links', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      order: {
        amount: 5000,       // €50.00 in cents
        currency: 'EUR',
        payment_reference: 'INV-2024-001'
      }
    })
  });

  const { data } = await response.json();
  console.log('Payment link URL:', data.payment_link_url);
  console.log('Expires at:', data.expires_at);
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://core.quidkey.com/api/v1/payment-links',
      headers={'Authorization': f'Bearer {access_token}'},
      json={
          'order': {
              'amount': 5000,       # €50.00 in cents
              'currency': 'EUR',
              'payment_reference': 'INV-2024-001'
          }
      }
  )

  data = response.json()['data']
  print(f"Payment link URL: {data['payment_link_url']}")
  print(f"Expires at: {data['expires_at']}")
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "success": true,
  "data": {
    "link_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "payment_link_url": "https://core.quidkey.com/payment-link/a1b2c3d4e5f6...",
    "expires_at": "2024-04-07T12:00:00.000Z",
    "status": "active"
  }
}
```

<Check>
  Save the `payment_link_url`. This is the URL you'll share with your customer. The token in the URL is only returned once at creation time.
</Check>

## Step 3: Share the Link

Send the `payment_link_url` to your customer through any channel:

* **Email**: include in invoice emails or payment reminders
* **SMS**: send a short message with the link
* **Messaging apps**: WhatsApp, Telegram, or any chat platform
* **In-person**: display as text or generate a QR code

When the customer clicks the link, they'll see a Quidkey-hosted checkout page where they can complete the payment. See [Checkout Experience](/guides/payment-links/checkout-experience) for details.

## Request Body Reference

| Field                       | Type    | Required    | Description                                                                                    |
| --------------------------- | ------- | ----------- | ---------------------------------------------------------------------------------------------- |
| `order.amount`              | integer | Yes         | Amount in minor units (cents). `5000` = €50.00                                                 |
| `order.currency`            | string  | Yes         | ISO 4217 currency code (e.g., `EUR`, `GBP`)                                                    |
| `order.payment_reference`   | string  | Yes         | Up to 18 characters. Appears on the customer's bank statement.                                 |
| `order.order_id`            | string  | No          | Your internal order identifier for reconciliation                                              |
| `order.locale`              | string  | No          | BCP-47 locale tag (e.g., `en`, `pt`, `es`). Default: `en`                                      |
| `merchant_id`               | string  | No          | Required for Partner authentication. UUID of the target merchant.                              |
| `metadata`                  | object  | No          | Arbitrary key-value pairs to attach to the link                                                |
| `redirect_urls`             | object  | No          | Custom redirect URLs after payment. See [Redirect URLs](#redirect-urls).                       |
| `redirect_urls.success_url` | string  | Conditional | URL to redirect customer to after successful payment. Required if `redirect_urls` is provided. |
| `redirect_urls.failure_url` | string  | Conditional | URL to redirect customer to after failed payment. Required if `redirect_urls` is provided.     |

<Note>
  **Amount format:** Use minor units (cents). `1000` = €10.00, `5000` = €50.00. This is the same format used by Stripe and the Embedded Flow.
</Note>

## Redirect URLs

By default, after payment customers are redirected to a Quidkey-hosted thank you or failure page. To send customers back to your own site, provide custom redirect URLs at creation time.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://core.quidkey.com/api/v1/payment-links' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
      "order": {
        "amount": 5000,
        "currency": "EUR",
        "payment_reference": "INV-2024-001"
      },
      "redirect_urls": {
        "success_url": "https://yoursite.com/payment/success",
        "failure_url": "https://yoursite.com/payment/failure"
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://core.quidkey.com/api/v1/payment-links', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      order: {
        amount: 5000,
        currency: 'EUR',
        payment_reference: 'INV-2024-001'
      },
      redirect_urls: {
        success_url: 'https://yoursite.com/payment/success',
        failure_url: 'https://yoursite.com/payment/failure'
      }
    })
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://core.quidkey.com/api/v1/payment-links',
      headers={'Authorization': f'Bearer {access_token}'},
      json={
          'order': {
              'amount': 5000,
              'currency': 'EUR',
              'payment_reference': 'INV-2024-001'
          },
          'redirect_urls': {
              'success_url': 'https://yoursite.com/payment/success',
              'failure_url': 'https://yoursite.com/payment/failure'
          }
      }
  )
  ```
</CodeGroup>

When custom redirect URLs are provided, Quidkey appends query parameters so you can correlate the redirect on your side:

| Parameter           | Description                             |
| ------------------- | --------------------------------------- |
| `status`            | `success` or `failed`                   |
| `payment_reference` | The payment reference from the link     |
| `order_id`          | Your order ID (if provided at creation) |

For example, after a successful payment the customer would be redirected to:

```
https://yoursite.com/payment/success?status=success&payment_reference=INV-2024-001
```

<Warning>
  Both `success_url` and `failure_url` must be provided together. You cannot set only one. If `redirect_urls` is omitted, customers are redirected to Quidkey's default pages.
</Warning>

<Note>
  Webhooks still fire regardless of redirect URL configuration. Custom redirects only affect where the customer's browser is sent. Your backend still receives the webhook notification as normal. See [After Payment](/guides/payment-links/after-payment) for webhook details.
</Note>

## Link Types

By default, payment links are **single-use**: they transition to `USED` after a customer completes payment. You can also create **reusable** links that stay active for multiple payments.

<Warning>
  Link type configuration (`single_use` vs `reusable`) is currently set at the system level. Contact support if you need reusable links for your use case (e.g., donation pages, recurring invoices).
</Warning>

## Link Expiry

Payment links expire after **7 days** by default. The expiry timestamp is returned in the `expires_at` field of the creation response.

When a customer opens an expired link, the checkout page displays an expiry message instead of the payment form. See [Link Lifecycle](/guides/payment-links/overview#link-lifecycle) for all status transitions.

## Next Steps

<CardGroup cols={2}>
  <Card title="Checkout Experience" icon="browser" href="/guides/payment-links/checkout-experience">
    See what your customers see when they open a payment link
  </Card>

  <Card title="After Payment" icon="chart-line" href="/guides/payment-links/after-payment">
    Track status, handle webhooks, and manage your links
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/payment-links/create-a-payment-link">
    Full endpoint documentation with interactive playground
  </Card>

  <Card title="Overview" icon="link" href="/guides/payment-links/overview">
    Payment Links overview and lifecycle
  </Card>
</CardGroup>
