Checkout
Hosted checkout link
A single-use URL to the full-page checkout, minted server-side. Good for emails, marketing pages, server-side redirects, or anywhere the embed script can't run.
Buy link (no server code)
The fastest way to sell: paste a permanent product URL anywhere (email, landing page, social) and each click mints a fresh checkout. No API key, no server. The URL is:
https://pay.meridapay.com/pay/<product-id>
Get it pre-filled from the dashboard: open the product, click Sell this product → Link tab → Copy. Optional query passthroughs:
discount_codestringPre-applied discount, same code your dashboard issued.
success_urlhttps URLOverride where the buyer lands after paying. {CHECKOUT_TOKEN} in
the URL is substituted with the actual session token.
Under the hood, the buyer worker calls POST /buy-links/<id>/checkout
on the API surface to mint the session. You don't need to think about
it unless you want server-side control (next section).
Mint a link from your backend
When you need to attach per-buyer context (customer email, your own
user id external_customer_id, metadata that should ride on every
webhook, an idempotency key), call POST /checkouts from your backend
instead. The response includes a pay.meridapay.com/<token> URL.
// Your backend (example: Next.js route handler)
export async function POST() {
const res = await fetch("https://api.meridapay.com/checkouts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MERIDA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
product_id: "<product-id>",
customer_email: "[email protected]",
external_customer_id: "user_123",
success_url: "https://app.example.com/thanks",
}),
})
const { url } = await res.json()
return Response.redirect(url, 303)
}
See API reference for the full request/response shape.
Prefill via query params
If you know the buyer's identity (logged-in user, known lead), pass it in
the body of POST /checkouts (preferred, see the snippet above) so it
rides on every webhook. For lightweight one-off prefills, you can also
append query params to the minted URL before redirecting:
https://pay.meridapay.com/<token>[email protected]&name=Jane%20Doe&discount_code=LAUNCH20
emailstringPrefill the buyer's email input.
namestringPrefill the cardholder name input.
discount_codestringPre-applied discount code.
brandhex colorPay button tint. Hex only. Anything else is ignored.
labelstringDisplay title shown in place of the product name, up to 140 characters. Handy when many checkouts ride one shared product and each needs its own title. Display only, so reporting keeps the product's real name.
Query-param prefills are visible to anyone who sees the URL. Treat them as public.
Idempotency
Pass an Idempotency-Key header on POST /checkouts so retries from
your backend (timeouts, redeliveries) return the same checkout instead of
minting duplicates.
Currency
A product can be priced in more than one currency. When a buyer opens the hosted checkout, MeridaPay selects the currency that matches their region automatically. If your product offers that currency, the buyer sees the local price right away. If not, the checkout falls back to the product's default currency.
The buyer can switch among the currencies your product offers at any time before paying. The charge always uses the currency shown when they confirm.
To pin one currency for all buyers regardless of location, pass currency
in the body of POST /checkouts:
body: JSON.stringify({
product_id: "<product-id>",
customer_email: "[email protected]",
currency: "EUR", // always charge in EUR
success_url: "https://app.example.com/thanks",
}),
If you omit currency, the checkout handles selection for you.
After the payment
The buyer pays on pay.meridapay.com/<token> and is redirected to your
success_url with ?status=paid&payment_link_id=<token> appended. The
authoritative confirmation comes from the
payment.succeeded webhook, not from the buyer landing on
that URL (they might close the tab).
Next up
API reference →