Peptide-Pay API
カードと暗号資産で決済を行い、あなたが管理するUSDCウォレットに着金するためのREST API。1回のPOSTでチェックアウトを作成。1つのウェブフックで支払い通知。30分以内にリリース可能。
はじめに
Peptide-Payは4つの統合モードに対応しています。あなたの制約に合うものを選んでください。内部のAPIはすべて同じです。
ドロップイン型ボタン、サインアップ不要。リクエストボディにUSDCウォレットアドレスを渡します。バックエンドのステートはゼロ、パブリック、DevToolsで可視。
サーバー間通信。Bearer sk_live_ 背後でウォレットを隠蔽。ダッシュボードからブランディング、ウェブフック、一括ペイアウトを設定。
既製プラグイン。ZIPをアップロード、APIキー + ウェブフックシークレットを貼り付けると、支払い時に注文が自動完了。HPOS対応、WC 7.0+。
Custom App + Manual Payment Method。既存ストアに約30分でインストール。Shopify Admin API 経由で注文を支払い済みとしてマークします。
クイックスタート (5分)
3ステップ:セッション作成、お客様をリダイレクト、ウェブフックを処理。以下は本番利用可能なNode.jsチェックアウトルートのサンプルです。
// 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);これがハッピーパスの全体です。お客様はのホステッド・チェックアウトに着地し、カードまたは暗号資産を選択、支払いから30秒以内にウェブフックが発火します。
認証
統合モードに応じた2つの方式:
| 方式 | 方法 | タイミング |
|---|---|---|
| Bearerトークン | Authorization: Bearer sk_live_… | サーバーサイド。ウォレットを非公開に保ちます。 |
| ボディ内ウォレット | { "wallet": "0x…", … } | バックエンドのない静的サイト / ウィジェット。 |
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リファレンス
ベースURL: 。すべてのエンドポイントはJSONで通信し、成功時は単一オブジェクト、4xx/5xx時はオブジェクトを返します。
#チェックアウトセッションを作成
ホステッド・チェックアウトURLを発行します。お客様がそれを開き、カードまたは暗号資産で支払うと、Peptide-PayがあなたのウォレットにUSDCで決済し、ウェブフックが発火します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| amount_cents | integer | 必須 | 通貨の最小単位での金額(セント)。範囲 100 – 10,000,000。 |
| currency | string | 必須 | ISO 4217コード。対応:EUR、USD、GBP、CAD、AUD、CHF。 |
| wallet | string | いずれか | Polygon上のUSDCウォレット(0x + 40桁のhex)。Bearerキーで認証されていない場合は必須。 |
| customer_email | string | 任意 | チェックアウトUIに表示され、KYC再利用のためオンランプに転送されます。 |
| success_url | url | 任意 | 支払い成功後のリダイレクト先。http/httpsのみ。 |
| cancel_url | url | 任意 | お客様がチェックアウトを放棄した場合のリダイレクト先。 |
| webhook_url | url | 任意 | order.paidイベントのPOST先。ダッシュボードのデフォルトを上書きします。 |
| provider | string | 任意 | デフォルトは 'gateway' (スマートピッカー — 推奨)。またはGET /providersから特定のオンランプIDを固定(例:moonpay、revolut、banxa、transak)。 |
| product_name | string | 任意 | チェックアウトページに表示されるラベル(最大80文字)。 |
| metadata | object | 任意 | 最大10組の文字列キー/値ペア。ウェブフックでそのまま返却されます。予約キー:order_id。 |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| id | string | 任意 | セッションID、cs_で始まります。 |
| url | string | 任意 | お客様をリダイレクトするホステッド・チェックアウトURL。 |
| status | string | 任意 | 作成時は常に "pending"。 |
| amount | integer | 任意 | amount_centsのエコー。 |
| currency | string | 任意 | currencyのエコー。 |
| provider | string | 任意 | providerのエコー(デフォルト 'gateway')。 |
| expires_at | string | 任意 | ISO 8601形式の有効期限(作成から24時間)。 |
| tracking_number | string | 任意 | Polygon決済アドレス — ウェブフックペイロードのaddress_inと一致、/trackでライブ監視可能。 |
例
// 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);#セッションを取得(ポーリング)
ウェブフックのフォールバックとして、またはリダイレクト後に成功ページをハイドレートするのに使用。サーバーサイドで毎回決済レイヤを再確認 — 安価(200ms未満)のため、3〜5秒ごとのポーリングで問題ありません。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| id | string | 任意 | セッションID。 |
| status | string | 任意 | pending | paid | expired | failed。 |
| amount | integer | 任意 | 元の金額(セント)。 |
| currency | string | 任意 | 元の通貨。 |
| paid_at | string|null | 任意 | オンチェーン決済完了時のISO 8601タイムスタンプ。 |
| paid_provider | string|null | 任意 | 実際に支払いを処理したプロバイダ(リクエストされたものと異なる場合があります)。 |
| txid | string|null | 任意 | Polygon決済のtxid。polygonscan.com/tx/{txid}でリンクしてください。 |
| expires_at | string | 任意 | ISO 8601形式の有効期限。 |
// 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');
}#ライブプロバイダーマトリクス
現在トラフィックを受け付けているオンランプの一覧と、プロバイダーごとの最低金額。エッジで5分キャッシュ — アプリ起動時に1回ポーリング、リクエストごとではありません。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| providers[].id | string | 任意 | プロバイダーキー(/checkout/initの`provider`として渡せます)。 |
| providers[].provider_name | string | 任意 | ドロップダウン用の人間向けラベル。 |
| providers[].status | string | 任意 | 'active'(このエンドポイントは常にアクティブでフィルタ済み)。 |
| providers[].minimum_currency | string | 任意 | 最低金額のISOコード。 |
| providers[].minimum_amount | number | 任意 | プロバイダーが受け付ける最低金額(minimum_currency単位)。 |
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.ウェブフック
セッションが終端状態に達すると、署名付きのJSONイベントを設定された(セッションごと、またはダッシュボード設定)にPOSTします。署名検証のため常にのリクエストボディを解析してください — JSONを再シリアライズするとキーの順序が変わりHMACが壊れます。
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
}イベントの種類
| イベント | 条件 |
|---|---|
| order.paid | オンチェーン決済確認時。 + + は必ず存在。注文を支払い済みにマーク。 |
現在のみ配送 — 期限切れ・失敗セッションはで観測可能(24時間TTL後、終端の失敗は)。将来的にこれらへのプッシュイベントを追加する可能性があります。
署名検証
サインアップアカウントを持つマーチャントにはシークレットが付与され、すべての配送には形式のヘッダが含まれます。を計算し、と定数時間比較してください。5分以上古いものは拒否。
// 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');
}リトライポリシー
非2xxレスポンス(および5秒超タイムアウト)を指数バックオフでリトライ。約42時間で計6回:
- 試行1 — 確認直後すぐ。
- 試行2 — +5分。
- 試行3 — +15分。
- 試行4 — +1時間。
- 試行5 — +4時間。
- 試行6 — +12時間、その後+24時間(最終)。
6回の試行が失敗するとイベントはデッドレター化されます。で現状をいつでも再取得できます。
よくある問題
- すべての配送で「invalid signature」が出る
- フレームワークがハッシュ前にボディをJSONパースしています。生のバイトを読んでください(Express: express.raw({type:'*/*'}); Next.js: req.text(); Laravel: request()->getContent(); Rails: request.raw_post)。ハッシュ前に再シリアライズ禁止。
- IPホワイトリスト — どのIPから送信される?
- 配送は現在Vercel Edgeから発信(動的IP)。静的レンジは公開していません。どうしてもホワイトリストが必要な場合、署名ヘッダを認証ゲートとして使い、任意のソースIPを受け入れてください — HMACが真の身元確認です。
- HTTPS必須?
- はい。http://エンドポイントへのPOSTは拒否します(混乱代理 / 平文リプレイリスク)。ngrokの無料httpsは、ローカルテストで問題なく動作します。
- エンドポイントが遅い — 5秒タイムアウトを延長できる?
- いいえ。即座に2xxで応答し、非同期で処理してください(ジョブキュー、setImmediate、goroutine)。長時間ブロックするハンドラは必ずタイムアウトします。
SDK
APIはで十分小さいです — しかしNode SDKは型、自動リトライ、署名検証を代行するヘルパーを提供します。
// 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-pay完全な型、ウェブフックヘルパー、自動リトライ。
任意の言語1回のPOSTと1回のGET。ライブラリ不要。
手数料
定額 — Peptide-Payの全コミッション。サブスクリプションなし、月額なし、チャージバック手数料なし。カードオンランプ手数料(上流のカードプロセッサが課す約4.5%)はパススルー — お客様が支払い、あなたのペイアウトに触れません。
| 支払い方法 | あなたの負担 | お客様の負担 |
|---|---|---|
| カード / Apple Pay / Google Pay | 3% | 約4.5%(オンランプ、パススルー) |
| 暗号資産直接(USDC → USDC) | 3% | ガス代のみ(Polygonで約$0.01) |
詳細な内訳と計算例は /fees で。
テスト
すべての新規マーチャントアカウントにを無料提供 — 3%手数料は24時間以内にウォレットへ返金。本番前に完全なフロー(実カード、実USDC、実ウェブフック)をエンドツーエンドでリハーサルできます。
- サンドボックスモード は自動:マーチャントごとの最初の3支払い済みセッションがとしてマークされ、自動返金の対象になります。
- MoonPay開発用カード:、任意の将来の有効期限、任意のCVV、ZIP 10001。
- ローカルウェブフックテスト:ngrokでlocalhostを公開し、URLをセッションごとの欄に貼り付け。
完全なローカルループ(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.エラーとレート制限
すべてのエラーはの形を共有します。ステータスコードは標準RESTに準拠。
400401403404429502トラブルシューティング
- ダッシュボードでセッションが「paid」なのにウェブフックが発火しない
- webhook_urlがパブリックHTTPSで到達可能か確認(LAN外からcurl)。正しければGET /sessions/{id}でステータスをポーリング確認 — ダッシュボード/appでウェブフック配送統計(成功率、回数)が表示されます。デッドレターまで42時間で6試行。ポーリングで常に再同期可能。
- HMAC不一致 — 署名が常に無効
- 99%の原因:生バイトではなく再シリアライズ済みボディをハッシュしています。フレームワークはハンドラ実行前にJSONを自動パースするので、生バッファが必要です。Next.js:.json()の前にreq.text()。Express:app.use('/webhooks', express.raw({ type: '*/*' }), …)。Rails:request.raw_post。また、`HMAC(whsec_secret, t + '.' + rawBody)`を計算しているか確認 — `HMAC(whsec_secret, rawBody)`だけではダメ。タイムスタンププレフィックスは必須です。
- MoonPayが「お住まいの国ではサービスが利用できません」と表示
- MoonPayは約20カ国を制限しています(イラン、北朝鮮、キューバなど、全リストは公式サイト)。デフォルトプロバイダーは 'gateway' — スマートピッカーがRevolut、Transak、Banxaへ自動フォールバックし、異なる地域をカバーします。provider: 'moonpay' を固定している場合は削除し、ルーターに任せてください。
- 「paid」イベント後もウォレットがUSDCを受け取っていない
- polygonscan.com/address/<your-wallet> でUSDC(Polygon POS)転送を確認してください。決済は97%があなたに、3%がPeptide-Payに着金します - 97%の入金が見えない場合、init呼び出しで間違ったウォレットを貼り付けた可能性があります。GET /sessions/{id}でtxidフィールドを確認 - オンチェーン転送の実体を指します。
- お客様が二重請求された
- 起きないはずです。各セッションには1つの決済addressInがあり、同じアドレスへの2回目の支払いは当社側で別セッションとなり、最初のもののみ注文に計上されます。発生した場合、2つのpolygonscan txidとセッションIDのスクリーンショットをhi@peptide-pay.comにメール - トレジャリーから重複分を返金します。
- 「Payment infrastructure temporarily unavailable」の502が返る
- 決済上流が劣化(リクエストの0.5%未満)。同じIdempotency-Keyで30秒後にリトライ - ウォレット発行成功次第、キャッシュが元のレスポンスを返します。ライブインシデントは/statusで追跡。
導入準備はできましたか?
ほとんどのマーチャントはゼロから最初の支払い完了まで30分未満です。