Pay Link Integration Guide
This guide covers where to create pay links in your application flow and how to show them to customers.
Step 1 — Create the order in your system first
Before calling the Coinsnap API, your own system should create the order or invoice internally. The pay link belongs to a specific business transaction — your order is the source of truth.
At minimum you need:
- Your own internal order ID or invoice number
- The order amount and currency
- Optionally: customer name or email, description, success URL
Example order:
- Order ID:
ORD-2026-1045 - Customer: John Smith
- Amount: €149.00
This order ID becomes the key reference between your system and Coinsnap. It will appear in every webhook event so you can match payments back to orders.
Step 2 — Create a pay link via the API
After the order exists in your system, call the Coinsnap API to create a pay link.
async function createOrder(cart, customer) {
// 1. Save the order to your database
const order = await db.orders.create({
customerId: customer.id,
total: cart.total,
currency: cart.currency,
status: 'pending_payment',
});
// 2. Create a pay link for this order
const res = await fetch(
`https://app.coinsnap.io/api/v1/stores/${process.env.COINSNAP_STORE_ID}/payment-requests`,
{
method: 'POST',
headers: {
'x-api-key': process.env.COINSNAP_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: cart.total,
currency: cart.currency,
orderId: order.id,
title: customer.name,
customerEmail: customer.email,
description: `Order ${order.id}`,
redirectUrl: `${process.env.APP_URL}/orders/${order.id}/success`,
}),
}
);
const payLink = await res.json();
// 3. Store both the ID and URL against your order
await db.orders.update(
{ id: order.id },
{ payLinkId: payLink.id, payLinkUrl: payLink.url }
);
return { order, payLinkUrl: payLink.url };
}
Step 3 — Choose where to show the pay link
You have four options. Pick the one that fits your workflow.
Option A — On the order confirmation page
Show the pay link immediately after the customer places an order. Bitcoin is offered as an alternative to whatever payment method they chose.
<div class="payment-option">
<h3>Pay with Bitcoin</h3>
<p>Scan or click to pay with Bitcoin or Lightning.</p>
<a href="{{ order.payLinkUrl }}" class="btn">Pay with Bitcoin →</a>
</div>
Option B — In the order confirmation email
Include the pay link in the transactional email sent after order creation. The customer pays when convenient.
await sendEmail({
to: customer.email,
subject: `Order ${order.id} confirmed`,
html: `
<p>Hi ${customer.name},</p>
<p>Your order has been confirmed.</p>
<p>Pay with Bitcoin: <a href="${order.payLinkUrl}">${order.payLinkUrl}</a></p>
<p>This link is valid for 30 days.</p>
`,
});
Option C — In the customer account area
Store the pay link and display a "Pay with Bitcoin" button on unpaid orders in the customer's account.
{% if order.status == 'pending_payment' %}
<a href="{{ order.payLinkUrl }}">Pay with Bitcoin</a>
{% endif %}
Option D — On an invoice PDF or email
For B2B and invoice-based billing, include the pay link the same way you'd include bank transfer instructions.
Instead of:
Please transfer EUR 149.00 to IBAN DE12... with reference ORD-2026-1045
Include:
Pay this invoice with Bitcoin: [pay link URL]
All payment details — amount, currency, your order reference — are already embedded in the link. The customer clicks and pays. No manual entry of IBAN or reference number.
Step 4 — Handle payment confirmation
Register a webhook endpoint in Coinsnap Dashboard → Webhooks and handle the Settled event to mark the order as paid.
case 'Settled': {
const orderId = event.metadata?.orderId;
const order = await db.orders.findById(orderId);
if (order.status === 'paid') break; // idempotency guard
await db.orders.update({ id: orderId }, {
status: 'paid',
paidAt: new Date(),
});
await triggerFulfillment(orderId);
break;
}
See Handle Payment Result for the full webhook guide including all event types.
End-to-end flow
- Customer places an order in your application
- Your system creates the order (
status: pending_payment) - Your application calls the Coinsnap API to create a pay link
- Coinsnap returns the pay link ID and URL
- Your system stores both against the order
- The customer receives the pay link (confirmation page, email, or account area)
- The customer opens the pay link
- Coinsnap shows the hosted payment page with order details prefilled
- The customer clicks "Pay with Bitcoin"
- Coinsnap generates a Bitcoin invoice at the current exchange rate
- The customer pays via Lightning or Bitcoin
- Coinsnap sends a
Settledwebhook to your server - Your server marks the order as paid and triggers fulfillment
One pay link per order
Create one pay link per order and reuse it. Do not create a new pay link every time the customer views their order — the same URL remains valid as long as the order is unpaid and the expiry date hasn't passed.