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

# Create a Payment Link

> Create a shareable Therius-hosted checkout URL for a one-time payment or a subscription. Single-use by default, or reusable with an optional cap.

`POST /payment-link` creates a hosted checkout page you can send to a payer by email, chat, or QR code — no SDK integration needed. The response contains the `url` to share.

## Link types

* **One-time, fixed amount** — you set `amount` (`amountMode: "fixed"`, the default). Use it for invoices and tickets.
* **One-time, payer-entered amount** — set `amountMode: "customer_entered"` and a `currency`. The payer types the amount, optionally bounded by `amountMin` and `amountMax` (minor units).
* **Subscription** — set `type: "subscription"` and a `subscriptionPlanId`. The plan sets the price. Omit `subscriptionPlanId` and the payer picks from your active plans. Don't send `amount` on subscription links.

## Single-use and reusable links

By default a link is single-use: it moves to `used` after the first **successful** payment. Failed attempts don't consume it, so the payer can retry.

Set `reusable: true` to accept many payments. Add `maxUses` to cap the number of successful payments; the link becomes `used` when the cap is reached. Without `maxUses`, a reusable link stays `active` until it expires or you cancel it. `maxUses` requires `reusable: true`, and subscription links can't be reusable.

## Environment and expiry

A link takes the environment of the key that created it: `prv_sandbox_` keys create sandbox links, `prv_production_` keys create production links. Links expire after 7 days unless you set `expiresInDays` (1–365) or `expiresAt` (`YYYY-MM-DD`, end of that day in UTC).

## Reference and return URL

`reference` is your own identifier (an invoice number, for example). It becomes the `orderCode` of the resulting payment. `returnUrl` must be an `https` URL (`http` is accepted in sandbox).

## Example

<RequestExample>
  ```bash cURL theme={"dark"}
  curl -X POST https://api.therius.io/v1/payment-link \
    -H "Authorization: Bearer prv_production_your_key_here" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{
      "merchantCode": "MERCHANT_001",
      "type": "one-time",
      "amount": { "currency": "BRL", "value": 15000, "exponent": 2 },
      "title": "Invoice 4821",
      "reference": "INV-4821",
      "customerEmail": "ana@example.com",
      "returnUrl": "https://shop.example.com/thanks",
      "expiresInDays": 14
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Created theme={"dark"}
  {
    "id": "5b1f0a52-3c0e-4a52-9d57-0c1d7e9f2a10",
    "url": "https://pay.therius.io/pay/Zk3x...",
    "type": "one-time",
    "status": "active",
    "amountMode": "fixed",
    "amount": { "currency": "BRL", "value": 15000, "exponent": 2 },
    "title": "Invoice 4821",
    "reference": "INV-4821",
    "customerEmail": "ana@example.com",
    "returnUrl": "https://shop.example.com/thanks",
    "saveCardEnabled": false,
    "reusable": false,
    "usesCount": 0,
    "environment": "production",
    "expiresAt": "2026-10-28T12:00:00Z",
    "createdAt": "2026-10-14T12:00:00Z"
  }
  ```
</ResponseExample>

<Note>
  Send an `Idempotency-Key` header so a retried request returns the original link instead of creating a second one. See [Idempotency](/idempotency).
</Note>


## OpenAPI

````yaml POST /payment-link
openapi: 3.1.0
info:
  title: Therius API
  description: REST API for payments, subscriptions, and billing plans.
  version: 1.0.0
servers:
  - url: https://api.therius.io/v1
    description: Production
  - url: https://api-sandbox.therius.io/v1
    description: Sandbox
security:
  - bearerAuth: []
paths:
  /payment-link:
    post:
      tags:
        - Payment Links
      summary: Create a payment link
      operationId: createPaymentLink
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - type
              properties:
                merchantCode:
                  type: string
                  description: >-
                    Your merchant account identifier. Required if the key maps
                    to more than one merchant account.
                type:
                  type: string
                  enum:
                    - one-time
                    - subscription
                amountMode:
                  type: string
                  enum:
                    - fixed
                    - customer_entered
                  default: fixed
                  description: One-time links only.
                amount:
                  allOf:
                    - $ref: '#/components/schemas/Amount'
                  description: >-
                    Required for one-time links. `value` is required when
                    `amountMode` is `fixed`; for `customer_entered` only
                    `currency` is needed. Not allowed on subscription links.
                amountMin:
                  type: integer
                  format: int64
                  description: >-
                    `customer_entered` only. Minimum amount the payer may enter,
                    minor units.
                amountMax:
                  type: integer
                  format: int64
                  description: >-
                    `customer_entered` only. Maximum amount the payer may enter,
                    minor units.
                subscriptionPlanId:
                  type: integer
                  format: int64
                  description: >-
                    Subscription links only. Omit to let the payer choose among
                    your active plans.
                checkoutConfigId:
                  type: string
                  format: uuid
                  description: Checkout Builder configuration to style the page.
                title:
                  type: string
                  maxLength: 255
                description:
                  type: string
                  maxLength: 2000
                reference:
                  type: string
                  maxLength: 128
                  description: >-
                    Your own reference (invoice number, PNR). It becomes the
                    `orderCode` of the resulting payment.
                customerEmail:
                  type: string
                customerName:
                  type: string
                returnUrl:
                  type: string
                  format: uri
                  description: >-
                    Where to send the payer after paying. Must be `https`
                    (sandbox also allows `http`).
                expiresInDays:
                  type: integer
                  minimum: 1
                  maximum: 365
                  default: 7
                expiresAt:
                  type: string
                  description: >-
                    Expiry date, `YYYY-MM-DD` (end of that day, UTC). Takes
                    precedence over `expiresInDays`.
                saveCardEnabled:
                  type: boolean
                  default: false
                reusable:
                  type: boolean
                  default: false
                  description: Accept many payments instead of one. One-time links only.
                maxUses:
                  type: integer
                  minimum: 1
                  description: >-
                    Cap on successful payments for a reusable link. Requires
                    `reusable: true`.
      responses:
        '201':
          description: Payment link created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentLink'
        '401':
          description: Missing or invalid API key
        '403':
          description: Production access is not enabled for this account
        '422':
          description: Invalid request
        '429':
          description: Rate limit exceeded
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      description: >-
        A UUID you generate per operation. Required in production. Retrying with
        the same key returns the original response.
      schema:
        type: string
        format: uuid
  schemas:
    Amount:
      type: object
      required:
        - currency
        - value
        - exponent
      properties:
        currency:
          type: string
          description: >-
            ISO 4217 currency code. On capture, refund and cancel it must match
            the currency of the original payment.
          example: USD
        value:
          type: integer
          description: >-
            Amount in minor units (cents, pence, etc.). `4999` = $49.99 for USD
            (exponent 2); `5000` = ¥5000 for JPY (exponent 0). On capture it
            must not exceed the authorized value; on refund the cumulative total
            across refunds must not exceed the captured amount.
          example: 4999
        exponent:
          type: integer
          description: >-
            Number of decimal places for the currency — `2` for USD/EUR, `0` for
            JPY. Determines where the decimal point sits in `value`.
          example: 2
    PaymentLink:
      type: object
      properties:
        id:
          type: string
          format: uuid
        url:
          type: string
          format: uri
          description: The hosted checkout URL to share with the payer.
        type:
          type: string
          enum:
            - one-time
            - subscription
        status:
          type: string
          enum:
            - active
            - used
            - expired
            - cancelled
          description: >-
            `used` once a single-use link takes its first successful payment, or
            a reusable link reaches `maxUses`.
        amountMode:
          type: string
          enum:
            - fixed
            - customer_entered
        amount:
          allOf:
            - $ref: '#/components/schemas/Amount'
          description: >-
            Absent on subscription links. For `customer_entered` links only
            `currency` and `exponent` are set.
        amountMin:
          type: integer
          format: int64
          description: Minimum payer-entered amount, minor units.
        amountMax:
          type: integer
          format: int64
          description: Maximum payer-entered amount, minor units.
        subscriptionPlanId:
          type: integer
          format: int64
        checkoutConfigId:
          type: string
          format: uuid
        title:
          type: string
        description:
          type: string
        reference:
          type: string
        customerEmail:
          type: string
        customerName:
          type: string
        returnUrl:
          type: string
          format: uri
        saveCardEnabled:
          type: boolean
        reusable:
          type: boolean
        maxUses:
          type: integer
        usesCount:
          type: integer
          description: Number of successful payments taken through this link.
        environment:
          type: string
          enum:
            - production
            - sandbox
        expiresAt:
          type: string
          format: date-time
        usedAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your secret API key: `Bearer prv_production_xxx` (production) or `Bearer
        prv_sandbox_xxx` (sandbox).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.