External E-commerce Integration
Integrate Send Pay Links with your existing shopping cart or e-commerce platform
External E-commerce Integration
This guide explains how to integrate Send Pay Links with your external shopping cart, e-commerce platform, or custom application to generate checkout pages on-the-fly with dynamic cart data.
Overview
Send Pay Links acts as a headless checkout system. Your e-commerce store calculates the cart totals, then sends the data to our API to generate a hosted checkout page.
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Your Store │ │ Send Pay Links │ │ Checkout Page │
│ (Cart System) │────▶│ API │────▶│ /c/[code] │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
│ POST cart data │ │
│───────────────────────▶│ │
│ │ │
│ { checkoutUrl } │ │
│◀───────────────────────│ │
│ │ │
│ Redirect customer ─────────────────────────────▶Step 1: Generate a Checkout URL
From your backend, POST your cart data to generate a checkout URL:
POST https://sendpaylinks.com/api/token/generate
Content-Type: application/jsonRequest Body
{
"orderId": "cart_12345",
"merchantId": "your_store_id",
"customer": {
"email": "customer@example.com",
"firstName": "John",
"lastName": "Doe",
"phone": "+1234567890"
},
"shippingAddress": {
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "New York",
"state": "NY",
"postalCode": "10001",
"country": "US"
},
"lineItems": [
{
"id": "prod_abc",
"name": "Blue Widget",
"quantity": 2,
"unitPrice": 2999,
"sku": "WIDGET-BLUE",
"imageUrl": "https://yourstore.com/images/widget.jpg"
},
{
"id": "prod_xyz",
"name": "Red Gadget",
"quantity": 1,
"unitPrice": 4999,
"sku": "GADGET-RED"
}
],
"subtotal": 10997,
"shipping": 999,
"tax": 880,
"discount": 0,
"total": 12876,
"currency": "USD",
"allowedProviders": ["stripe", "nmi"],
"successUrl": "https://yourstore.com/order-confirmed",
"cancelUrl": "https://yourstore.com/cart",
"webhookUrl": "https://yourstore.com/api/webhooks/checkout"
}Response
{
"success": true,
"code": "abc123xyz",
"checkoutUrl": "https://sendpaylinks.com/c/abc123xyz",
"token": "eyJhbGciOiJIUzI1NiIs...",
"payload": { ... }
}Redirect the Customer
After receiving the response, redirect your customer to the checkoutUrl:
// JavaScript
window.location.href = response.checkoutUrl;// PHP
header("Location: " . $response['checkoutUrl']);
exit;# Python/Flask
return redirect(response['checkoutUrl'])Step 2: Understanding Key Fields
Required Fields
| Field | Type | Description |
|---|---|---|
orderId | string | Your unique order/cart identifier |
merchantId | string | Your store identifier (for tracking) |
customer | object | Customer contact information |
shippingAddress | object | Shipping address |
lineItems | array | Products in the cart |
total | number | Total amount in cents (e.g., 9999 = $99.99) |
currency | string | ISO currency code (e.g., "USD") |
allowedProviders | array | Payment providers to offer |
successUrl | string | Redirect URL after successful payment |
cancelUrl | string | Redirect URL if customer cancels |
Optional Fields
| Field | Type | Description |
|---|---|---|
webhookUrl | string | URL to receive payment notifications |
metadata | object | Custom key-value data passed through |
metadata.brandId | string | Brand ID for multi-tenant settings |
upsellConfig | object | Configure post-purchase upsells |
salesAttribution | object | Track sales commissions |
Step 3: Using merchantId vs brandId
These are two separate identifiers with different purposes:
| Field | Purpose | Where It Comes From |
|---|---|---|
merchantId | Your tracking identifier | You provide it (store ID, account ID, etc.) |
brandId | Platform settings identifier | Created in Send Pay Links admin |
When to Use Each
merchantId - Always include this. Use your own store/account ID for:
- Tracking orders by store
- Analytics and reporting
- Webhook identification
brandId - Include in metadata when you need:
- Brand-specific payment credentials (different Stripe keys per brand)
- Custom checkout themes
- Organization-level settings
{
"merchantId": "my-shopify-store",
"metadata": {
"brandId": "brand_abc123"
}
}Step 4: Receive Webhooks
Configure webhookUrl to receive real-time notifications when payments complete:
{
"webhookUrl": "https://yourstore.com/api/webhooks/sendpaylinks"
}Webhook Payload
{
"type": "checkout.completed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"object": {
"order_id": "cart_12345",
"transaction_id": "pi_abc123",
"provider": "stripe",
"amount": 12876,
"currency": "USD",
"status": "completed",
"customer": {
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe"
},
"line_items": [
{
"id": "prod_abc",
"name": "Blue Widget",
"quantity": 2,
"unit_price": 2999,
"total_price": 5998
}
]
}
}
}Code Examples
Node.js / Express
const express = require('express');
const app = express();
app.post('/checkout', async (req, res) => {
const { cart, customer } = req.body;
const response = await fetch('https://checkout.yoursite.com/api/token/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: cart.id,
merchantId: process.env.STORE_ID,
customer: {
email: customer.email,
firstName: customer.firstName,
lastName: customer.lastName,
},
lineItems: cart.items.map(item => ({
id: item.productId,
name: item.name,
quantity: item.quantity,
unitPrice: Math.round(item.price * 100), // Convert to cents
})),
subtotal: Math.round(cart.subtotal * 100),
shipping: Math.round(cart.shipping * 100),
tax: Math.round(cart.tax * 100),
total: Math.round(cart.total * 100),
currency: 'USD',
allowedProviders: ['stripe'],
successUrl: `${process.env.STORE_URL}/order-confirmed`,
cancelUrl: `${process.env.STORE_URL}/cart`,
webhookUrl: `${process.env.STORE_URL}/api/webhooks/checkout`,
}),
});
const data = await response.json();
res.redirect(data.checkoutUrl);
});PHP
<?php
function createCheckout($cart, $customer) {
$payload = [
'orderId' => $cart['id'],
'merchantId' => getenv('STORE_ID'),
'customer' => [
'email' => $customer['email'],
'firstName' => $customer['first_name'],
'lastName' => $customer['last_name'],
],
'lineItems' => array_map(function($item) {
return [
'id' => $item['product_id'],
'name' => $item['name'],
'quantity' => $item['quantity'],
'unitPrice' => (int)($item['price'] * 100),
];
}, $cart['items']),
'total' => (int)($cart['total'] * 100),
'currency' => 'USD',
'allowedProviders' => ['stripe'],
'successUrl' => 'https://yourstore.com/order-confirmed',
'cancelUrl' => 'https://yourstore.com/cart',
];
$ch = curl_init('https://checkout.yoursite.com/api/token/generate');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response['checkoutUrl'];
}
// Usage
header("Location: " . createCheckout($cart, $customer));
exit;
?>Python
import requests
import os
def create_checkout(cart, customer):
payload = {
"orderId": cart["id"],
"merchantId": os.environ["STORE_ID"],
"customer": {
"email": customer["email"],
"firstName": customer["first_name"],
"lastName": customer["last_name"],
},
"lineItems": [
{
"id": item["product_id"],
"name": item["name"],
"quantity": item["quantity"],
"unitPrice": int(item["price"] * 100),
}
for item in cart["items"]
],
"total": int(cart["total"] * 100),
"currency": "USD",
"allowedProviders": ["stripe"],
"successUrl": "https://yourstore.com/order-confirmed",
"cancelUrl": "https://yourstore.com/cart",
}
response = requests.post(
"https://checkout.yoursite.com/api/token/generate",
json=payload
)
return response.json()["checkoutUrl"]
# Usage with Flask
from flask import redirect
@app.route("/checkout", methods=["POST"])
def checkout():
checkout_url = create_checkout(cart, customer)
return redirect(checkout_url)Adding Upsells
Include upsellConfig to show post-purchase offers:
{
"orderId": "cart_12345",
"merchantId": "your_store",
...
"upsellConfig": {
"enabled": true,
"offers": [
{
"id": "upsell_premium",
"productId": "prod_premium",
"name": "Upgrade to Premium",
"description": "Get 50% more features!",
"price": 1999,
"originalPrice": 3999,
"ctaText": "Yes, Upgrade Me!",
"declineText": "No Thanks"
}
]
}
}Or reference a pre-built flow from the admin:
{
"upsellConfig": {
"enabled": true,
"flowId": "flow_abc123"
}
}Next Steps
- Configure webhooks for order notifications
- Set up upsells for post-purchase offers
- Add sales attribution for commission tracking