For partners
White-label integration
Everything needed to run payment requests and checkout under a partner's own brand. The partner's pages frame ours; once a buyer reaches the checkout, signing in, paying and settling all happen inside our site.
- Site (production)
https://stabledrop.me- API (production)
https://api.stabledrop.me- Test (site and API)
https://test.conduit-ucpi.com
The white-label brand, reading this. You request your brand (step 1) and host the pages on your site (step 4).
The Stabledrop team. We set up your brand and allow your domains (steps 2 and 3). Nothing for you to do there.
Your customers who take payments, through links, a checkout button or the API (steps 5 and 6).
| # | Step | Who does it |
|---|---|---|
| 1 | Request your brand: paste your config and send | You (the partner) |
| 2 | Create your brand | Stabledrop (us) |
| 3 | Allow your domains | Stabledrop (us) |
| 4 | Host the framed pages on your site | You (the partner) |
| 5 | Take payments | Your merchants |
| 6 | Confirm payments | Your merchantsYou (the partner) |
| 7 | Test end to end | You (the partner)Stabledrop (us) |
Request your brand
Who does this:You (the partner)You, the partner: fill in the form below and send it.
Paste your brand config, add your email address and domains, and send us the email this builds. We set up your brand and allow your domains (steps 2 and 3), then reply to confirm.
Nothing you send can change a payment's terms, fee, tiebreaker or verification. Branding only changes how the pages look and read.
We create your brand
Who does this:Stabledrop (us)Stabledrop, once your request arrives. Nothing for you to do here; this is how we do it.
- Upload the image and font files to the service (
POST /api/brands/{id}/assets); each upload returns an asset id. - Add the brand to
webapp/config/brands/snapshot.json, referring to those asset ids. Pull first, because pushing replaces the whole record. - Push it, then commit the updated snapshot so the copy bundled with the site agrees.
- Tell the partner their brand id.
{
"id": "your-brand",
"name": "Your Brand",
"tagline": "Protected payments",
"locale": "en",
"links": {
"support": "mailto:[email protected]",
"terms": "/terms-of-service",
"privacy": "/privacy-policy",
"arbitration": "/dispute-policy"
}
}WHITELABEL_URL=https://api.stabledrop.me WHITELABEL_ADMIN_KEY=… node scripts/brands/pull.mjs
# edit config/brands/snapshot.json, then push only this brand
WHITELABEL_URL=https://api.stabledrop.me WHITELABEL_ADMIN_KEY=… node scripts/brands/push.mjs your-brandTheme colours are "R G B" triples in primary and secondary ramps. Use the test service's address for the test environment.
We allow your domains
Who does this:Stabledrop (us)Stabledrop. Nothing for you to do here; we email you when your pages can go live.
- Frame allow-list: add every partner domain to the webapp's
ALLOWED_FRAME_ANCESTORSvariable, in each environment the partner will use (test and production), then redeploy the webapp. Without this the browser shows an empty frame. - Privy: add the domains to the allowed origins in the Privy dashboard.
Check the variable for each environment before telling a partner their pages are ready.
Host the framed pages on your site
Who does this:You (the partner)You, the partner, on your own website: copy these pages into it.
Each page on your site frames one of ours with your brand id. Keep the allow attribute: without clipboard-write the copy buttons fail inside your page.
Checkout: your-site/contract-create (required for checkout)
Passes its own address parameters straight to our checkout, always under your brand. A link such as your-site/contract-create?seller=0x…&amount=9.77&description=Order%20%231042opens that payment. It also forwards the checkout's results to whatever opened the page, for merchants who open it as a popup.
<div id="checkout"></div>
<script>
var BRAND = 'your-brand';
var SITE = 'https://stabledrop.me';
// The merchant's terms are this page's own query string; the brand is always yours.
var params = new URLSearchParams(window.location.search);
params.set('b', BRAND);
var frame = document.createElement('iframe');
frame.src = SITE + '/contract-create?' + params.toString();
frame.title = 'Checkout';
frame.allow = 'clipboard-write; payment';
frame.style.cssText = 'width:100%;height:760px;border:0';
document.getElementById('checkout').appendChild(frame);
// The checkout reports to this page (payment_completed, payment_error,
// payment_cancelled, close_modal). Forward them to whatever opened this page.
window.addEventListener('message', function (event) {
if (event.origin !== SITE) return;
if (window.opener) window.opener.postMessage(event.data, '*');
if (window.parent !== window) window.parent.postMessage(event.data, '*');
});
</script>Payment requests: your-site/create
Merchants make a payment request and get a link, QR code and PDF to send their customer.
<iframe src="https://stabledrop.me/create?b=your-brand"
title="Request a payment"
allow="clipboard-write; payment"
style="width:100%;height:760px;border:0"></iframe>Developer guide: your-site/integrate
Our integration guide, shown with your brand. Its code samples already include your brand id, and its support contact is the one from your brand record.
<iframe src="https://stabledrop.me/integrate?b=your-brand"
title="Integration guide"
allow="clipboard-write"
style="width:100%;height:85vh;min-height:720px;border:0"></iframe>Optional: your-site/dashboard
<iframe src="https://stabledrop.me/dashboard?b=your-brand"
title="Payments dashboard"
allow="clipboard-write; payment"
style="width:100%;height:85vh;min-height:720px;border:0"></iframe>For testing, use https://test.conduit-ucpi.com in place of https://stabledrop.me.
Your merchants take payments
Who does this:Your merchantsYour merchants, on their own sites. Share this step with them, or point them at your integrate page from step 4, which shows the same with your brand filled in.
Merchants can use any of three routes. All of them record the payment under the partner's brand.
A. A link to the partner's checkout page
https://your-site.example/contract-create?seller=0xYourWalletAddress&amount=9.77&description=Order%20%231042&tokenSymbol=USDC| Parameter | Meaning |
|---|---|
seller | Required. The wallet that is paid: 0x plus 40 hex characters, or an email address. |
amount | Required. In dollars as typed, for example 9.77. At least 1, or exactly 0.001 for a free test. |
description | Required. What the payment is for, up to 160 characters. |
tokenSymbol | USDC (default) or USDT. |
epoch_expiry | Payout date as a Unix timestamp. Default 7 days. 0 pays the seller instantly, with no dispute window. |
order_id | Your order reference, echoed back in events and webhooks. |
return | Where to send the buyer afterwards. |
webhook_url | Your endpoint to be told when the payment is made. |
Without all three required parameters, the buyer is sent to the general payment page instead.
B. A checkout button on the merchant's own website
The script opens our checkout in a popup. Point baseUrl at our site and set brand: the partner's branding and attribution, with nothing hosted by the partner.
<script src="https://stabledrop.me/conduit-checkout.js"></script>
<script>
ConduitCheckout.init({
sellerAddress: '0xYourWalletAddress',
baseUrl: 'https://stabledrop.me',
brand: 'your-brand',
onSuccess: function (data) { console.log('Paid', data); },
onError: function (error) { console.error(error); },
onCancel: function () { console.log('Cancelled'); }
});
</script>
<button onclick="ConduitCheckout.open({ amount: '9.77', description: 'Order #1042', orderId: '1042' })">
Pay
</button>C. From the merchant's server, with no script
No sign-in or API key. The answer contains the escrow address, how to fund it, a pay_link to send the customer, and the exact request that creates the escrow once paid. We do not email the customer for a server call; the merchant sends the pay_link.
curl -X POST https://api.stabledrop.me/api/ap2/prepare \
-H 'Content-Type: application/json' \
-d '{
"seller": "0xYourWalletAddress",
"nominal_buyer": "[email protected]",
"amount": 9770000,
"expiry_timestamp": 1893456000,
"description": "Order #1042",
"brand": "your-brand"
}'On the API, amount is in base units: 1 USDC is 1000000, so 9.77 is 9770000. Once the money arrives, send the answer's settle.request.body unchanged to POST /api/ap2/settle. Every field is described in the API reference.
Confirm payments
Who does this:Your merchantsYou (the partner)Your merchants check each payment before shipping. You can see every payment made under your brand.
Check a payment before shipping anything. The results service is public and needs no key. Treat it as the source of truth; a webhook only tells you to look.
curl -X POST https://api.stabledrop.me/api/results \
-H 'Content-Type: application/json' \
-d '{"contractid": "507f1f77bcf86cd799439011"}'curl -X POST https://api.stabledrop.me/api/results \
-H 'Content-Type: application/json' \
-d '{"brandId": "your-brand"}'A payment has arrived when its state is one of ACTIVE, DISPUTED, RESOLVED, CLAIMED or COMPLETED. Having a chainAddress does not mean it was paid: the address is recorded when the buyer opens the checkout.
Test end to end
Who does this:You (the partner)Stabledrop (us)You run these checks on your pages; we fix anything on our side. An empty frame means step 3 is not done yet: tell us.
- Each hosted page shows our page inside it, in the partner's branding (an empty frame means the domain is not on the allow-list yet).
your-site/contract-create?seller=…&amount=0.001&description=Testopens a checkout for the free test amount.- Pay it; the payment appears in
/api/resultsunder your brand id. - The developer guide's samples show your brand id and your support contact.
- A merchant's checkout button opens the popup and calls
onSuccessafter paying.
Limits of framed pages
- Google sign-in cannot run inside a frame. Buyers inside your page get email sign-in and an "open in a new tab" option for Google. Some browsers, notably Safari, may not keep a sign-in inside a frame.
- Links we generate are on our domain. Payment links, request emails and dashboard links open
stabledrop.me/…?b=your-brand: your branding, our address. - No webhooks to the partner. Partners follow their payments through the results service, filtered by brand id.
- Calling our API from a browser page on your domain needs your origin allowed for cross-origin requests. Calls from a server do not.