# Payment links API

> Create, update and deactivate hosted payment links with the Anytime Capital Payments API: one per order or reusable, with metadata, and prefilled checkout.

Source: https://anytime-capital.com/docs/payment-links · Markdown: https://anytime-capital.com/docs/payment-links.md · All docs: https://anytime-capital.com/docs/llms-full.txt

A payment link is a hosted checkout page for one price. Share its `url` by text, email, DM or QR code, put it behind a button on your site, or create one per order from your backend and send the customer straight to it. Customers pay by card, Apple Pay or Google Pay, and by bank account or stablecoin where you have turned them on. Links made for invoices and subscription plans are managed with those and aren't listed here.

| Topic | Detail |
| --- | --- |
| Endpoints | [`POST /api/v1/payment-links`](#create-payment-link), [`GET /api/v1/payment-links`](#list-payment-links), [`GET /api/v1/payment-links/{id}`](#get-payment-link), [`POST /api/v1/payment-links/{id}`](#update-payment-link), [`POST /api/v1/payment-links/{id}/deactivate`](#deactivate-payment-link) |
| Key permissions | `payment_links:write`, `payment_links:read` |
| Samples | curl; Node.js 18+ with the built-in `fetch` (in an ES module); the [Node SDK](https://anytime-capital.com/docs/node-sdk.md) (preview: not on npm yet); Python with `requests`. |
| Every request can also answer | 401 `UNAUTHORIZED`, 401 `API_KEY_EXPIRED`, 403 `NOT_ENROLLED`, 403 `PERMISSION_DENIED`, 403 `IP_NOT_ALLOWED`, 429 `RATE_LIMITED`, 500 `INTERNAL_ERROR`. See [Error codes](https://anytime-capital.com/docs/error-codes.md). |

## The payment link object

```json
{
  "object": "payment_link",
  "livemode": true,
  "id": "pl_4kTz8QwN2xYb6RcD1mPa",
  "url": "https://anytime-capital.com/pay/business/pl_4kTz8QwN2xYb6RcD1mPa",
  "title": "Consulting — October",
  "description": "Two strategy sessions",
  "amountCents": 12500,
  "currency": "usd",
  "active": true,
  "singleUse": false,
  "shippingCents": 0,
  "collectShipping": false,
  "allowDiscountCodes": false,
  "successUrl": null,
  "confirmationMessage": "Thanks! We'll email your session times within a day.",
  "requireTermsConsent": false,
  "metadata": {
    "campaign": "fall-launch"
  },
  "items": [],
  "createdAt": "2026-10-01T09:30:00.000Z",
  "deactivatedAt": null,
  "allowQuantity": false,
  "maxQuantity": null,
  "customFields": [],
  "tipsEnabled": false,
  "payWhatYouWant": false,
  "minAmountCents": null
}
```

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | The type of object. Always `payment_link`. |
| `livemode` | boolean | False for test-mode data (an `ak_test_` key); true for live data. |
| `id` | string | `pl_` followed by 20 letters and digits. |
| `url` | string (uri) | The pay page. Share it, redirect to it or embed it. |
| `title` | string | What the customer pays for. |
| `description` | string or null | Shown under the title. |
| `amountCents` | integer | The price in cents. With `payWhatYouWant`, the suggested amount. |
| `currency` | string | usd. |
| `active` | boolean | Taking payments. |
| `singleUse` | boolean | Closes after its first payment. |
| `shippingCents` | integer | Flat shipping. Integer cents. |
| `collectShipping` | boolean | Asks for a shipping address. |
| `allowDiscountCodes` | boolean | Accepts discount codes. |
| `successUrl` | string or null | Where customers go after paying. A link has at most one of `successUrl` and `confirmationMessage`. |
| `requireTermsConsent` | boolean | Customers must agree to your terms. |
| `confirmationMessage` | string or null | Shown after paying. |
| `metadata` | object | Your own key/value data. |
| `items` | object[] | Catalog products, for links made in the dashboard from products. Empty for single-price links. |
| `createdAt` | string (date-time) | Created. |
| `deactivatedAt` | string (date-time) or null | Deactivated. |
| `allowQuantity` | boolean | Customers choose how many. |
| `maxQuantity` | integer or null | Most per payment. |
| `customFields` | object[] |  |
| `customFields[].id` | string | Your id. |
| `customFields[].label` | string | The question. |
| `customFields[].type` | string | `text`, `long_text`, `phone`, `dropdown`. |
| `customFields[].options` | string[] |  |
| `customFields[].required` | boolean | Must be answered. |
| `tipsEnabled` | boolean | Offers a tip. |
| `payWhatYouWant` | boolean | Customers choose the amount. |
| `minAmountCents` | integer or null | Smallest amount with payWhatYouWant. Integer cents. |

## Endpoints

### Create a payment link

`POST /api/v1/payment-links`

Permission: `payment_links:write`. Supports `Idempotency-Key`.

A hosted payment page for one price. Catalog products (`items`) can't be sent through the API yet: send `amountCents` for a single price. Links built from products in the dashboard still list and retrieve with their `items`.

**Headers**

| Header | Type | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | string | no | Recommended. A unique key such as a UUID: a retry with the same key within 24 hours gets the first response back instead of acting twice. See [Idempotency](https://anytime-capital.com/docs/idempotency.md). |

**Body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `title` | string | yes | What the customer is paying for. Up to 120 characters. |
| `amountCents` | integer | yes | The price in cents. With payWhatYouWant, the suggested amount. From 100 ($1.00) to 1,000,000 ($10,000.00). |
| `description` | string | no | Shown under the title. Up to 500 characters. |
| `singleUse` | boolean | no | Close the link after its first successful payment. Default false. |
| `shippingCents` | integer | no | Flat shipping added to each payment. Default 0. From 0 ($0.00) to 100,000 ($1,000.00). |
| `collectShipping` | boolean | no | Ask for a shipping address. Default false. |
| `allowDiscountCodes` | boolean | no | Let customers enter one of your discount codes. Default false. |
| `successUrl` | string (uri) | no | An https:// page on your site customers go to after paying. Not with confirmationMessage. Up to 500 characters. |
| `confirmationMessage` | string | no | Shown on the confirmation page after paying, instead of a successUrl. Up to 500 characters. |
| `requireTermsConsent` | boolean | no | Customers must tick “I agree to the terms” before paying. Needs a terms link in **Settings → Payments** (`409 TERMS_URL_REQUIRED` otherwise). Default `false`. |
| `metadata` | object | no | Up to 20 of your own key/value pairs, e.g. `{"orderId": "1042"}`: keys up to 40 letters, numbers, `-` and `_`; values text up to 500 characters. Copied onto each payment made on the link; customers never see it. |
| `allowQuantity` | boolean | no | Let customers choose how many. Default false. |
| `maxQuantity` | integer | no | With allowQuantity: the most per payment (default 10). From 1 to 99. |
| `tipsEnabled` | boolean | no | Offer a tip. Default false. |
| `payWhatYouWant` | boolean | no | Customers choose the amount. Not with quantity, tips or discount codes. Default false. |
| `minAmountCents` | integer | no | With payWhatYouWant: the smallest amount. From 100 ($1.00) to 1,000,000 ($10,000.00). |
| `customFields` | object[] | no | Up to 3 questions asked at checkout. Up to 3 items. |
| `customFields[].id` | string | yes | Your id for the question; answers are keyed by it. |
| `customFields[].label` | string | yes | Up to 60 characters. |
| `customFields[].type` | string | yes | One of `text`, `long_text`, `phone`, `dropdown`. |
| `customFields[].options` | string[] | no | Dropdown only: 2–10 different choices. Up to 10 items. |
| `customFields[].required` | boolean | no |  |

**Request (curl)**

```bash
curl -X POST https://anytime-capital.com/api/v1/payment-links \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: order-1042-link" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Consulting — October",
    "description": "Two strategy sessions",
    "amountCents": 12500,
    "singleUse": true,
    "metadata": {
      "orderId": "1042"
    }
  }'
```

**Request (Node.js)**

```javascript
const res = await fetch("https://anytime-capital.com/api/v1/payment-links", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "order-1042-link",
  },
  body: JSON.stringify({
    title: "Consulting — October",
    description: "Two strategy sessions",
    amountCents: 12500,
    singleUse: true,
    metadata: { orderId: "1042" },
  }),
});
const link = await res.json();
if (!res.ok) throw new Error(`${link.error.code}: ${link.error.message}`);
```

**Request (Node SDK)**

```typescript
import { AnytimeCapital } from "@anytimecapital/node";

const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });

const link = await client.paymentLinks.create(
  {
    title: "Consulting — October",
    description: "Two strategy sessions",
    amountCents: 12500,
    singleUse: true,
    metadata: { orderId: "1042" },
  },
  { idempotencyKey: "order-1042-link" },
);
```

**Request (Python)**

```python
import os

import requests

res = requests.post(
    "https://anytime-capital.com/api/v1/payment-links",
    headers={
        "Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}",
        "Idempotency-Key": "order-1042-link",
    },
    json={
        "title": "Consulting — October",
        "description": "Two strategy sessions",
        "amountCents": 12500,
        "singleUse": True,
        "metadata": {"orderId": "1042"},
    },
    timeout=30,
)
link = res.json()
if not res.ok:
    raise RuntimeError(f"{link['error']['code']}: {link['error']['message']}")
```

**Response** (201)

```json
{
  "object": "payment_link",
  "livemode": true,
  "id": "pl_4kTz8QwN2xYb6RcD1mPa",
  "url": "https://anytime-capital.com/pay/business/pl_4kTz8QwN2xYb6RcD1mPa",
  "title": "Consulting — October",
  "description": "Two strategy sessions",
  "amountCents": 12500,
  "currency": "usd",
  "active": true,
  "singleUse": true,
  "shippingCents": 0,
  "collectShipping": false,
  "allowDiscountCodes": false,
  "successUrl": null,
  "confirmationMessage": null,
  "requireTermsConsent": false,
  "metadata": {
    "orderId": "1042"
  },
  "items": [],
  "createdAt": "2026-10-01T09:30:00.000Z",
  "deactivatedAt": null,
  "allowQuantity": false,
  "maxQuantity": null,
  "customFields": [],
  "tipsEnabled": false,
  "payWhatYouWant": false,
  "minAmountCents": null
}
```

**Errors**

| Status | Code | When |
| --- | --- | --- |
| 400 | `INVALID_JSON` | The body isn't valid JSON, or couldn't be read. An empty body reads as `{}`. Send `Content-Type: application/json` and a JSON object. |
| 400 | `INVALID_INPUT` | A field, filter, `limit` or `cursor` is missing or invalid. The message starts with the field's name, as in `amountCents: …`, or reads `Invalid cursor.` Fix the named field. Don't retry the same request unchanged. |
| 400 | `INVALID_IDEMPOTENCY_KEY` | The `Idempotency-Key` header is empty, longer than 255 characters, or has characters other than printable ASCII. Use a UUID. See [Idempotency](https://anytime-capital.com/docs/idempotency.md). |
| 409 | `TERMS_URL_REQUIRED` | `requireTermsConsent` needs a link to your terms, and the business hasn't set one. Add your terms link in **Settings → Payments**, then retry. |
| 422 | `IDEMPOTENCY_KEY_REUSED` | The `Idempotency-Key` was used in the last 24 hours with a different body or endpoint. Use a new key for a new request; reuse a key only to retry the same request. |

### List payment links

`GET /api/v1/payment-links`

Permission: `payment_links:read`.

Payment links with their pay page url and buyer choices. Links behind invoices and plans aren't listed.

**Query**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `active` | boolean | no | true for live objects, false for deactivated or archived ones. |
| `limit` | integer | no | How many objects per page, 1–100. Default 25. See [Pagination](https://anytime-capital.com/docs/pagination.md). |
| `cursor` | string | no | The previous page's `nextCursor`, for the page after it. |

**Request (curl)**

```bash
curl "https://anytime-capital.com/api/v1/payment-links?active=true&limit=10" \
  -H "Authorization: Bearer $ANYTIME_API_KEY"
```

**Request (Node.js)**

```javascript
const res = await fetch("https://anytime-capital.com/api/v1/payment-links?active=true&limit=10", {
  headers: { Authorization: `Bearer ${process.env.ANYTIME_API_KEY}` },
});
const page = await res.json();
if (!res.ok) throw new Error(`${page.error.code}: ${page.error.message}`);
```

**Request (Node SDK)**

```typescript
import { AnytimeCapital } from "@anytimecapital/node";

const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });

const page = await client.paymentLinks.list({ active: true, limit: 10 });
```

**Request (Python)**

```python
import os

import requests

res = requests.get(
    "https://anytime-capital.com/api/v1/payment-links",
    headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
    params={"active": "true", "limit": "10"},
    timeout=30,
)
page = res.json()
if not res.ok:
    raise RuntimeError(f"{page['error']['code']}: {page['error']['message']}")
```

**Response** (200)

```json
{
  "object": "list",
  "data": [
    {
      "object": "payment_link",
      "livemode": true,
      "id": "pl_4kTz8QwN2xYb6RcD1mPa",
      "url": "https://anytime-capital.com/pay/business/pl_4kTz8QwN2xYb6RcD1mPa",
      "title": "Consulting — October",
      "description": "Two strategy sessions",
      "amountCents": 12500,
      "currency": "usd",
      "active": true,
      "singleUse": false,
      "shippingCents": 0,
      "collectShipping": false,
      "allowDiscountCodes": false,
      "successUrl": null,
      "confirmationMessage": "Thanks! We'll email your session times within a day.",
      "requireTermsConsent": false,
      "metadata": {
        "campaign": "fall-launch"
      },
      "items": [],
      "createdAt": "2026-10-01T09:30:00.000Z",
      "deactivatedAt": null,
      "allowQuantity": false,
      "maxQuantity": null,
      "customFields": [],
      "tipsEnabled": false,
      "payWhatYouWant": false,
      "minAmountCents": null
    }
  ],
  "hasMore": false,
  "nextCursor": null
}
```

**Errors**

| Status | Code | When |
| --- | --- | --- |
| 400 | `INVALID_INPUT` | A field, filter, `limit` or `cursor` is missing or invalid. The message starts with the field's name, as in `amountCents: …`, or reads `Invalid cursor.` Fix the named field. Don't retry the same request unchanged. |

### Get a payment link

`GET /api/v1/payment-links/{id}`

Permission: `payment_links:read`.

One payment link by id.

**Path**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | `pl_…` |

**Request (curl)**

```bash
curl https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa \
  -H "Authorization: Bearer $ANYTIME_API_KEY"
```

**Request (Node.js)**

```javascript
const res = await fetch("https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa", {
  headers: { Authorization: `Bearer ${process.env.ANYTIME_API_KEY}` },
});
const link = await res.json();
if (!res.ok) throw new Error(`${link.error.code}: ${link.error.message}`);
```

**Request (Node SDK)**

```typescript
import { AnytimeCapital } from "@anytimecapital/node";

const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });

const link = await client.paymentLinks.retrieve("pl_4kTz8QwN2xYb6RcD1mPa");
```

**Request (Python)**

```python
import os

import requests

res = requests.get(
    "https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa",
    headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
    timeout=30,
)
link = res.json()
if not res.ok:
    raise RuntimeError(f"{link['error']['code']}: {link['error']['message']}")
```

**Response** (200)

```json
{
  "object": "payment_link",
  "livemode": true,
  "id": "pl_4kTz8QwN2xYb6RcD1mPa",
  "url": "https://anytime-capital.com/pay/business/pl_4kTz8QwN2xYb6RcD1mPa",
  "title": "Consulting — October",
  "description": "Two strategy sessions",
  "amountCents": 12500,
  "currency": "usd",
  "active": true,
  "singleUse": false,
  "shippingCents": 0,
  "collectShipping": false,
  "allowDiscountCodes": false,
  "successUrl": null,
  "confirmationMessage": "Thanks! We'll email your session times within a day.",
  "requireTermsConsent": false,
  "metadata": {
    "campaign": "fall-launch"
  },
  "items": [],
  "createdAt": "2026-10-01T09:30:00.000Z",
  "deactivatedAt": null,
  "allowQuantity": false,
  "maxQuantity": null,
  "customFields": [],
  "tipsEnabled": false,
  "payWhatYouWant": false,
  "minAmountCents": null
}
```

**Errors**

| Status | Code | When |
| --- | --- | --- |
| 404 | `NOT_FOUND` | No such object on your business (an id from another business reads the same), or no such endpoint under `/api/v1`, which still answers in JSON. Check the id and the path. Ids are case-sensitive. |

### Update a payment link

`POST /api/v1/payment-links/{id}`

Permission: `payment_links:write`. Supports `Idempotency-Key`.

Send only what changes. The price is fixed: 400 NOT_EDITABLE names a field that can't change. Changes apply straight away; payments already made keep what they were charged. The price and how it is priced are fixed: `amountCents`, `items`, `payWhatYouWant`, `minAmountCents`, `shippingCents`, `allowDiscountCodes` and `singleUse` answer `400 NOT_EDITABLE`.

**Path**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | `pl_…` |

**Headers**

| Header | Type | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | string | no | Recommended. A unique key such as a UUID: a retry with the same key within 24 hours gets the first response back instead of acting twice. See [Idempotency](https://anytime-capital.com/docs/idempotency.md). |

**Body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `title` | string | no | Up to 120 characters. |
| `description` | string or null | no | New description; null removes it. Up to 500 characters. |
| `successUrl` | string (uri) or null | no | An https:// page to send customers to after paying; setting it clears confirmationMessage, null clears it. Up to 500 characters. |
| `confirmationMessage` | string or null | no | Message after paying; setting it clears successUrl, null clears it. Up to 500 characters. |
| `requireTermsConsent` | boolean | no |  |
| `metadata` | object or null | no | Replaces all of the link's metadata; null clears it. Up to 20 entries. |
| `customFields` | object[] | no | Up to 3 questions asked at checkout. Up to 3 items. |
| `customFields[].id` | string | yes | Your id for the question; answers are keyed by it. |
| `customFields[].label` | string | yes | Up to 60 characters. |
| `customFields[].type` | string | yes | One of `text`, `long_text`, `phone`, `dropdown`. |
| `customFields[].options` | string[] | no | Dropdown only: 2–10 different choices. Up to 10 items. |
| `customFields[].required` | boolean | no |  |
| `tipsEnabled` | boolean | no |  |
| `allowQuantity` | boolean | no |  |
| `maxQuantity` | integer or null | no | With allowQuantity: the most per payment. From 1 to 99. |
| `collectShipping` | boolean | no |  |

**Request (curl)**

```bash
curl -X POST https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: update-pl_4kTz8Q-title" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Consulting — November",
    "metadata": {
      "campaign": "winter"
    }
  }'
```

**Request (Node.js)**

```javascript
const res = await fetch("https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "update-pl_4kTz8Q-title",
  },
  body: JSON.stringify({ title: "Consulting — November", metadata: { campaign: "winter" } }),
});
const link = await res.json();
if (!res.ok) throw new Error(`${link.error.code}: ${link.error.message}`);
```

**Request (Node SDK)**

```typescript
import { AnytimeCapital } from "@anytimecapital/node";

const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });

const link = await client.paymentLinks.update(
  "pl_4kTz8QwN2xYb6RcD1mPa",
  { title: "Consulting — November", metadata: { campaign: "winter" } },
  { idempotencyKey: "update-pl_4kTz8Q-title" },
);
```

**Request (Python)**

```python
import os

import requests

res = requests.post(
    "https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa",
    headers={
        "Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}",
        "Idempotency-Key": "update-pl_4kTz8Q-title",
    },
    json={"title": "Consulting — November", "metadata": {"campaign": "winter"}},
    timeout=30,
)
link = res.json()
if not res.ok:
    raise RuntimeError(f"{link['error']['code']}: {link['error']['message']}")
```

**Response** (200)

```json
{
  "object": "payment_link",
  "livemode": true,
  "id": "pl_4kTz8QwN2xYb6RcD1mPa",
  "url": "https://anytime-capital.com/pay/business/pl_4kTz8QwN2xYb6RcD1mPa",
  "title": "Consulting — November",
  "description": "Two strategy sessions",
  "amountCents": 12500,
  "currency": "usd",
  "active": true,
  "singleUse": false,
  "shippingCents": 0,
  "collectShipping": false,
  "allowDiscountCodes": false,
  "successUrl": null,
  "confirmationMessage": "Thanks! We'll email your session times within a day.",
  "requireTermsConsent": false,
  "metadata": {
    "campaign": "winter"
  },
  "items": [],
  "createdAt": "2026-10-01T09:30:00.000Z",
  "deactivatedAt": null,
  "allowQuantity": false,
  "maxQuantity": null,
  "customFields": [],
  "tipsEnabled": false,
  "payWhatYouWant": false,
  "minAmountCents": null
}
```

**Errors**

| Status | Code | When |
| --- | --- | --- |
| 400 | `INVALID_JSON` | The body isn't valid JSON, or couldn't be read. An empty body reads as `{}`. Send `Content-Type: application/json` and a JSON object. |
| 400 | `INVALID_INPUT` | A field, filter, `limit` or `cursor` is missing or invalid. The message starts with the field's name, as in `amountCents: …`, or reads `Invalid cursor.` Fix the named field. Don't retry the same request unchanged. |
| 400 | `INVALID_IDEMPOTENCY_KEY` | The `Idempotency-Key` header is empty, longer than 255 characters, or has characters other than printable ASCII. Use a UUID. See [Idempotency](https://anytime-capital.com/docs/idempotency.md). |
| 400 | `NOT_EDITABLE` | The update names a field that is fixed once a link exists: `amountCents`, `items`, `payWhatYouWant`, `minAmountCents`, `shippingCents`, `allowDiscountCodes` or `singleUse`. The message names it. Create a new link at the new price and deactivate the old one. |
| 404 | `NOT_FOUND` | No such object on your business (an id from another business reads the same), or no such endpoint under `/api/v1`, which still answers in JSON. Check the id and the path. Ids are case-sensitive. |
| 409 | `TERMS_URL_REQUIRED` | `requireTermsConsent` needs a link to your terms, and the business hasn't set one. Add your terms link in **Settings → Payments**, then retry. |
| 422 | `IDEMPOTENCY_KEY_REUSED` | The `Idempotency-Key` was used in the last 24 hours with a different body or endpoint. Use a new key for a new request; reuse a key only to retry the same request. |

### Deactivate a payment link

`POST /api/v1/payment-links/{id}/deactivate`

Permission: `payment_links:write`. Supports `Idempotency-Key`.

Stop a link taking payments. Safe to repeat. Anyone who opens the link sees that it's closed. There's no API to turn it back on.

**Path**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | `pl_…` |

**Headers**

| Header | Type | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | string | no | Recommended. A unique key such as a UUID: a retry with the same key within 24 hours gets the first response back instead of acting twice. See [Idempotency](https://anytime-capital.com/docs/idempotency.md). |

**Request (curl)**

```bash
curl -X POST https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa/deactivate \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: deactivate-pl_4kTz8Q"
```

**Request (Node.js)**

```javascript
const res = await fetch("https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa/deactivate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
    "Idempotency-Key": "deactivate-pl_4kTz8Q",
  },
});
const link = await res.json();
if (!res.ok) throw new Error(`${link.error.code}: ${link.error.message}`);
```

**Request (Node SDK)**

```typescript
import { AnytimeCapital } from "@anytimecapital/node";

const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });

const link = await client.paymentLinks.deactivate(
  "pl_4kTz8QwN2xYb6RcD1mPa",
  { idempotencyKey: "deactivate-pl_4kTz8Q" },
);
```

**Request (Python)**

```python
import os

import requests

res = requests.post(
    "https://anytime-capital.com/api/v1/payment-links/pl_4kTz8QwN2xYb6RcD1mPa/deactivate",
    headers={
        "Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}",
        "Idempotency-Key": "deactivate-pl_4kTz8Q",
    },
    timeout=30,
)
link = res.json()
if not res.ok:
    raise RuntimeError(f"{link['error']['code']}: {link['error']['message']}")
```

**Response** (200)

```json
{
  "object": "payment_link",
  "livemode": true,
  "id": "pl_4kTz8QwN2xYb6RcD1mPa",
  "url": "https://anytime-capital.com/pay/business/pl_4kTz8QwN2xYb6RcD1mPa",
  "title": "Consulting — October",
  "description": "Two strategy sessions",
  "amountCents": 12500,
  "currency": "usd",
  "active": false,
  "singleUse": false,
  "shippingCents": 0,
  "collectShipping": false,
  "allowDiscountCodes": false,
  "successUrl": null,
  "confirmationMessage": "Thanks! We'll email your session times within a day.",
  "requireTermsConsent": false,
  "metadata": {
    "campaign": "fall-launch"
  },
  "items": [],
  "createdAt": "2026-10-01T09:30:00.000Z",
  "deactivatedAt": "2026-10-16T10:00:00.000Z",
  "allowQuantity": false,
  "maxQuantity": null,
  "customFields": [],
  "tipsEnabled": false,
  "payWhatYouWant": false,
  "minAmountCents": null
}
```

**Errors**

| Status | Code | When |
| --- | --- | --- |
| 400 | `INVALID_IDEMPOTENCY_KEY` | The `Idempotency-Key` header is empty, longer than 255 characters, or has characters other than printable ASCII. Use a UUID. See [Idempotency](https://anytime-capital.com/docs/idempotency.md). |
| 404 | `NOT_FOUND` | No such object on your business (an id from another business reads the same), or no such endpoint under `/api/v1`, which still answers in JSON. Check the id and the path. Ids are case-sensitive. |
| 422 | `IDEMPOTENCY_KEY_REUSED` | The `Idempotency-Key` was used in the last 24 hours with a different body or endpoint. Use a new key for a new request; reuse a key only to retry the same request. |

## Prefill checkout

Fill in details for your customer by adding parameters to a link's `url`. A value that isn't valid is ignored, never an error.

| Parameter | What it does |
| --- | --- |
| `prefilled_email` | The customer's email for their receipt. They can still change it. |
| `code` | One of your discount codes, applied when checkout opens, on links that accept codes. |
| `ref` | Your own reference for the payment, up to 200 letters, numbers, spaces and `_ . : / # @ + -`. Stored on the payment as `clientReference` and returned by the API and in webhooks. |

```text
https://anytime-capital.com/pay/business/pl_4kTz8QwN2xYb6RcD1mPa?prefilled_email=jordan%40example.com&code=FALL20&ref=order_1042
```

On your own website, the Pay button and the inline checkout take the same values as `data-email`, `data-code` and `data-ref`. See [Checkout](https://anytime-capital.com/docs/checkout.md).

## One link per order

For a cart or an order whose total you work out yourself, create a `singleUse` link per order with the order id in `metadata`, send the customer to its `url`, and mark the order paid when the `payment.succeeded` webhook arrives: `data.metadata` carries your order id, `data.paymentLinkId` the link id and `data.customer.email` the buyer. Use a stored Idempotency-Key so a retry never makes a second link. For a fixed price you sell again and again, one reusable link with `?ref=` per customer does the same job. The [Next.js guide](https://anytime-capital.com/docs/nextjs-checkout.md) builds this end to end.

- [Products](https://anytime-capital.com/docs/products.md): Your catalog: what links built in the dashboard sell.
- [Discount codes](https://anytime-capital.com/docs/discount-codes.md): Codes customers enter on links that allow them.
- [Checkout & website](https://anytime-capital.com/docs/checkout.md): The Pay button, inline checkout and your branding.

---

Anytime Capital is a fintech company, not a bank. Payment processing, banking and payout services are provided by Anytime Capital's licensed partners. Rates shown are for US card payments; international cards, currency conversion and disputes may carry additional fees shown in your dashboard before you accept a payment.
