Hosted Checkout
Accept payments with a pre-built, secure payment page
Checkout URL: https://pay.wyrr.com/checkout?session_id={ id } | API: POST /api/v1/checkout/sessions
How It Works
Create Session
Your server creates a checkout session via API
Redirect Customer
Customer is sent to the hosted checkout page
Customer Pays
Customer selects method and completes payment
Verify Payment
Your server verifies the payment status via API
Quick Start
Create a checkout session from your server, then redirect the customer to the returned URL.
curl -X POST https://api.wyrr.com/api/v1/checkout/sessions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_12345" \
-d '{
"merchantId": "your-merchant-id",
"amount": 99.99,
"currency": "USD",
"successUrl": "https://yoursite.com/success",
"cancelUrl": "https://yoursite.com/cancel",
"businessName": "Your Store",
"description": "Order #12345",
"paymentMethodTypes": ["card", "bank_transfer"]
}'Response
{
"success": true,
"sessionId": "59a943bc-46a2-4457-a0ac-7bf5d22416b4",
"checkoutUrl": "https://pay.wyrr.com/checkout?session_id=59a943bc-46a2-4457-a0ac-7bf5d22416b4",
"status": "open",
"expiresAt": "2024-01-02T10:00:00Z"
}/api/v1/checkout/sessionsCreate Session Parameters
| Name | Type | Required | Description |
|---|---|---|---|
merchantIdbody | string | Required | Your merchant account identifier |
amountbody | number | Required | Payment amount in major currency units (e.g. 99.99) |
currencybody | string | Required | ISO 4217 currency code (e.g. USD, EUR, GBP, NGN) |
successUrlbody | string | Required | URL to redirect customer after successful payment |
cancelUrlbody | string | Required | URL to redirect customer if they cancel checkout |
businessNamebody | string | Optional | Display name shown on the checkout page |
descriptionbody | string | Optional | Description of the purchase shown to customer |
customerEmailbody | string | Optional | Pre-fill the customer email on checkout |
paymentMethodTypesbody | string[] | Optional | Allowed payment methods: "card", "bank_transfer", "stablecoin". Defaults to all enabled methods. |
logoUrlbody | string | Optional | URL to your logo image (recommended 256x256 PNG) |
brandColorbody | string | Optional | Hex color for primary button and accents (e.g. #4F46E5) |
modebody | string | Optional | "payment" (one-time) or "subscription" (recurring). Defaults to "payment". |
expiresInbody | number | Optional | Session expiry in seconds. Default 1800 (30 minutes), max 86400 (24 hours). |
metadatabody | object | Optional | Key-value pairs for your own reference. Returned in webhooks and API responses. |
Idempotency-Keyheader | string | Optional | Unique key to prevent duplicate session creation. Recommended for all requests. |
Redirect the Customer
After creating a session, redirect the customer to the checkout page. You can use the checkoutUrl from the response or construct the URL yourself.
// Option 1: Use the checkoutUrl from the response
window.location.href = session.checkoutUrl;
// Option 2: Construct the URL manually
window.location.href = "https://pay.wyrr.com/checkout?session_id=" + session.sessionId;Handle Redirects
Success Redirect
When payment succeeds, the customer is redirected to your success URL with the session ID appended:
https://yoursite.com/success?session_id=59a943bc-...Cancel Redirect
If the customer abandons checkout, they are redirected to your cancel URL:
https://yoursite.com/cancelImportant: Never trust the redirect alone to confirm a payment. A customer could navigate directly to your success URL without paying. Always verify the payment server-side using the verification endpoint below.
Verify Payment
After the customer is redirected back, verify the payment status from your server. Extract the session_id from the query string and call the verify endpoint.
/api/v1/checkout/sessions/{sessionId}/verify1// Server-side verification (Node.js / Express)
2app.get('/success', async (req, res) => {
3 const sessionId = req.query.session_id;
4
5 const response = await fetch(
6 `https://api.wyrr.com/api/v1/checkout/sessions/${sessionId}/verify`,
7 {
8 headers: {
9 'Authorization': 'Bearer sk_test_...'
10 }
11 }
12 );
13
14 const result = await response.json();
15
16 if (result.status === 'complete') {
17 // Payment confirmed — fulfill the order
18 await fulfillOrder(result.paymentId, result.amount);
19 } else {
20 // Payment not complete — show error
21 res.redirect('/payment-failed');
22 }
23});
Verification Response
{
"sessionId": "59a943bc-46a2-4457-a0ac-7bf5d22416b4",
"status": "complete",
"paymentId": "pay_8f3a1b2c4d5e6f7a",
"amount": 99.99,
"currency": "USD",
"paymentMethod": "card",
"customerEmail": "customer@example.com",
"metadata": {
"orderId": "12345"
}
}| Status | Description |
|---|---|
open | Session created, customer has not yet completed payment |
complete | Payment succeeded. Safe to fulfill the order. |
expired | Session expired before payment was completed |
cancelled | Customer cancelled the checkout |
failed | Payment was attempted but declined or errored |
Payment Methods
Card Payments
Visa, Mastercard, Amex, Discover. Supports 3D Secure authentication for SCA compliance.
Bank Transfers
ACH (US), SEPA (EU), Faster Payments (UK), Interac (Canada). Lower fees than card payments.
Stablecoins
USDC and USDT on Ethereum, Polygon, and Solana. Instant settlement with no chargebacks.
Customization
Customize the checkout page appearance by passing optional parameters when creating a session.
logoUrlLogoPass a URL to your logo image. Recommended size: 256x256 pixels, PNG or SVG format.
"logoUrl": "https://yoursite.com/logo.png"brandColorBrand ColorSet a hex color code for the primary button and accent elements on the checkout page.
"brandColor": "#4F46E5"businessNameBusiness NameDisplay your business name prominently on the checkout header.
"businessName": "Your Store"Payment Links
Payment links are reusable URLs that you can share with customers via email, SMS, or social media. Unlike checkout sessions, payment links do not expire and can be used by multiple customers.
/api/v1/checkout/linkscurl -X POST https://api.wyrr.com/api/v1/checkout/links \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"merchantId": "your-merchant-id",
"amount": 49.99,
"currency": "USD",
"businessName": "Your Store",
"description": "Premium Plan",
"paymentMethodTypes": ["card", "bank_transfer"]
}'{
"linkId": "pl_a1b2c3d4e5f6",
"url": "https://pay.wyrr.com/l/pl_a1b2c3d4e5f6",
"active": true,
"createdAt": "2024-01-01T00:00:00Z"
}Test Cards
Use these card numbers in test mode to simulate different payment outcomes. Any future expiry date and any 3-digit CVC will work.
| Card Number | Behavior |
|---|---|
4242 4242 4242 4242 | Successful payment |
4000 0000 0000 0002 | 3D Secure authentication required |
4000 0000 0000 0003 | Payment declined |
Tip: Use expiry 12/34 and CVC 123 for all test cards.
Webhooks
For reliable payment confirmation, listen for webhook events instead of (or in addition to) redirect-based verification. Webhooks are delivered asynchronously and handle edge cases like customer closing the browser before the redirect.
Key Events
payment.capturedPayment successfully captured. Fulfill the order.payment.failedPayment attempt failed. Notify the customer.checkout.session.expiredSession expired before payment was completed.1// Handle checkout webhook events
2app.post('/webhooks/wyrr', (req, res) => {
3 const event = req.body;
4
5 switch (event.type) {
6 case 'payment.captured':
7 const sessionId = event.data.checkoutSessionId;
8 const paymentId = event.data.paymentId;
9 // Fulfill the order
10 fulfillOrder(sessionId, paymentId);
11 break;
12
13 case 'payment.failed':
14 // Notify the customer or retry
15 notifyPaymentFailed(event.data);
16 break;
17
18 case 'checkout.session.expired':
19 // Clean up pending order
20 cancelPendingOrder(event.data.sessionId);
21 break;
22 }
23
24 res.status(200).send('OK');
25});
Learn more: See the Webhooks documentation for setup instructions, signature verification, and retry behavior.