Peptide-Pay API
Kart ve kripto için REST API, kontrol ettiğin bir USDC wallet'a settlement. Bir POST checkout oluşturur. Bir webhook ödendiğini söyler. 30 dakikanın altında canlıya al.
Başlarken
Peptide-Pay dört entegrasyon modunu destekliyor. Kısıtlamalarına uyanı seç; alttaki API aynı.
Drop-in buton, signup yok. USDC wallet adresini request body'de gönder. Sıfır backend state; public, DevTools'ta görünür.
Server-to-server. Wallet'ını Bearer sk_live_ arkasına sakla. Dashboard'dan branding, webhook'lar, mass payout'ları yapılandır.
Hazır eklenti. ZIP'i yükle, API key + webhook secret'ını yapıştır, siparişler ödemede otomatik tamamlanır. HPOS-ready, WC 7.0+.
Custom App + Manuel Ödeme Yöntemi. Mevcut bir mağazaya ~30 dakikada kurulum. Siparişleri Shopify Admin API üzerinden ödendi olarak işaretliyoruz.
Quickstart (5 dk)
Üç adım: session oluştur, müşteriyi yönlendir, webhook'u işle. Aşağıdaki örnek production-ready Node.js checkout route'u.
// Create a checkout session and redirect your customer.
// Authorization resolves the merchant wallet server-side — no wallet in the body.
const res = await fetch('https://peptide-pay.com/api/v1/checkout/init', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.PEPTIDEPAY_API_KEY}`, // sk_live_…
},
body: JSON.stringify({
amount_cents: 5000, // €50.00 — integer, in cents
currency: 'EUR', // EUR, USD, GBP, CAD, AUD, CHF
email: 'buyer@example.com', // optional, shown in checkout
success_url: 'https://mystore.com/success',
cancel_url: 'https://mystore.com/cart',
webhook_url: 'https://mystore.com/api/peptidepay-webhook',
metadata: { order_id: '1234' },
}),
});
const { id, url, tracking_number } = await res.json();
// => { id: 'cs_abc…', url: 'https://peptide-pay.com/session/cs_abc…',
// tracking_number: '0x…', provider: 'gateway', status: 'pending', … }
// Redirect your customer to the hosted checkout.
return Response.redirect(url, 303);Happy path'in tamamı bu. Müşteri 'ta hosted checkout'a düşer, kart veya kripto seçer, webhook'un ödeme sonrası 30 saniye içinde tetiklenir.
Authentication
Entegrasyon moduna göre iki şema:
| Şema | Nasıl | Ne zaman |
|---|---|---|
| Bearer token | Authorization: Bearer sk_live_… | Server-side. Wallet'ı gizli tutar. |
| Body'de wallet | { "wallet": "0x…", … } | Backend'siz static site / widget'lar. |
sk_live_… and an sk_test_… key. Use sk_live_ as your canonical key — that is what every example here uses. The sk_test_ key is provided for the webhook-receiver simulator at /api/v1/test/fire-webhook. Peptide-Pay settles real on-chain USDC — there is no test network. To dry-run an integration, run a $1 real payment and refund yourself.API referansı
Base URL: . Tüm endpoint'ler JSON konuşur, başarıda tek object döner, 4xx/5xx'te object döner.
#Checkout session oluştur
Hosted checkout URL üretir. Müşteri açar, kart veya kripto ile öder, Peptide-Pay wallet'ına USDC olarak settle eder, webhook tetiklenir.
| Alan | Tür | Zorunlu | Açıklama |
|---|---|---|---|
| amount_cents | integer | zorunlu | En küçük para birimi cinsinden tutar (cent). Aralık 100 – 10 000 000. |
| currency | string | zorunlu | ISO 4217 kodu. Desteklenen: EUR, USD, GBP, CAD, AUD, CHF. |
| wallet | string | one-of | Polygon'da USDC wallet (0x + 40 hex). Bearer key ile kimlik doğrulanmadıysa zorunlu. |
| customer_email | string | opsiyonel | Checkout UI'da gösterilir ve KYC yeniden kullanımı için on-ramp'a iletilir. |
| success_url | url | opsiyonel | Başarılı ödeme sonrası redirect. Sadece http/https. |
| cancel_url | url | opsiyonel | Müşteri checkout'u terk ederse redirect. |
| webhook_url | url | opsiyonel | order.paid event'leri için POST hedefi. Dashboard default'unu override eder. |
| provider | string | opsiyonel | Default 'gateway' (akıllı seçici — önerilen). Veya GET /providers'tan belirli bir on-ramp id'yi sabitle (ör. moonpay, revolut, banxa, transak). |
| product_name | string | opsiyonel | Checkout sayfasında gösterilen etiket (maks 80 karakter). |
| metadata | object | opsiyonel | En fazla 10 string key/value çifti, webhook'ta geri döner. Rezerve key: order_id. |
| Alan | Tür | Zorunlu | Açıklama |
|---|---|---|---|
| id | string | opsiyonel | Session id, cs_ ile başlar. |
| url | string | opsiyonel | Müşteriyi yönlendirilecek hosted checkout URL. |
| status | string | opsiyonel | Oluşturmada her zaman "pending". |
| amount | integer | opsiyonel | amount_cents yankısı. |
| currency | string | opsiyonel | currency yankısı. |
| provider | string | opsiyonel | provider yankısı (default 'gateway'). |
| expires_at | string | opsiyonel | ISO 8601 expiry (oluşturmadan 24 saat). |
| tracking_number | string | opsiyonel | Polygon settlement adresi — webhook payload'undaki address_in ile eşleşir, canlı takip için /track ile kullanılır. |
Örnekler
// Node.js 18+
const res = await fetch('https://peptide-pay.com/api/v1/checkout/init', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.PEPTIDEPAY_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(), // safe double-submit
},
body: JSON.stringify({
amount_cents: 5000,
currency: 'EUR',
email: 'buyer@example.com',
success_url: 'https://mystore.com/success',
cancel_url: 'https://mystore.com/cart',
metadata: { order_id: '1234' },
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { id, url } = await res.json();
return Response.redirect(url, 303);#Session al (polling)
Bunu webhook fallback olarak veya redirect sonrası success sayfasını hydrate etmek için kullan. Server-side her çağrıda settlement katmanımızı yeniden kontrol eder — ucuz (<200ms), 3-5sn'de bir poll gayet iyi.
| Alan | Tür | Zorunlu | Açıklama |
|---|---|---|---|
| id | string | opsiyonel | Session id. |
| status | string | opsiyonel | pending | paid | expired | failed. |
| amount | integer | opsiyonel | Orijinal tutar, cent olarak. |
| currency | string | opsiyonel | Orijinal para birimi. |
| paid_at | string|null | opsiyonel | On-chain settlement tamamlandığında ISO 8601. |
| paid_provider | string|null | opsiyonel | Ödemeyi gerçekten işleyen provider (istenenden farklı olabilir). |
| txid | string|null | opsiyonel | Polygon settlement txid. polygonscan.com/tx/{txid} ile linkle. |
| expires_at | string | opsiyonel | ISO 8601 expiry. |
// Poll every 3-5 seconds until terminal state. Use webhooks for push-
// delivery in production; polling is the fallback when webhooks are down.
async function waitForPayment(sessionId, { timeoutMs = 15 * 60 * 1000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const res = await fetch(`https://peptide-pay.com/api/v1/sessions/${sessionId}`);
const s = await res.json();
if (s.status === 'paid') return s; // terminal: success
if (s.status === 'expired') throw new Error('Session expired');
if (s.status === 'failed') throw new Error('Payment failed');
await new Promise(r => setTimeout(r, 4000));
}
throw new Error('Polling timeout');
}#Canlı provider matrisi
Şu anda trafik kabul eden on-ramp'ları, provider başına minimum tutarla listeler. Edge'de 5 dk cache'li — app boot'ta bir kez poll et, her request'te değil.
| Alan | Tür | Zorunlu | Açıklama |
|---|---|---|---|
| providers[].id | string | opsiyonel | Provider key (/checkout/init'te `provider` olarak geçilebilir). |
| providers[].provider_name | string | opsiyonel | Dropdown için insan okunur etiket. |
| providers[].status | string | opsiyonel | 'active' (bu endpoint'te her zaman active filtrelenir). |
| providers[].minimum_currency | string | opsiyonel | Minimum'un ISO kodu. |
| providers[].minimum_amount | number | opsiyonel | Provider'ın kabul ettiği en düşük tutar (minimum_currency biriminde). |
curl -sS 'https://peptide-pay.com/api/v1/providers' | jq '.providers[] | {id, provider_name, minimum_currency, minimum_amount}'
# [
# { "id": "gateway", "provider_name": "Smart (recommended)", "minimum_currency": "USD", "minimum_amount": 1 },
# { "id": "moonpay", "provider_name": "Moonpay", "minimum_currency": "EUR", "minimum_amount": 20 },
# { "id": "revolut", "provider_name": "Revolut Ramp", "minimum_currency": "EUR", "minimum_amount": 10 },
# { "id": "binance", "provider_name": "Binance Pay", "minimum_currency": "EUR", "minimum_amount": 15 },
# …
# ]
# Cache: 5 minutes at the edge. Call once per deploy, not per request.Webhook'lar
Bir session terminal state'e ulaştığında yapılandırdığın 'e (session başına veya dashboard'da) imzalı bir JSON event POST ederiz. İmza doğrulama için her zaman request body'yi parse et — JSON'u yeniden serialize etmek key sırasını bozar ve HMAC kırılır.
POST /your-endpoint HTTP/1.1
Host: mystore.com
Content-Type: application/json
x-peptidepay-signature: t=1745300551,v1=3f9b5c1e8a7d… ← HMAC-SHA256, hex
{
"event": "order.paid",
"session_id": "cs_abc123",
"order_id": "1234",
"address_in": "0xAb12…",
"status": "paid",
"amount": 5000,
"currency": "EUR",
"txid": "0xfa89b2…",
"paid_at": "2026-04-23T10:02:31.000Z",
"attempt": 1
}Event türleri
| Event | Ne zaman |
|---|---|
| order.paid | On-chain settlement onaylandı. + + garanti mevcut. Siparişi ödendi işaretle. |
Bugün sadece teslim ediliyor — expired ve failed session'lar ile gözlemlenebilir (24 saat TTL sonrası status olur; terminal failure'lar gösterir). İleride bunlar için push event ekleyebiliriz.
İmza doğrulama
Signup hesabı olan merchant'lar bir secret alır ve her teslimat formunda header taşır. hesapla ve ile constant-time karşılaştır. 5 dakikadan eskisini reddet.
// Node.js — Express/Next.js route handler
import crypto from 'node:crypto';
const SECRET = process.env.PEPTIDEPAY_WEBHOOK_SECRET; // dashboard → Webhooks
export async function POST(req) {
const rawBody = await req.text(); // MUST be the raw bytes
const header = req.headers.get('x-peptidepay-signature') ?? '';
const [ tPart, v1Part ] = header.split(',');
const t = tPart?.split('=')[1];
const v1 = v1Part?.split('=')[1];
if (!t || !v1) return new Response('bad sig', { status: 400 });
// Reject replays older than 5 minutes.
if (Math.abs(Date.now() / 1000 - Number(t)) > 300)
return new Response('stale', { status: 400 });
const expected = crypto
.createHmac('sha256', SECRET)
.update(`${t}.${rawBody}`)
.digest('hex');
const ok =
v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(v1, 'hex'), Buffer.from(expected, 'hex'));
if (!ok) return new Response('invalid sig', { status: 401 });
const event = JSON.parse(rawBody);
// Idempotency: dedupe by event.session_id in your DB — retries re-fire
// the same event (with an incrementing "attempt" field) until you 2xx.
if (event.event === 'order.paid') {
await markOrderPaid(event.order_id, event.txid);
}
return new Response('ok');
}Retry politikası
Non-2xx response'ları (ve >5sn timeout'ları) exponential backoff ile tekrar deneriz. ~42 saatte toplam altı deneme:
- Deneme 1 — onaydan hemen sonra.
- Deneme 2 — +5 dakika.
- Deneme 3 — +15 dakika.
- Deneme 4 — +1 saat.
- Deneme 5 — +4 saat.
- Deneme 6 — +12 saat, sonra +24 saat (son).
6 başarısız denemeden sonra event dead-letter olur. Mevcut state'i istediğin zaman ile yeniden talep edebilirsin.
Sık karşılaşılan sorunlar
- Her teslimatta 'invalid signature' görüyorum
- Framework'ün hash'lemeden önce body'yi JSON parse etti. RAW byte'ları oku (Express: express.raw({type:'*/*'}); Next.js: req.text(); Laravel: request()->getContent(); Rails: request.raw_post). Hash'lemeden önce asla yeniden serialize etme.
- IP whitelist — hangi IP'lerden gönderiyorsunuz?
- Teslimatlar şu anda Vercel Edge'den (dinamik IP'ler) geliyor. Statik aralık yayınlamıyoruz. MUTLAKA whitelist yapman gerekiyorsa, imza header'ını auth gate olarak kullan ve herhangi bir source IP'yi kabul et — HMAC gerçek kimlik kontrolü.
- HTTPS zorunlu mu?
- Evet. http:// endpoint'lere POST yapmayı reddederiz (confusable deputy / plaintext replay riski). ngrok'un ücretsiz https URL'i local test için gayet iyi.
- Endpoint'im yavaş — 5sn timeout'u uzatabilir miyim?
- Hayır. Hemen 2xx cevapla, sonra asenkron işle (job queue, setImmediate, goroutine). Uzun bloklayan handler'lar her zaman timeout olur.
SDK'lar
API yeterince küçük, sadece gayet iyi — ama Node SDK sana type'ları, otomatik retry'ı ve imza doğrulamayı senin yerine yapan bir helper'ı veriyor.
// npm install github:kinerette/peptide-pay-sdk
import { PeptidePay } from 'peptide-pay';
const pp = new PeptidePay(process.env.PEPTIDEPAY_API_KEY);
// Create a session
const session = await pp.checkout.create({
amount_cents: 5000,
currency: 'EUR',
customer_email: 'buyer@example.com',
success_url: 'https://mystore.com/success',
cancel_url: 'https://mystore.com/cart',
metadata: { order_id: '1234' },
});
// Retrieve a session
const latest = await pp.sessions.retrieve(session.id);
// Verify + parse a webhook (throws on invalid signature)
app.post('/webhooks/peptidepay', express.raw({ type: '*/*' }), (req, res) => {
const event = pp.webhooks.constructEvent(
req.body,
req.headers['x-peptidepay-signature'],
process.env.PEPTIDEPAY_WEBHOOK_SECRET,
);
// event.event === 'order.paid' (currently the only event delivered)
res.sendStatus(200);
});peptide-payTam type'lar, webhook helper, otomatik retry.
herhangi bir dilBir POST, bir GET. Library gerekmez.
Komisyonlar
Sabit — Peptide-Pay'in tam komisyonu. Subscription yok, aylık yok, chargeback komisyonu yok. Kart on-ramp komisyonları (~%4.5, upstream kart processor'dan) pass-through — müşteri öder, senin payout'una dokunmaz.
| Ödeme yöntemi | Sen ödersin | Müşteri öder |
|---|---|---|
| Kart / Apple Pay / Google Pay | %3 | ~%4.5 (on-ramp, pass-through) |
| Direkt kripto (USDC → USDC) | %3 | sadece gas (~$0.01 Polygon'da) |
Çözümlü örneklerle tam breakdown: /fees.
Test
Her yeni merchant hesabı bedava alır — %3 komisyonun tamamı 24 saat içinde wallet'a iade edilir. Canlıya almadan önce uçtan uca akışı (gerçek kart, gerçek USDC, gerçek webhook) prova etmek için bunları kullan.
- Sandbox mode otomatik: merchant başına ilk 3 ödenen session olarak işaretlenir ve auto-refund'a uygun olur.
- MoonPay dev kartı: , herhangi bir gelecek expiry, herhangi bir CVV, ZIP 10001.
- Local webhook testi: localhost'u ngrok ile expose et, URL'i her session'ın alanına yapıştır.
Tam local loop (ngrok)
# 1. Expose your local webhook endpoint
ngrok http 3000
# 2. Copy the https://xxxx.ngrok-free.app URL and paste it into
# Dashboard → Webhooks → Endpoint URL, OR send it inline:
curl -X POST 'https://peptide-pay.com/api/v1/checkout/init' \
-H "Authorization: Bearer $PEPTIDEPAY_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"amount_cents": 100,
"currency": "EUR",
"customer_email": "test+sandbox@yours.com",
"success_url": "https://yours.com/success",
"cancel_url": "https://yours.com/cart",
"webhook_url": "https://xxxx.ngrok-free.app/webhooks/peptidepay"
}'
# 3. Open the returned `url`, hit MoonPay's dev test card
# 4242 4242 4242 4242 (any future exp, any CVV).
# 4. Your local endpoint receives the signed POST within ~30s of payment.Hatalar & rate limit'ler
Tüm hatalar yapısını paylaşır. Status code'lar standart REST.
400401403404429502Troubleshooting
- Session dashboard'da 'paid' ama webhook'um hiç tetiklenmedi
- webhook_url'inin public HTTPS üzerinden erişilebilir olduğunu kontrol et (LAN dışından curl at). Doğruysa, GET /sessions/{id} ile poll edip status'u onayla — dashboard /app webhook delivery istatistiklerini gösterir (başarı oranı, sayılar). Dead-letter'dan önce 42 saatte altı deneme; her zaman polling ile re-sync edebilirsin.
- HMAC mismatch — imza her zaman geçersiz
- %99 ihtimalle: raw byte'lar yerine yeniden serialize edilmiş body'yi hash'liyorsun. Framework'ler handler çalışmadan önce JSON'u otomatik parse eder; raw buffer'a ihtiyacın var. Next.js: herhangi bir .json()'dan önce req.text(). Express: app.use('/webhooks', express.raw({ type: '*/*' }), …). Rails: request.raw_post. Ayrıca `HMAC(whsec_secret, t + '.' + rawBody)` hesapladığını kontrol et — SADECE `HMAC(whsec_secret, rawBody)` DEĞİL. Timestamp prefix zorunlu.
- MoonPay 'service unavailable in your country' diyor
- MoonPay ~20 ülkeyi kısıtlıyor (İran, Kuzey Kore, Küba, tam liste sitelerinde). Default provider 'gateway' — akıllı seçici Revolut, Transak veya Banxa'ya fall-back yapar, farklı coğrafyaları kapsar. provider: 'moonpay' ile belirli bir provider sabitlediyeysen, kaldır ve router'ın seçmesine izin ver.
- Wallet'ım 'paid' event'inden sonra USDC almadı
- polygonscan.com/address/<your-wallet>i USDC (Polygon POS) transferler için kontrol et. Settlement %97 sana ve %3 Peptide-Pay'e düşer - %97 inbound'u görmüyorsan, init çağrısında yanlış wallet yapıştırmış olabilirsin. GET /sessions/{id} ile yeniden doğrula - txid alanı gerçek on-chain transfere işaret eder.
- Müşteriden iki kez tahsilat yapıldı
- Olmamalı. Her session'ın tek bir settlement addressIn'i var; aynı adrese ikinci bir ödeme bizde ayrı bir session olur ve sipariş için sadece ilkini credit ederiz. Olduysa iki polygonscan txid + session id ekran görüntüsü al ve hi@peptide-pay.com'a email at - duplicate'i hazinemizden iade ederiz.
- 502 'Payment infrastructure temporarily unavailable' alıyorum
- Settlement upstream'imiz bozuk (request'lerin < %0.5'i). Aynı Idempotency-Key ile 30sn sonra tekrar dene - wallet başarıyla oluştuğu anda cache orijinal response'u döner. Canlı olaylar için /status takip et.
Entegrasyona hazır mısın?
Çoğu merchant sıfırdan ilk ödenen işleme 30 dakikanın altında geçiyor.