Connect your checkout.
Open hosted checkout, create payment links, and read account records. Each endpoint below has its own authentication and amount format.
Quick Checkout
GET https://team.paywall.app/quickcheckout/acct_YOUR_ACCOUNTThis Stripe checkout flow supports connected accounts and enabled team-owned Stripe credentials. Its URL always uses the business’s connected account ID, including when team-owned credentials are used. The response is an HTML checkout page.
Replace the placeholder with the connected account ID assigned to your business. Numeric team IDs are not accepted. Opening the URL starts checkout; it does not create a completed payment.
URL parameters
amount- Fixed checkout amount in cents: 18000 means USD 180.00. Quick Checkout payment submission enforces a minimum of 5.00; for USD, use at least 500.
currency- Lowercase currency code, such as usd. Use a currency enabled for your account.
order_id- Optional external order reference forwarded to the success redirect and callback. It does not create an order record.
success_url- Optional success destination. Use a trusted HTTPS URL without an existing query or fragment: checkout appends payment and customer details. A redirect is not proof of payment.
shipping_amount- Optional shipping amount in decimal currency units: 5.00 adds USD 5.00.
tax_amount- Optional tax amount in cents: 500 adds USD 5.00.
Keep customer personal information and secret API keys out of URL parameters. This flow divides amount and tax_amount by 100, but adds shipping_amount directly. Use a confirmed two-decimal currency such as USD. For example, amount=18000, shipping_amount=5.00, and tax_amount=500 total USD 190.00.
cancel_url and sub_total do not control this checkout flow. Use the payment-link endpoint below when you need a stored link; its redirect fields have different behavior.
Create a payment link
POST https://team.paywall.app/linkcheckout/acct_YOUR_ACCOUNTSend JSON with Content-Type: application/json and Accept: application/json. This public endpoint does not require a bearer token. The path identifies the business by its connected Stripe account ID.
{
"amount": 18000,
"currency": "usd",
"order_id": "order_1048",
"success_url": "https://example.com/paid",
"cancel_url": "https://example.com/cancelled",
"name": "Example Customer",
"email": "customer@example.com"
}Required fields: amount, currency, success_url, cancel_url, name, and email. order_id and description are optional. Use an integer amount in cents: 18000 means USD 180.00. Decimal strings such as 180.00 are also converted to cents; avoid mixing formats.
A successful response is JSON with payment_link, id, transaction_id, order_id, currency, and other QR record fields. Its amount is in decimal currency units: 180 means USD 180.00. Send customers to the returned payment_link. Creating a link does not charge a customer or create an order.
success_url and cancel_url must be valid URLs, but are not saved on the link record and do not configure its redirects. Validation errors return 422, an unknown account returns 404, and an unexpected creation failure returns 500.
Retrieve a payment-link record
GET https://team.paywall.app/api/qr/by-order-id?transaction_id=YOUR_TRANSACTION_IDUse the transaction_id returned by link creation, despite the endpoint’s by-order-id name. This public JSON endpoint requires no bearer token. The response wraps the QR record in data; amount and amount_paid are in cents. A missing transaction_id returns 422 with Accept: application/json; no matching record returns 404.
Treat the response as a payment-link record, rather than independent proof that funds were received.
Authenticated account API
Protected /api routes use Laravel Sanctum bearer tokens and team context. Create a token for the intended team in the account portal’s API Tokens page. Keep it on your server and send Authorization: Bearer YOUR_TEAM_TOKEN and Accept: application/json. Your user must have permission to access the requested records.
curl 'https://team.paywall.app/api/payment-intents' \
--header 'Authorization: Bearer YOUR_TEAM_TOKEN' \
--header 'Accept: application/json'Read endpoints include GET /api/payment-intents, GET /api/charges, GET /api/customers, and GET /api/qrs. Lists are paginated. GET /api/payment-intents/RECORD_ID uses PayWall’s internal record ID, not Stripe’s pi_ identifier. These endpoints read stored records; they do not perform a fresh Stripe lookup.
A team-scoped token selects its team automatically; X-Team-ID does not switch that token to another team. Missing authentication returns 401, permission or team-token failures return 403, and unavailable records return 404.
Callbacks and webhooks
Quick Checkout accepts success_post_url for a legacy callback. It sends JSON, then a second form-encoded POST. This callback differs from the queued notifications configured through your team’s Purchase Post URL.
Queued notifications send JSON with X-Paywall-Event-Id and X-Paywall-Timestamp. With a Purchase Post Token configured, X-Paywall-Signature contains t=TIMESTAMP,v1=SIGNATURE. Verify HMAC-SHA256 of the timestamp, a period, and the exact raw request body using that token. Reject stale timestamps. Respond with 2xx after storing the event; handle duplicate delivery using the event ID. Delivery failures are retried, up to ten attempts, when the webhook queue worker is running.
Verify before fulfillment
Check payment status, amount, currency, account, and order against your trusted server records and the payment provider in the correct account context. Browser redirects, public QR records, and callbacks alone must not trigger delivery. For Stripe payments, use a server-side PaymentIntent retrieval or a signature-verified Stripe event. PayWall webhook signatures identify the notification sender; they do not replace payment verification. See Stripe webhook verification.
Use an explicitly enabled test environment to test successful, declined, canceled, and duplicate payments. Test card details must never be used in live mode.
Your workflow.
Our payment tools.
Go from a payment request to a connected customer experience. Open hosted checkout from your website. Verify the payment on your server before fulfilling an order.
curl --get 'https://team.paywall.app/quickcheckout/acct_YOUR_ACCOUNT' \
--data-urlencode 'amount=18000' \
--data-urlencode 'currency=usd' \
--data-urlencode 'order_id=order_1048'