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

# Create a payment link

> Makes a payment link: an invoice for an amount, with no buyer on it. `payUrl` in the answer is the link. Whoever opens it gives their email address and pays, and the order is theirs. It is an invoice in every other way: it is listed with them, has a number and a PDF, and is cancelled if it is not paid in seven days.

A link is paid once unless `uses` says more. A link for more than one payment is never the order that is paid: each person who presses Pay on it is given an order and an invoice of their own, which names the link in `linkOf`, and the link's `uses` says how many times it has been paid and how many are left. The count is asked when Pay is pressed, so two people who press it for the last use at the same moment can both pay.

It may be paid with whichever payment methods the store has switched on when it is made. It counts toward the 2,000 unpaid invoices a store may hold at once. To email it to somebody, send it (Send an invoice) with their address.

With `currency`, the amount is in that currency and the buyer is charged exactly it, where the store may charge in it: its own currency always, and the others only while adaptive pricing is on. The order is then for the amount's worth in the store's currency at the rate of the moment.

With `items`, the link sells products in place of an amount: it is for what they cost, in the store's own currency, and whoever pays is sent them as any buyer is. `amount` and `description` are then left out. What it sells has to be in stock when the link is made, and again each time somebody pays through a link for several payments (`out_of_stock`).

It may be paid with every payment method the store has switched on, or with the ones named in `gateways`. It is open for seven days, or until `expiresAt`, or for `dueDays` days, up to 365.

Needs the `invoices.write` permission (Raise Invoices). It makes an order, and is counted against a budget of its own: 60 a minute for each key.



## OpenAPI

````yaml /api-reference/openapi.json post /stores/{storeId}/payment-links
openapi: 3.1.0
info:
  title: Shoply API
  version: '1'
  description: >-
    Everything a store's own server can do with a secret API key: its catalogue,
    orders, customers, marketing, finance and the rest of what the dashboard
    does. And the Customer API, which a buyer's own device asks with a token of
    theirs.
servers:
  - url: https://api.shoply.gg/v1
security:
  - apiKey: []
tags:
  - name: API key
  - name: Store
  - name: Domain
  - name: Payment methods
  - name: Analytics
  - name: Storefronts
  - name: Storefront code
  - name: Payment Routing
  - name: Custom payment methods
  - name: Products
  - name: Product pictures
  - name: Stock
  - name: Categories
  - name: Upsells
  - name: Subscriptions
  - name: Orders
  - name: Invoices
  - name: Reviews
  - name: Coupons
  - name: Coupon categories
  - name: Coupon pop-up
  - name: Sales
  - name: Blog
  - name: Search settings
  - name: Redirects
  - name: Sitemap
  - name: Cart Recovery
  - name: Email Marketing
  - name: Email Templates
  - name: Customers
  - name: Affiliates
  - name: Support Tickets
  - name: Blacklist
  - name: Fraud protection
  - name: Disputes
  - name: Finance
  - name: Tax
  - name: Expenses
  - name: Expense setup
  - name: API requests
  - name: Webhook endpoints
  - name: Webhook deliveries
  - name: Customer API
paths:
  /stores/{storeId}/payment-links:
    post:
      tags:
        - Invoices
      summary: Create a payment link
      description: >-
        Makes a payment link: an invoice for an amount, with no buyer on it.
        `payUrl` in the answer is the link. Whoever opens it gives their email
        address and pays, and the order is theirs. It is an invoice in every
        other way: it is listed with them, has a number and a PDF, and is
        cancelled if it is not paid in seven days.


        A link is paid once unless `uses` says more. A link for more than one
        payment is never the order that is paid: each person who presses Pay on
        it is given an order and an invoice of their own, which names the link
        in `linkOf`, and the link's `uses` says how many times it has been paid
        and how many are left. The count is asked when Pay is pressed, so two
        people who press it for the last use at the same moment can both pay.


        It may be paid with whichever payment methods the store has switched on
        when it is made. It counts toward the 2,000 unpaid invoices a store may
        hold at once. To email it to somebody, send it (Send an invoice) with
        their address.


        With `currency`, the amount is in that currency and the buyer is charged
        exactly it, where the store may charge in it: its own currency always,
        and the others only while adaptive pricing is on. The order is then for
        the amount's worth in the store's currency at the rate of the moment.


        With `items`, the link sells products in place of an amount: it is for
        what they cost, in the store's own currency, and whoever pays is sent
        them as any buyer is. `amount` and `description` are then left out. What
        it sells has to be in stock when the link is made, and again each time
        somebody pays through a link for several payments (`out_of_stock`).


        It may be paid with every payment method the store has switched on, or
        with the ones named in `gateways`. It is open for seven days, or until
        `expiresAt`, or for `dueDays` days, up to 365.


        Needs the `invoices.write` permission (Raise Invoices). It makes an
        order, and is counted against a budget of its own: 60 a minute for each
        key.
      operationId: invoices.link
      parameters:
        - name: storeId
          in: path
          required: true
          description: >-
            The store's ID. A key reaches the store it was made in: `GET /key`
            answers which.
          schema:
            type: string
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: number
                  description: >-
                    How much to ask for, above zero. Left out when `items` is
                    sent.
                  example: 100
                description:
                  type: string
                  description: >-
                    What it is for, up to 255 characters. The buyer sees it as
                    the order's one line. Left out, the line is called Payment.
                  example: Logo design deposit
                currency:
                  type: string
                  description: >-
                    The currency the amount is in and the buyer is charged in,
                    as a three-letter code. Left out, the store's own.
                  example: USD
                uses:
                  type: integer
                  description: 'How many times the link can be paid: 1 to 1,000.'
                  default: 1
                items:
                  type: array
                  description: >-
                    Products the link sells, in place of an amount: up to 50
                    lines.
                  items:
                    type: object
                    properties:
                      productId:
                        type: string
                        description: A product of the store.
                      variantId:
                        type: string
                        description: The variant of it being sold.
                      quantity:
                        type: integer
                        description: How many.
                        example: 1
                    required:
                      - productId
                      - variantId
                      - quantity
                gateways:
                  type: array
                  description: >-
                    The payment methods it may be paid with, by their names in
                    the payment methods list. Left out, every method the store
                    has switched on.
                  items:
                    type: string
                expiresAt:
                  type: string
                  description: >-
                    When it stops being payable, as a date and time, or a day
                    (`YYYY-MM-DD`) for the end of that day. At least an hour
                    from now and at most 365 days.
                  example: '2026-11-30T23:59:59Z'
                dueDays:
                  type: integer
                  description: 'In place of `expiresAt`: how many days it is open, 1 to 365.'
                  default: 7
      responses:
        '201':
          description: It worked.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    nullable: true
                  code:
                    nullable: true
                  data:
                    type: object
                    properties:
                      orderId:
                        type: string
                      number:
                        type: integer
                      label:
                        type: string
                      recipientName:
                        type: string
                      note:
                        type: string
                      gateways:
                        type: array
                        items:
                          type: string
                      dueAt:
                        type: string
                      overdue:
                        type: boolean
                      sentAt:
                        nullable: true
                      sendCount:
                        type: integer
                      dateCreated:
                        type: string
                      payUrl:
                        type: string
                      kind:
                        type: string
                      title:
                        type: string
                      uses:
                        nullable: true
                      linkOf:
                        type: string
                      charge:
                        nullable: true
                      email:
                        type: string
                      amount:
                        type: integer
                      currencyCode:
                        type: string
                      status:
                        type: string
                      itemCount:
                        type: integer
                      paidAt:
                        nullable: true
                  meta:
                    type: object
                    properties:
                      nextNumber:
                        type: string
                      currencyCode:
                        type: string
                      methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
                      sendWait:
                        type: integer
                      sendEvery:
                        type: integer
                      dueDays:
                        type: object
                        properties:
                          min:
                            type: integer
                          max:
                            type: integer
                          default:
                            type: integer
                      canEmail:
                        type: boolean
                      linkCurrencies:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            name:
                              type: string
              example:
                success: true
                message: null
                code: null
                data:
                  orderId: 479a5h0p1ya-150cadc3a07-1006663
                  number: 1
                  label: INV-0001
                  recipientName: ''
                  note: ''
                  gateways:
                    - stripe
                  dueAt: '2026-10-29T16:20:19Z'
                  overdue: false
                  sentAt: null
                  sendCount: 0
                  dateCreated: '2026-10-22T16:20:19Z'
                  payUrl: >-
                    http://localhost:3002/checkout/479a5h0p1ya-150cadc3a07-1006663
                  kind: link
                  title: Logo design deposit
                  uses: null
                  linkOf: ''
                  charge: null
                  email: ''
                  amount: 100
                  currencyCode: USD
                  status: pending
                  itemCount: 1
                  paidAt: null
                meta:
                  nextNumber: INV-0002
                  currencyCode: USD
                  methods:
                    - id: stripe
                      name: Credit/Debit Card (Stripe)
                  sendWait: 0
                  sendEvery: 300
                  dueDays:
                    min: 1
                    max: 30
                    default: 7
                  canEmail: true
                  linkCurrencies:
                    - code: USD
                      name: US dollar
        '401':
          $ref: '#/components/responses/NoKey'
        '403':
          $ref: '#/components/responses/NotAllowed'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/Refused'
        '429':
          $ref: '#/components/responses/TooMany'
      x-codeSamples:
        - lang: javascript
          label: Node.js
          source: |
            import Shoply from "@shoplygg/node";

            const shoply = new Shoply({ apiKey: process.env.SHOPLY_API_KEY });

            const result = await shoply.invoices.link();
        - lang: php
          label: PHP
          source: |
            <?php

            require 'vendor/autoload.php';

            $shoply = new Shoply\Client(['apiKey' => getenv('SHOPLY_API_KEY')]);

            $result = $shoply->invoices->link();
        - lang: python
          label: Python
          source: |
            import shoply

            client = shoply.Client()  # reads SHOPLY_API_KEY

            result = client.invoices.link()
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        A word of your own for this one change, up to 180 letters, digits, dots,
        dashes, underscores and colons. Sent again with the same key, the
        request is not carried out twice: the first answer comes back, with
        `Idempotent-Replay: true`.
      schema:
        type: string
  responses:
    NoKey:
      description: >-
        No API key was sent, or the one sent is not a live key:
        `api_key_required`, `invalid_api_key`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Refusal'
    NotAllowed:
      description: >-
        The key is real and may not do this: `missing_scope` (with
        `requiredScope`), `ip_not_allowed`, `account_unavailable`, or
        `dashboard_only` for something only a person in the dashboard may do.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Refusal'
    NotFound:
      description: >-
        There is no such thing in this store: `not_found`. A store that is not
        the key's own is answered the same way.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Refusal'
    Refused:
      description: >-
        The request was understood and not carried out. `validation_failed` says
        what is wrong with each field under `errors`; other codes are the
        route's own.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Refusal'
    TooMany:
      description: >-
        The key has used up its budget for now: `rate_limited`. `Retry-After`
        says how many seconds to wait.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Refusal'
  schemas:
    Refusal:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          description: What is wrong, in words for a person.
        code:
          type: string
          description: What is wrong, as a word that does not change.
        data:
          nullable: true
        errors:
          type: object
          description: >-
            For `validation_failed`: what is wrong with each field, by the
            field's name.
          additionalProperties:
            type: string
      required:
        - success
        - message
        - code
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        A secret API key, made under Developers in the dashboard:
        `Authorization: Bearer shoply_sk_...`

````

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