Skip to content
Get started

Payment Requests

Request a payment from a recipient over iMessage. You create a payment request, send its checkout_url to the recipient, and they pay with Apple Pay or card. Funds settle directly to your own Stripe account — Linq never holds the money.

How it works

  1. Create a payment request with an amount and currency. You get back a checkout_url and a status of requested.
  2. Send the checkout_url to the recipient as a link message part so it arrives as a tappable card (see Sending the link below).
  3. The recipient pays on the hosted checkout (Apple Pay App Clip on a supported iPhone, web checkout everywhere else).
  4. You receive a payment.succeeded webhook and the request’s status becomes succeeded. Requests you don’t collect eventually expire.

Connected accounts (Stripe Standard, direct charges)

Agent Pay runs on Stripe Connect Standard accounts using direct charges: the charge is created on your connected account and you are the merchant of record. That means the money, the payout schedule, the customer relationship, and the compliance surface are all yours — Linq orchestrates the request and the checkout but is never in the funds flow.

Refunds, disputes, and chargebacks are handled by you, in your own Stripe Dashboard. Because charges settle directly to your account, Linq has no custody of the funds and cannot issue refunds or contest disputes on your behalf — and there is no refund/dispute endpoint in this API by design. Use the Stripe Dashboard (or the Stripe API on your own account) for the money lifecycle after a payment succeeds.

Getting set up

Open Agent Pay in your Linq dashboard (https://zero.linqapp.com/organization/payments), click Connect Stripe, and complete Stripe’s onboarding (business details + a bank account). When your account reaches charges_enabled, request creation unlocks; until you connect Stripe, POST /v3/payment_requests returns 403. You can keep collecting even while Stripe finishes background verification.

Deliver the checkout_url as a link message part via POST /v3/chats/{chatId}/messages — it renders as a rich card with your branding (title, amount, image) instead of a bare URL, which converts far better. A link part must be the only part in the message. See Rich Link Previews.

On a supported iPhone the link opens an Apple Pay App Clip — a native, no-install checkout sheet. Everywhere else (Android, desktop, iPhones without the App Clip yet) the same URL opens the web checkout, so the link always works. The App Clip experience for your payment links is registered automatically by Linq and refreshed whenever you update your Agent Pay branding; a newly registered experience can take up to ~24 hours to activate on Apple’s side, during which links open the web checkout.

Webhooks

Subscribe to payment lifecycle events to reconcile server-side rather than polling: payment.succeeded, payment.canceled, and payment.expired. Each event carries the payment request id, amount, currency, and your metadata. See Webhooks.

Create a payment request
POST/v3/payment_requests
Get a payment request
GET/v3/payment_requests/{paymentRequestId}
List payment requests
GET/v3/payment_requests
Cancel a payment request
POST/v3/payment_requests/{paymentRequestId}/cancel
ModelsExpand Collapse
PaymentRequest object { id, amount, checkout_url, 9 more }
id: string

Unique identifier of the payment request.

formatuuid
amount: number

Amount in the currency’s minor units.

formatint64
checkout_url: string

URL the recipient opens to pay: https://zero.linqapp.com/pay/{slug}?session=..., where {slug} is your partner checkout slug.

created_at: string
formatdate-time
currency: string
object: string
status: "requested" or "succeeded" or "canceled" or "expired"

Lifecycle status of the payment request.

One of the following:
"requested"
"succeeded"
"canceled"
"expired"
description: optional string
expires_at: optional string

When an unpaid request auto-expires.

formatdate-time
metadata: optional map[string]
updated_at: optional string
formatdate-time
PaymentRequestListResponse object { data, has_more, object }
data: array of PaymentRequest { id, amount, checkout_url, 9 more }
id: string

Unique identifier of the payment request.

formatuuid
amount: number

Amount in the currency’s minor units.

formatint64
checkout_url: string

URL the recipient opens to pay: https://zero.linqapp.com/pay/{slug}?session=..., where {slug} is your partner checkout slug.

created_at: string
formatdate-time
currency: string
object: string
status: "requested" or "succeeded" or "canceled" or "expired"

Lifecycle status of the payment request.

One of the following:
"requested"
"succeeded"
"canceled"
"expired"
description: optional string
expires_at: optional string

When an unpaid request auto-expires.

formatdate-time
metadata: optional map[string]
updated_at: optional string
formatdate-time
has_more: boolean

Whether more results exist beyond this page.

object: "list"