Developers & partners
Nectar.Pay API
Nectar.Pay is the official directory of merchants in the Honest Money ecosystem. Anyone can show it. Merchants accept payments through the same API.
Open feed of every business that accepts crypto through Nectar.Pay. No key needed.
Create invoices, payment links, check status and receive signed webhooks. Needs a store API key.
OpenAPI description and AI-friendly docs for tools and agents.
Merchant directory feed
Free and public. You can see it as a page at /directory.
Every listed merchant.
Only stores added or changed after that time, plus stores that were closed or unlisted.
- No key, no sign-up. Cross-site requests (CORS) are allowed from any site.
- Use
idas your permanent reference. Names and slugs can change. - Merchants choose how they appear.
city_onlystores carry no name, address or contact, and their location is rounded to about 10 km. - Only stores that accept at least one coin are listed.
- Responses are cached for 5 minutes. For daily syncs, save
generated_atand pass it assincenext time. - Remove anything listed in
removedfrom your copy. - Nectar.Pay is the source of truth. Please don’t edit stores in your copy; ask merchants to update their info in Nectar.Pay.
curl https://app.nectar-pay.com/api/public/v1/directory
{
"generated_at": "2026-10-27T11:00:00Z",
"since": null,
"count": 1,
"stores": [{
"id": "dedc6db9-c547-45ed-920a-a5c325d49507", // permanent, never changes
"slug": "blakes-bbq",
"listing": "full", // "full" | "online" | "city_only"
"status": "live",
"name": "Blake's BBQ",
"category": "Restaurant",
"description": "Texas BBQ, family-run since 2014.",
"logo_url": "https://app.nectar-pay.com/api/public/store-logo/…/logo.png",
"presence": "physical", // "physical" | "online" | "both"
"address": { "street": "123 Main St", "city": "Odessa", "region": "TX",
"postal_code": "79761", "country": "United States" },
"location": { "lat": 31.84, "lng": -102.36, "precision": "exact" },
"phone": "(432) 555-0100",
"website": "https://example.com",
"hours": "Mon–Sat 11am–9pm",
"accepts": ["BTC", "TSD", "TXC", "USDC"],
"egiving": { "accepted": true, "discount_pct": 10 },
"updated_at": "2026-10-27T10:57:57Z"
}],
"removed": [
{ "id": "…", "status": "closed", "removed_at": "2026-10-27T09:00:00Z" }
]
}Payments API — full reference
For stores and plugins: invoices, payment links, rates, store info and signed webhooks. Step-by-step guides: API keys, wallet setup, address rotation, tap to pay (Tangem).
Developer documentation
A non-custodial gateway. You hold the keys; we derive deposit addresses, watch the chain, and notify your store. This page is the complete public API reference — everything a third-party site needs to integrate without ever talking to us.
1. Create an account & store
Sign up at /auth, create a store, and add at least one chain config.
New to xpubs? Step-by-step wallet setup guide for every supported chain → Wondering whether each invoice gets its own address? Address derivation & rotation policy →
2. Get your credentials
Each store has its own secret API key (sk_live_…), created from Store → API keys. It's shown once — store it securely.
For webhooks, set your endpoint URL and copy the signing secret from Store → Webhooks. The secret is per-store and is used to verify every event we send you (see §6).
3. Base URL & authentication
All API calls go to https://app.nectar-pay.com. Keys are issued and validated on this host only — sending a valid key to nectar-pay.com (the marketing site) returns 401 Invalid API key.
Every request carries the key as a Bearer token. Keys are scoped to a single store: you can only ever see and create that store's invoices.
NECTARPAY_API_URL=https://app.nectar-pay.com
# sanity-check your key before wiring anything else:
curl -s https://app.nectar-pay.com/api/public/v1/me \
-H "Authorization: Bearer sk_live_..."A 200 from /api/public/v1/me confirms the key, the store it belongs to, and the webhook URL currently configured. All errors across the API look like { "error": "human readable message" } with an appropriate 4xx/5xx status.
4. Create an invoice
POST https://app.nectar-pay.com/api/public/v1/invoices
Authorization: Bearer sk_live_...
Content-Type: application/json
{
"chain": "btc", // optional — omit to let the customer pick
"amount": 49.00, // required, fiat amount
"currency": "USD", // required, ISO fiat code
"order_id": "ORDER_1234", // optional, echoed back + sent in webhooks
"description": "T-shirt, size M", // optional
"redirect_url": "https://store.example.com/thanks", // optional
"buyer_email": "sam@example.com", // optional, sends a receipt
"expires_in_seconds": 900 // optional, 60–86400, default is store TTL
}Supported chain values:
| chain | network |
|---|---|
| btc | Bitcoin (on-chain) |
| lightning | Bitcoin via Lightning |
| txc | TEXITcoin |
| eth | Ethereum (ETH + USDC/USDT/PYUSD/DAI) |
| base | Base (ETH + stablecoins) |
| tron | Tron (TRX + USDT) |
| sol | Solana (SOL + SPL tokens) |
| doge | Dogecoin |
| ltc | Litecoin |
| bch | Bitcoin Cash |
| dash | Dash |
| isk | Iskander Network |
| zcu | ZCU (Zero Chill) |
If you omit chain, the invoice is created in a "customer picks the network" state and address/crypto_amount/rate are null until the customer chooses on the hosted checkout page.
Response (201):
{
"id": "7c9e…-invoice-uuid",
"address": "bc1q…", // null if chain omitted
"crypto_amount": 0.00041712, // null if chain omitted
"rate": 117500.00, // fiat per coin, null if chain omitted
"fiat_amount": 49.00,
"currency": "USD",
"chain": "btc",
"status": "pending",
"expires_at": "2026-09-14T10:15:00.000Z",
"checkout_url": "https://app.nectar-pay.com/i/7c9e…"
}Send the customer to checkout_url (QR + amount + copyable address) or render your own UI from address and crypto_amount.
5. Check invoice status (polling)
GET https://app.nectar-pay.com/api/public/v1/invoices/{id}
Authorization: Bearer sk_live_...
→ 200 {
"id": "7c9e…",
"status": "confirmed", // see lifecycle below
"chain": "btc",
"fiat_amount": 49.00,
"fiat_currency": "USD",
"crypto_amount": 0.00041712,
"rate": 117500.00,
"address": "bc1q…",
"order_id": "ORDER_1234",
"description": "…",
"redirect_url": "…",
"buyer_email": "…",
"expires_at": "…",
"created_at": "…",
"checkout_url": "https://app.nectar-pay.com/i/7c9e…"
}A 404 means the invoice doesn't exist or belongs to a different store's key — we never leak across stores.
Invoice lifecycle:
| status | meaning |
|---|---|
| pending | Created; waiting for payment (or for the customer to pick a chain). |
| underpaid | A payment arrived but is short of the requested amount. |
| confirmed | Paid and confirmed on-chain. Treat this as final. |
| expired | TTL elapsed with no (sufficient) payment. |
6. Receive webhooks
We POST a signed JSON event to your configured webhook URL on every status change. Headers:
POST /your/webhook HTTP/1.1
Content-Type: application/json
X-TXCPay-Signature: t=1729000000,v1=<hex-hmac-sha256>
X-TXCPay-Event: invoice.paid
X-TXCPay-Event-Id: 0f4c…-event-uuid
User-Agent: payHME-webhook/1Events and when they're sent:
| Event | When / what to do |
|---|---|
| invoice.paid | Full payment received (data.status = "confirmed"). Always followed by invoice.confirmed. |
| invoice.overpaid | Customer paid more than asked (data.status = "overpaid"). Also followed by invoice.confirmed. |
| invoice.confirmed | FINAL — mark the order paid / ship. Sent for every settled invoice (status confirmed or overpaid). Settle on this one event. |
| invoice.underpaid | Payment arrived but short beyond the 1% cushion (data.status = "underpaid"). Don't ship. |
A real, complete paid notification — this is the exact JSON body, no other fields are sent:
POST https://your-site.com/your/webhook
Content-Type: application/json
X-TXCPay-Signature: t=1791019331,v1=5d2c0e9f6b1a…(64 hex chars)
X-TXCPay-Event: invoice.confirmed
X-TXCPay-Event-Id: 3b8f2a61-9d4e-4c1a-8f0b-2e7d5c9a1f44
User-Agent: payHME-webhook/1
{
"id": "3b8f2a61-9d4e-4c1a-8f0b-2e7d5c9a1f44",
"type": "invoice.confirmed",
"created_at": "2026-10-03T09:22:11.482Z",
"data": {
"invoice_id": "7c9e6f1a-2b3d-4e5f-8a9b-0c1d2e3f4a5b",
"store_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"status": "confirmed",
"chain": "txc",
"address": "TXc9yQ…(the address the customer paid)",
"fiat_amount": 49.00,
"fiat_currency": "USD",
"paid_amount_usd": 49.00,
"order_id": "ORDER_1234"
}
}| Field | Meaning |
|---|---|
| id | Unique event id (uuid). Dedupe on this — same as the X-TXCPay-Event-Id header. |
| type | One of the four events above. Same as the X-TXCPay-Event header. |
| created_at | When we sent it (ISO 8601, UTC). |
| data.invoice_id | NectarPay invoice id — the id returned when you created the invoice. |
| data.store_id | Your store's id. |
| data.status | confirmed | overpaid | underpaid. |
| data.chain | Network paid on: btc, txc, eth, base, tron, sol, ltc, doge, bch, dash, isk, zcu. |
| data.address | Receiving address in your wallet. |
| data.fiat_amount | Invoice amount you asked for (number). |
| data.fiat_currency | Currency of fiat_amount, e.g. USD. |
| data.paid_amount_usd | USD value we actually received (can be slightly under within 1%, or over). |
| data.order_id | The order_id you sent when creating the invoice, or null. Use it to find your order. |
Want to double-check? Fetch GET /api/public/v1/invoices/{invoice_id} and confirm status is confirmed or overpaid before shipping.
Always verify the signature against the raw request body before trusting anything:
// node:
const sig = req.headers["x-txcpay-signature"];
const [, t] = sig.match(/t=(\d+)/);
const [, v1] = sig.match(/v1=([a-f0-9]+)/);
const expected = crypto
.createHmac("sha256", WEBHOOK_SECRET) // Store → Webhooks
.update(`${t}.${rawBody}`)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))) reject();
// php:
[$t, $v1] = sscanf($_SERVER['HTTP_X_TXCPAY_SIGNATURE'], 't=%d,v1=%s');
$expected = hash_hmac('sha256', "$t." . file_get_contents('php://input'), $WEBHOOK_SECRET);
if (!hash_equals($expected, $v1)) { http_response_code(401); exit; }Reject timestamps more than ~5 minutes old to stop replay. Events carry a unique id — dedupe on it, because retries can repeat a delivery. Reply 2xx quickly and process asynchronously.
Missed one? Trigger a redelivery for a single invoice:
curl -X POST "https://app.nectar-pay.com/api/public/v1/invoices/{id}?action=redeliver-webhook" \
-H "Authorization: Bearer sk_live_..."7. Drop-in JS button (no backend code)
One <script> tag and a button — crypto checkout opens in a modal, no redirect, works on any site.
<script src="https://app.nectar-pay.com/sdk/payhme.js" defer></script>
<button
data-payhme
data-api-key="sk_live_..."
data-chain="btc"
data-amount="49.00"
data-currency="USD"
data-order-id="ORDER_1234"
>Pay $49 with Bitcoin</button>Or call it programmatically:
PayHME.checkout({
apiKey: "sk_live_...",
chain: "base", amount: 49, currency: "USD",
orderId: "ORDER_1234",
}).then(result => {
// result.status: "paid" | "closed" | "expired"
if (result.status === "paid") console.log("Got it:", result.tx);
});The button's result event is a UX signal, not a settlement guarantee — still confirm payment via webhook or the status endpoint before shipping goods.
Click below — this is the actual SDK, opening a real (test-mode) checkout in a modal. No payment will be processed; close the modal at any time.
Tip: open your browser console to see the payhme:result event payload when the modal closes.
8. Email an invoice to the customer
Have us send the branded payment request by email. Uses the invoice's buyer_email unless you pass to. Sending an expiring invoice pushes its expiry out 7 days so the emailed link stays payable.
curl -X POST "https://app.nectar-pay.com/api/public/v1/invoices/{id}/email" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"to":"customer@example.com"}'
# 200
{ "ok": true, "to": "customer@example.com", "sent_at": "...",
"send_count": 1, "expires_at": "...", "checkout_url": "https://app.nectar-pay.com/i/..." }9. List invoices (reconciliation)
Paged, newest first, scoped to your key's store. All filters are optional and combinable; status and chain accept comma-separated lists.
curl "https://app.nectar-pay.com/api/public/v1/invoices?status=confirmed,underpaid&since=2026-09-01T00:00:00Z&limit=100" \
-H "Authorization: Bearer sk_live_..."
# 200
{ "total": 214, "limit": 100, "offset": 0, "invoices": [ { "id": "...", "status": "confirmed",
"chain": "btc", "token": null, "fiat_amount": 49, "fiat_currency": "USD",
"crypto_amount": 0.00042, "order_id": "ORDER_1234", "created_at": "...",
"checkout_url": "..." } ] }| Query param | Meaning |
|---|---|
| status | pending, detected, underpaid, confirmed, overpaid, expired, cancelled, failed |
| chain | btc, txc, eth, base, sol, tron, ltc, doge, bch, dash, isk, zcu, lightning |
| order_id | Exact match on your own order reference |
| since / until | ISO-8601 timestamps filtering created_at |
| limit / offset | limit 1–200 (default 50), offset for paging |
10. Webhook delivery history
Every attempt we made for an invoice — status code, retry schedule, and the first 500 bytes of your response. Handy when a webhook silently failed in production.
curl "https://app.nectar-pay.com/api/public/v1/invoices/{id}/webhooks" \
-H "Authorization: Bearer sk_live_..."
# 200
{ "invoice_id": "...", "deliveries": [ { "id": "...", "url": "https://you/hook",
"attempt": 1, "status_code": 200, "ok": true, "delivered_at": "...",
"next_retry_at": null, "event_type": "invoice.paid", "event_id": "..." } ] }11. Rates
The live USD rates we price invoices with. Pass ?amount= to get the converted crypto amount per network — useful for showing a price before creating an invoice. Stablecoins (USDC, USDT, TSD) are pegged at $1.
curl "https://app.nectar-pay.com/api/public/v1/rates?amount=25" \
-H "Authorization: Bearer sk_live_..."
# 200
{ "fiat": "USD", "amount": 25,
"rates": [ { "chain": "btc", "rate": 118422.5, "crypto_amount": 0.00021, "fetched_at": "..." } ],
"stablecoins": [ { "token": "USDC", "rate": 1, "crypto_amount": 25 } ] }12. Store info
What your key can see about the store it belongs to: currency, tax settings, default invoice lifetime, which networks and tokens are enabled, whether a webhook is configured, and the store's hosted payment links.
curl "https://app.nectar-pay.com/api/public/v1/store" \
-H "Authorization: Bearer sk_live_..."
# 200
{ "id": "...", "name": "Acme Coffee", "currency": "USD", "invoice_ttl_seconds": 900,
"tax_bps": 825, "webhook_configured": true,
"chains": [ { "chain": "btc", "network": "mainnet", "tokens": [] },
{ "chain": "base", "network": "mainnet", "tokens": ["USDC"] } ],
"payment_links": [ { "slug": "acme", "url": "https://app.nectar-pay.com/t/acme" } ] }13. Hosted payment links (no code at all)
A payment link is a reusable hosted page at https://app.nectar-pay.com/t/your-slug — put it in an email, a QR code, a bio link, a donation button. No API key needed by the payer. Create and manage them over the API:
# create
curl -X POST "https://app.nectar-pay.com/api/public/v1/links" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"slug":"acme","title":"Acme Coffee","preset_amounts":[5,10,25],
"allow_custom_amount":true,"min_amount":1,"max_amount":500}'
# 201 -> { "slug": "acme", "url": "https://app.nectar-pay.com/t/acme", ... }
# list
curl "https://app.nectar-pay.com/api/public/v1/links" -H "Authorization: Bearer sk_live_..."
# update / deactivate
curl -X PATCH "https://app.nectar-pay.com/api/public/v1/links/acme" \
-H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" \
-d '{"title":"Acme Coffee — Tips"}'
curl -X DELETE "https://app.nectar-pay.com/api/public/v1/links/acme" \
-H "Authorization: Bearer sk_live_..."Omit slug and we derive one from the title (with a short suffix if it's taken). Deleting deactivates the link — the URL stops accepting payments but past invoices stay intact. Set is_donation: true for a donate-style page.
E-commerce plugins
Prefer a ready-made plugin? WooCommerce, PrestaShop, OpenCart, Magento, WHMCS and more → Every plugin is a thin wrapper around the exact API documented above.
Don't trust us? Good.
We get it. The whole point of crypto is don't trust, verify. A payment processor asking you to take its word for it is the exact thing we built Nectar.Pay to replace. We don't hold your keys — and you don't have to take our word for that either.
Read the source. Run it yourself. Or fork the whole thing and run a competing gateway — we honestly don't mind. The bees do better when the hive is bigger.
Every line of the gateway, SDK, and watcher. MIT-ish, audit-friendly, no hidden custody layer.
One-click clone of the entire Nectar.Pay stack into your own Lovable workspace. Your domain, your keys, your hive. Checkout via blockchainmint.com — coming soon.
Prefer to self-host the GitHub source? Go for it — no license fee, no phone-home. The $999 remix is just the shortcut.
Partner APIs
Signed public list of approved eGiving churches. Optional ?q= (search) and ?code=. Every response is TXC-message-signed; wallets should pin the signer address.
For approved wallet partners: claim the POP reward for a paid sale (HMAC-signed). Each sale can be claimed once.