4 paths, equal weight: Shopify, WooCommerce, AI builders (Lovable / v0 / Bolt / Cursor), or direct API. Click the one that describes you and we walk through the exact steps — nothing more, nothing less.
Made for Lovable, v0, Bolt, Cursor. Do them in order. Each takes a minute.
0 / 5 done
We need a wallet on file so payments can settle.
Your site will use this to verify incoming events are really from us.
Loading your secret…
Your AI will read it and install Peptide-Pay end-to-end. No extra instructions needed.
You are integrating the Peptide-Pay payment processor into a NEW website I'm building with you. Follow this spec exactly — do not invent endpoints, do not add fields not listed here, do not skip the security steps.
=== ABOUT PEPTIDE-PAY ===
Peptide-Pay is a non-custodial payment processor purpose-built for solo founders and indie devs launching high-risk merchants (peptides, research chemicals, supplements, nootropics) — think "Stripe, for people who get rejected from Stripe". It accepts Apple Pay, Google Pay, cards (Visa/Mastercard/Amex), and crypto, settles on-chain in USDC on Polygon directly to the merchant's wallet, and charges a flat 3% commission. No LLC required to start, no rolling reserve, no setup deposit, same-day go-live. No subscription, no monthly fee. No account required for wallet-only mode. Perfect for MVP / pre-incorporation / soft-launch. Funds never transit a Peptide-Pay balance — every settlement is a direct on-chain transfer from the customer's payment rail to the merchant's wallet.
=== THE ONLY 3 ENDPOINTS YOU WILL USE ===
1. POST https://peptide-pay.com/api/v1/checkout/init — create a payment session
2. GET https://peptide-pay.com/api/v1/sessions/{id} — poll session status (webhook fallback)
3. POST from Peptide-Pay → {YOUR_SITE}/api/peptidepay-webhook — signed settlement notification
Any other URL or "provider" endpoint you might "remember" — DO NOT use it. Only these three.
=== REQUEST BODY (POST /api/v1/checkout/init) ===
{
"wallet": "0x...", // REQUIRED in wallet-only mode (no API key). 0x + 40 hex, Polygon.
"amount_cents": 5000, // REQUIRED. Integer. Minimum 100, maximum 10_000_000. Alias: "amount".
"currency": "EUR", // REQUIRED. One of: EUR, USD, GBP, CAD, CHF, AUD.
"customer_email": "buyer@example.com", // Optional. Shown in checkout, forwarded for KYC reuse.
"metadata": { "order_id": "ord_123" }, // Optional. Echoed back in webhook verbatim. Max 10 keys.
"success_url": "https://mysite.com/order/ord_123", // Optional. Redirect after paid. https only.
"cancel_url": "https://mysite.com/cart", // Optional. Redirect if abandoned.
"product_name": "BPC-157 10mg", // Optional. Shown on the hosted checkout page.
"webhook_url": "https://mysite.com/api/peptidepay-webhook" // Optional if set in dashboard.
}
Advanced mode: set header `Authorization: Bearer ${PEPTIDEPAY_API_KEY}` and omit `wallet` — the dashboard default is used. Idempotency: pass `Idempotency-Key: <uuid>` for safe retries.
=== GOTCHAS (read these — they break naive integrations) ===
- Use `https://www.peptide-pay.com` (with `www.`) as the API base. The apex domain 308-redirects and Node `fetch` strips the Authorization header on cross-origin redirects → silent 401.
- Set `PEPTIDEPAY_API_KEY` to your `sk_live_…` key — that is the canonical key for every endpoint. Signup also returns an `sk_test_…` key for the webhook-receiver simulator; the API will accept it but Peptide-Pay has no sandbox network, so every settlement is a real on-chain transfer regardless of which key you used. To dry-run, run a $1 real payment and refund it to yourself.
- If you authenticate with `Authorization: Bearer …`, do NOT also include `wallet` in the body — the header is the identity and the body field is ignored.
- Never modify the redirect URL after payment (cancel_url / success_url are fine BEFORE; intercepting the on-ramp's post-payment redirect breaks its signature → "Signature check failed" at the customer's bank).
=== RESPONSE (200 OK) ===
{
"id": "cs_abc123...",
"url": "https://peptide-pay.com/session/cs_abc123...",
"status": "pending",
"amount": 5000,
"currency":"EUR",
"expires_at": "2026-04-22T12:00:00Z"
}
You MUST redirect the customer to the returned `url`. That's Peptide-Pay's hosted checkout — it collects payment details on its own domain. Never build a card form on your site.
=== WEBHOOK VERIFICATION (non-negotiable) ===
Peptide-Pay sends a POST to your webhook URL with:
- Content-Type: application/json
- Body: { "event": "order.paid", "session_id": "cs_...", "order_id": "ord_123",
"address_in": "0x...", "status": "paid", "amount": 5000, "currency": "EUR",
"txid": "0x...", "paid_at": "2026-04-23T10:05:00Z", "attempt": 1 }
- Header: `x-peptidepay-signature: t=<unix_seconds>,v1=<hex HMAC-SHA256>`
The HMAC is computed as HMAC-SHA256(secret, "${t}.${raw_body}") — Stripe-style. The secret (whsec_...) is issued on signup at peptide-pay.com/signup. Wallet-only flows (no signup) deliver the webhook UNSIGNED — detect that by the missing header and validate via the address_in match to a session you created.
On your webhook endpoint YOU MUST:
1. Read the RAW body as bytes/string BEFORE any JSON parser touches it.
2. Parse the header into t and v1.
3. Reject if abs(now - t) > 300 seconds (replay protection).
4. Compute expected = HMAC-SHA256(whsec_secret, "${t}.${raw_body}") as hex.
5. Compare v1 vs expected with a TIMING-SAFE compare:
- Node: crypto.timingSafeEqual(Buffer.from(v1, 'hex'), Buffer.from(expected, 'hex'))
- Python: hmac.compare_digest(v1, expected)
- PHP: hash_equals(expected, v1)
6. If mismatch: return 401 and do nothing else.
7. If match: parse the JSON, find your order by `metadata.order_id` (or `session_id`), mark it paid, return 200.
Peptide-Pay retries failed deliveries 6 times over ~42 hours with exponential backoff (5min → 15min → 1h → 4h → 12h → 24h). Return 200 quickly and enqueue heavy work (email, fulfillment). Make your handler idempotent — dedupe on session_id.
=== ENVIRONMENT VARIABLES ===
PEPTIDEPAY_WALLET=0x... # REQUIRED for wallet-only mode. Polygon USDC address.
PEPTIDEPAY_API_KEY=sk_live_xxx # Optional. Advanced mode + dashboard + analytics. MUST start with sk_live_ — the sk_test_ key from signup only works on /api/v1/test/fire-webhook.
PEPTIDEPAY_WEBHOOK_SECRET=whsec_xxx # REQUIRED. Used for HMAC verification.
=== SMOKE TEST (run this BEFORE writing any code) ===
A 200 here proves your key + the API are healthy. A 400 mentioning sk_live_ means you copied the wrong key.
```bash
curl -X POST https://www.peptide-pay.com/api/v1/checkout/init \
-H "Authorization: Bearer sk_live_PASTE_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"amount_cents":100,"currency":"USD","success_url":"https://example.com/ok","cancel_url":"https://example.com/cancel"}'
```
Expected response: `{ "id": "cs_…", "url": "https://www.peptide-pay.com/session/cs_…", "status": "pending", … }`
=== FILES TO CREATE ===
Build EVERY file in this list. Use the conventions of the framework I asked you to use.
1. `lib/peptidepay.(ts|js|py|php)`
- `createPeptidePaySession({ amountCents, currency, metadata, successUrl, cancelUrl, customerEmail })`
→ POSTs to /api/v1/checkout/init, returns { id, url, status }
- `verifyPeptidePaySignature(rawBody: string, signature: string): boolean`
→ HMAC-SHA256 timing-safe compare against PEPTIDEPAY_WEBHOOK_SECRET
2. `api/checkout` (server route / action)
- Validate catalog prices SERVER-SIDE (never trust the client). Re-load the cart from the DB or hard-coded catalog.
- Call `createPeptidePaySession` with the authoritative total.
- Respond with a 303 redirect to the session's `url`, or JSON { url } for fetch-style calls.
3. `api/peptidepay-webhook` (server route)
- Disable automatic body parsing (Next.js App Router: Request.text() first).
- Verify the timestamped signature (step above). If invalid → 401.
- Load order by event.order_id (from the echoed metadata). If already paid → return 200 immediately (idempotent).
- Mark paid using event.txid + event.amount, enqueue email/fulfillment, return 200.
4. `api/order/[id]` (GET, for client polling on the success page)
- Load order from your DB.
- Return { status: 'pending' | 'paid', amount, currency }.
5. `order/[id]` page (success page)
- Client-side: poll /api/order/[id] every 3s. When status === 'paid', show the confirmation.
- Fallback: if still pending after 90s, show "Payment still processing, we'll email you" and keep polling silently.
6. Product pages: "Buy now" button → POST /api/checkout with { product_slug, quantity }.
7. Trust badge on the checkout CTA area:
<a href="https://peptide-pay.com" rel="noopener">Secured by Peptide-Pay</a>
=== STRICT DO ===
- DO HMAC timing-safe verify on every webhook.
- DO validate catalog prices on the server.
- DO use the exact env var names above.
- DO redirect to the session `url` returned by /checkout/init — it is Peptide-Pay's hosted checkout.
- DO keep all Peptide-Pay calls server-side only.
- DO add Idempotency-Key on retries of /checkout/init.
=== STRICT DON'T ===
- NEVER invent endpoints. Only the 3 listed above exist.
- NEVER expose PEPTIDEPAY_API_KEY or PEPTIDEPAY_WEBHOOK_SECRET to the browser.
- NEVER add credit-card input fields to my site — Peptide-Pay's hosted checkout is the ONLY place card data is collected.
- NEVER attempt to call any other payment rail — Peptide-Pay handles card, Apple Pay, Google Pay, and crypto internally.
- NEVER skip HMAC verification. Unsigned or mismatched webhooks = reject with 401.
- NEVER parse the webhook JSON before computing the HMAC — you'll corrupt the byte sequence and every signature will "mismatch".
=== REFERENCE ===
- API reference: https://peptide-pay.com/docs
- Payment flow diagram: https://peptide-pay.com/how-it-works
- Fee breakdown: https://peptide-pay.com/fees
- Merchant dashboard: https://peptide-pay.com/app
- Troubleshooting: https://peptide-pay.com/help
=== SELF-CHECK (run this BEFORE telling the user you're done) ===
After writing all the files, verify each of these. If any fails, fix it before shipping:
[ ] `lib/peptidepay.*` exists and exports `createPeptidePaySession` + `verifyPeptidePaySignature`.
[ ] `api/peptidepay-webhook` route exists and reads RAW body BEFORE parsing (see "NEVER parse the webhook body before hashing").
[ ] HMAC verification uses a TIMING-SAFE compare (`crypto.timingSafeEqual` / `hash_equals` / `hmac.compare_digest`).
[ ] `.env.example` (or equivalent) lists PEPTIDEPAY_WALLET, PEPTIDEPAY_WEBHOOK_SECRET, and PEPTIDEPAY_API_KEY (if used).
[ ] The checkout handler validates catalog prices server-side — no client-supplied totals reach /checkout/init.
[ ] The success page polls `/api/order/[id]` every 3s as a webhook fallback.
[ ] No credit-card form exists anywhere in the site (Peptide-Pay's hosted checkout is the only place card data lives).
[ ] The webhook handler is idempotent — receiving the same session_id twice has no side effects the second time.
[ ] Run a quick smoke: simulate a POST to /api/peptidepay-webhook with a handcrafted signed body. Confirm signature verification passes for valid sigs and returns 401 for tampered ones.
[ ] `PEPTIDEPAY_API_KEY` in `.env` starts with `sk_live_` (not `sk_test_` — that one is for the webhook-simulator endpoint only).
[ ] You ran the SMOKE TEST curl above and got HTTP 200 with an `{ id, url, status }` body — not 400/401.
[ ] Body of /checkout/init does NOT include `wallet` if you set the Authorization header (the header is the identity).
If all boxes are checked, PRINT the exact "WHAT YOU MUST DO NEXT" block below (verbatim — don't summarize it, don't translate it, don't paraphrase it). This is the moment where the human takes over.
=== WHAT YOU MUST DO NEXT (print this verbatim to the user after the self-check passes) ===
Hey — the code is done, but there are 4 things YOU (not me, the AI) have to do manually before this works. Without these, payments will succeed but your site will stay stuck on "pending" forever.
1. 🟦 DEPLOY YOUR SITE FIRST
Lovable / v0 / Bolt → click the "Publish" or "Deploy" button.
Write down the final URL you get (something like https://your-site.lovable.app).
2. 🟦 GRAB YOUR WEBHOOK SECRET FROM PEPTIDE-PAY
Go to → https://peptide-pay.com/app/api-keys
If you don't have an account yet: https://peptide-pay.com/signup (takes 30 seconds — no KYC).
Copy the string that starts with `whsec_…` .
3. 🟦 PASTE THE SECRET INTO YOUR .env
Open your project's .env (or environment variables settings on your hosting).
Add: PEPTIDEPAY_WEBHOOK_SECRET=whsec_… (the value you just copied)
Redeploy so the new env var is loaded.
4. 🟦 TELL PEPTIDE-PAY WHERE TO SEND ORDERS
Go to → https://peptide-pay.com/app/settings
In the "Webhook URL" field at the top, paste:
https://your-site.lovable.app/api/peptidepay-webhook
↑ replace "your-site.lovable.app" with YOUR deployed domain from step 1.
Click "Save webhook URL".
Then click "Send test webhook" — you should see a green ✅ within 2 seconds.
If it's red: read the error message (we give you a specific hint for each failure mode).
✅ Once "Send test webhook" returns ✅, you're done. Run a 1-euro test payment to confirm end-to-end.
❌ Skip any of these 4 steps and your orders WILL silently break. Please don't guess — do all 4 in order.
Your AI will push the code. Click below once your live URL is working.
When a customer pays, we POST a notification to YOUR site so it can mark the order as paid. We need that URL — it's your-deployed-site + /api/peptidepay-webhook.
In plain English: the AI prompt you pasted in step 2 created a route called /api/peptidepay-webhook on your site. After you deployed (step 3), that route is live at https://YOUR-SITE.com/api/peptidepay-webhook. Paste that full URL below — we'll POST test data to it in 2 seconds to confirm it works.
https://your-app.lovable.app/api/peptidepay-webhookhttps://your-app.vercel.app/api/peptidepay-webhookhttps://mystore.com/api/peptidepay-webhookWithout a webhook URL, your site has no way to know when a customer has finished paying. Orders stay stuck in "pending" until you manually check. With it, the moment a customer pays, your site flips the order to "paid" and triggers fulfillment (shipping email, inventory deduction, etc.) automatically.
4242 4242 4242 4242 with any future expiry. Point your webhook at an ngrok tunnel to see the signed POST end-to-end.