Get started
This quickstart walks through the happy path from both sides of the product: creating a link in the Customer Hub, and creating one programmatically via the API. Pick the scenario that matches how you work.
- Customer Hub
- API
Create and manage payment links programmatically. You authenticate once, create a link with a minimal payload, share the returned URL with your customer, and confirm payment via the post-payment redirect, a webhook, or the checkout session.
The examples below use curl; adapt the request bodies to your language or HTTP client of choice.
All parameters are passed as HTTP request headers — not in the URL or as query parameters. There are no resource IDs in the URL path and no ?key=value query strings. Every value the API needs — including resource IDs, pagination cursors, and date filters — goes in a named header:
- Authentication and routing:
AccessToken,InterfaceVersion,InterfaceName,CompanyName— required on every request. - Resource selection:
PaymentLinkId(to target a specific link on retrieve, update, or session list) andCheckoutSessionId(to retrieve a specific session). - Pagination and filtering:
Limit,StartingAfterId,EndingBeforeId,DatetimeAfter,DatetimeBefore— on list endpoints.
Authenticate. Follow the Quick Start to exchange your Client GUID and Auth Token for an Access Token, then include
AccessToken,InterfaceVersion,InterfaceName, andCompanyNameheaders on every subsequent request.Create a payment link.
POSTto/paymentlinks/createwith apaymentLink.lineItemsarray. Each line item wraps aproductwith aname, acurrencyCode(ISO 4217 three-letter code), and anamountobject containingtotal(in major units —10= $10.00). For the happy path, a single line item with oneproductis enough.curl -X POST https://api.shift4.com/api/rest/v1/paymentlinks/create \ -H "AccessToken: YOUR_ACCESS_TOKEN" \ -H "InterfaceVersion: 1.0" \ -H "InterfaceName: YourApp" \ -H "CompanyName: YourCompany" \ -H "Content-Type: application/json" \ -d '{ "paymentLink": { "lineItems": [ { "product": { "name": "Order #1234", "currencyCode": "USD", "amount": { "total": 10 } } } ], "returnUrl": "https://yourapp.example.com/after-payment" } }'Set
returnUrl. The URL the customer is redirected to after payment (included in the request above). Shift4 appendsstatus=successandcheckout_session_id=<id>as query parameters on redirect. If you don't setreturnUrl, the default from your Checkout Settings is used.Share the returned
url. The response wraps a single result object containingpaymentLink.id,paymentLink.status(active), andpaymentLink.url— the hosted checkout URL onpay.shift4.com. Sendurlto the customer.{ "result": [ { "dateTime": "2026-05-13T09:18:23.283-07:00", "paymentLink": { "id": "link_8kdskX8DZ8FR6W3acYPXiyAN", "status": "active", "url": "https://pay.shift4.com/link_8kdskX8DZ8FR6W3acYPXiyAN", "returnUrl": "https://yourapp.example.com/after-payment", "lineItems": [ { "product": { "name": "Order #1234", "currencyCode": "USD", "amount": { "total": 10 } } } ] } } ] }Confirm the payment. When the customer completes checkout, they're redirected back to your
returnUrlwithstatus=successandcheckout_session_id=<id>appended. Use thecheckout_session_idto read the payment details from/checkoutsessions/retrieve(the session ID goes in theCheckoutSessionIdheader):curl https://api.shift4.com/api/rest/v1/checkoutsessions/retrieve \ -H "AccessToken: YOUR_ACCESS_TOKEN" \ -H "InterfaceVersion: 1.0" \ -H "InterfaceName: YourApp" \ -H "CompanyName: YourCompany" \ -H "CheckoutSessionId: chse_wMCUGVZgpf45fWHzKbYWMKmZ"The response contains the checkout session with
customFields(the answers the customer entered),staticFields(the read-only context you set on the link), andlastTransaction— the underlying transaction response.Listen for webhook events. For a server-side source of truth, configure your notification URL during merchant boarding and Shift4 will POST events to it. Two notifications cover the Payment Links flow:
checkoutsessions-notificationwithevent.type = checkout_session_completed— fires when a customer completes checkout via the payment link. Listen for this to confirm payment without polling.paymentlinks-notificationwithevent.typeinpayment_link_created,payment_link_updated— useful to sync payment-link state.
Example
checkout_session_completedpayload:{ "event": { "type": "checkout_session_completed" }, "dateTime": "2026-05-13T09:25:11.000Z", "paymentLink": { "id": "link_8kdskX8DZ8FR6W3acYPXiyAN" }, "checkoutSession": { "id": "chse_wMCUGVZgpf45fWHzKbYWMKmZ", "staticFields": { "Invoice number": "ORD-4421" }, "customFields": [ { "key": "shoe_size", "label": "Shoe size", "optional": false, "value": "10" } ], "lastTransaction": { /* sale response */ } } }For
paymentlinks-notificationthe body is the payment link object alongsideeventanddateTime(nocheckoutSession). Return a200to acknowledge receipt.
If you need…
- If you need custom fields / address collection → Create link
- If you need expiry / max successful payments / scheduling → Create link
- If you need email sending → Share
- If you need invoice/order reconciliation → Monitor and reconcile
- If you need full notification event details and payloads → Monitor and reconcile