1つのAPI、1つのホスト型フロー
CryptoPayInは、選択された表示通貨で注文の価格を決定し、検証済みの法定通貨/USDおよび暗号資産/USDのスナップショットを確定し、専用の入金アドレスを割り当てたうえで、自社のブロックチェーンノードで入金を監視します。内部会計・手数料・残高は常にUSD建てです。バックエンドにはチェックアウトURLが即座に返され、その後は署名付きのライフサイクルイベントが送信されます。
これは本番APIです。サンドボックス用のプレフィックスはありません。作成に成功するたびに、実際のオンチェーンアドレスが割り当てられます。エンドツーエンドのテストには対応通貨の少額を使用し、シークレットキーは必ずサーバー側で保管してください。
統合の全体像
ダッシュボード → 開発者向けで一度だけシークレットを生成します。
注文の通貨・金額・選択したアセットをPOSTします。
返されたホスト型URLへお客様を案内します。
HMACを検証し、注文を冪等に更新します。
最初の決済を作成する
加盟店ダッシュボードでAPIキーを生成し、シークレットを環境変数に保存したうえで、バックエンドから決済を作成します。この例ではETHを使用しているため、トークンのネットワークを選択せずにテストできます。
curl --request POST https://cryptopayin.com/v1/payments \
--header "Authorization: Bearer $CPI_SECRET_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: order_1042" \
--data '{
"amount": 49.99,
"currency": "USD",
"asset": "ETH",
"order_ref": "order_1042",
"redirect_url": "https://shop.example/orders/1042/paid"
}'
const response = await fetch("https://cryptopayin.com/v1/payments", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.CPI_SECRET_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "order_1042"
},
body: JSON.stringify({
amount: 49.99, currency: "USD", asset: "ETH",
order_ref: "order_1042",
redirect_url: "https://shop.example/orders/1042/paid"
})
});
if (!response.ok) throw new Error(await response.text());
const payment = await response.json();
$payload = json_encode([
'amount' => 49.99, 'currency' => 'USD', 'asset' => 'ETH',
'order_ref' => 'order_1042',
'redirect_url' => 'https://shop.example/orders/1042/paid',
]);
$ch = curl_init('https://cryptopayin.com/v1/payments');
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CPI_SECRET_KEY'),
'Content-Type: application/json',
'Idempotency-Key: order_1042',
],
]);
$payment = json_decode(curl_exec($ch), true, flags: JSON_THROW_ON_ERROR);
import os, requests
response = requests.post(
"https://cryptopayin.com/v1/payments",
headers={
"Authorization": f"Bearer {os.environ['CPI_SECRET_KEY']}",
"Idempotency-Key": "order_1042",
},
json={
"amount": 49.99, "currency": "USD", "asset": "ETH",
"order_ref": "order_1042",
"redirect_url": "https://shop.example/orders/1042/paid",
}, timeout=15,
)
response.raise_for_status()
payment = response.json()レスポンスを利用する
決済のidを注文情報とあわせて保存し、その後お客様をcheckout_urlへリダイレクトしてください。暗号資産の金額や入金アドレスを自分で計算しないでください。
{
"id": "P-9F27C1E4KD",
"object": "payment",
"status": "created",
"amount": 49.99,
"amount_decimal": "49.99",
"amount_minor": 4999,
"currency": "USD",
"currency_minor_units": 2,
"amount_usd": 49.99,
"amount_usd_cents": 4999,
"fx_rate_usd": "1.000000000000",
"fx_source": "fixed:USD",
"fx_observed_at": "2026-07-17T13:00:00+00:00",
"fx_discrepancy_bps": 0,
"asset": "ETH",
"network": "mainnet",
"crypto_amount": "0.01388612",
"crypto_received": "0",
"deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
"exchange_rate": "3600.00000000",
"exchange_rate_currency": "USD",
"exchange_rate_source": "median:cb,cg,cl",
"exchange_rate_source_count": 3,
"exchange_rate_observed_at": "2026-07-17T13:00:00+00:00",
"exchange_rate_discrepancy_bps": 12,
"confirmations": 0,
"confirmations_required": 12,
"order_ref": "order_1042",
"checkout_url": "https://cryptopayin.com/i/P-9F27C1E4KD",
"expires_at": "2026-07-17T13:30:00+00:00",
"created_at": "2026-07-17T13:00:00+00:00",
"completed_at": null
}認証
すべてのAPIリクエストは、HTTPのBearerヘッダーにシークレットキーを付与して認証します。シークレットキーはcsk_live_で始まります。対になるcpk_live_の値はダッシュボード用の公開識別子であり、Bearer認証情報として使用してはいけません。
Authorization: Bearer csk_live_...すべてのエンドポイント生のシークレットが返されるのは、キー作成時の一度だけです。CryptoPayInはパスワードハッシュとインデックス付きSHA-256ルックアップのみを保存し、平文のシークレットは保存しません。
アプリケーションや環境ごとに個別のキーを作成し、それぞれを独立して失効させることができます。1つのアカウントにつき、有効なキーは最大50個まで保持できます。
csk_live_の値は、ブラウザのJavaScript、モバイルアプリのバイナリ、公開リポジトリ、チェックアウトページのいずれにも絶対に含めないでください。
Webhookエンドポイントはアカウント全体に紐づけることも、特定のAPIキー1つに紐づけることもでき、統合ごとに分離できます。
シークレットが未指定・形式不正・失効済み・不明のいずれかである場合は401 unauthorizedが返されます。停止または解約済みの加盟店アカウントも同様に拒否されます。有効なキーであっても、付与された権限の範囲外で使用された場合は403 insufficient_scopeが返されます。
冪等性
決済を作成するたびに、一意のIdempotency-Keyを送信してください。送信後に接続が切れた場合は、同一のJSONを同一のキーで再送してください。CryptoPayInは新たなアドレスを割り当てる代わりに、最初の決済をそのまま返します。
| ケース | 結果 | HTTP |
|---|---|---|
| 初回利用 | 新しい決済を作成して返します。 | 201 |
| 同じキー+同じJSON | Idempotent-Replayed: trueとともに、既存の決済を返します。 | 200 |
| 同じキー+異なるJSON | idempotency_conflictとしてリクエストを拒否します。 | 409 |
キーはAPI認証情報単位でスコープされ、半角の英字・数字・ピリオド・アンダースコア・コロン・ハイフンを1-128文字含めることができます。永続的な注文UUIDを使うとよいでしょう。同じ仕組みは出金も保護しており、再試行された出金が資金を二重に移動させることはありません。
APIリファレンス
このAPIは、決済・決済リンク・ショップ・商品・残高・出金をカバーしています。レスポンスはHTTPS上のUTF-8 JSONで返され、作成・更新にはいずれもContent-Type: application/jsonが必要です。更新系の操作は、呼び出し元キーの権限によって制御されます。ブラウザ向けのCORSワークフローは意図的に提供していません。呼び出しはバックエンドから行ってください。
/v1/assets利用可能なアセットを確認/v1/currencies表示可能な法定通貨を確認/v1/payments決済を作成/v1/payments決済の一覧・絞り込み/v1/payments/{id}決済を取得バージョン1には、後方互換性のあるフィールドやエンドポイントが追加される場合があります。互換性を破る変更を行う場合は、/v1を黙って変更するのではなく、新しいベースパスを使用します。
アセット一覧を取得
/v1/assetsBearer認証が必要チェックアウトで選択肢を決める際は、このエンドポイントを正とみなしてください。有効なカタログ項目、現在の独立検証済みレート、USD換算の最低金額、およびノードと価格フィードの準備状況を返します。ノードが同期中であったり価格を検証できない場合でも、項目はavailable: falseのまま一覧に残ることがあります。
curl https://cryptopayin.com/v1/assets \
--header "Authorization: Bearer $CPI_SECRET_KEY"{
"object": "list",
"data": [{
"asset": "USDT",
"network": "TRC20",
"type": "token",
"decimals": 6,
"minimum_amount": 1,
"currency": "USD",
"base_confirmations": 19,
"available": true,
"rate_usd": "1.00000000",
"rate_source": "median:cb,cg,cl",
"rate_source_count": 3,
"rate_discrepancy_bps": 4,
"rate_status": "healthy",
"rate_updated_at": "2026-07-17T13:00:00+00:00"
}]
}カタログとネットワーク識別子
| アセット | ネットワーク値 | 省略形 | 基本承認数 |
|---|---|---|---|
| BTC | mainnet | BTC | 2 |
| ETH | mainnet | ETH | 6 |
| USDT | TRC20 / ERC20 | USDT.TRC20 | 19 / 6 |
| USDC | ERC20 | USDC.ERC20 | 6 |
| DAI | ERC20 | DAI | 6 |
| SHIB | ERC20 | SHIB | 6 |
| PEPE | ERC20 | PEPE | 6 |
| LTC | mainnet | LTC | 6 |
| TRX | mainnet | TRX | 19 |
| DOGE | mainnet | DOGE | 20 |
| XMR | mainnet | XMR | 10 |
| SOL | mainnet | SOL | 32 |
対応状況は常に変動します。上記の表を、そのまま有効な許可リストとしてハードコードしないでください。USDTのように複数ネットワークにまたがるシンボルについては、networkを明示的に送信するか、ASSET.NETWORKの省略形を使用してください。
法定通貨一覧を取得
/v1/currenciesBearer認証が必要有効な表示通貨、そのISO精度、および現在のUSD換算の健全性を返します。available: trueが付いた行のみを提示してください。USDは基軸通貨として内在的に扱われますが、それ以外の通貨はすべて、最新のライブレートと独立した参照チェックが必要です。minimum_amountは、設定済みの有効アセットのうち最も低い下限額をその通貨に換算した値です。選択したアセットによってはより高い金額が必要になる場合があるため、必ずGET /v1/assetsもあわせて確認してください。
curl https://cryptopayin.com/v1/currencies \
--header "Authorization: Bearer $CPI_SECRET_KEY"{
"object": "list",
"accounting_currency": "USD",
"data": [{
"currency": "EUR",
"name": "Euro",
"symbol": "€",
"minor_units": 2,
"available": true,
"minimum_amount": "0.86",
"rate_usd": "1.160000000000",
"rate_source": "coinbase+ecb",
"rate_source_count": 2,
"rate_discrepancy_bps": 18,
"rate_updated_at": "2026-07-17T13:00:00+00:00",
"rate_reference_at": "2026-07-16T00:00:00+00:00"
}]
}後方互換性のため、POST /v1/paymentsでcurrencyを省略した場合もUSDを意味します。JPYのような小数点のない通貨では、端数のある金額は拒否されます。カタログの最低金額やレートは常にライブデータとして扱い、固定値としてハードコードしないでください。
決済を作成
/v1/payments120リクエスト/分/キー指定された表示通貨で請求書を作成し、検証済みの最新の法定通貨/USDおよび暗号資産/USDのスナップショットを確定したうえで、正確な暗号資産の金額を計算し、専用のオンチェーン入金アドレスを紐づけます。
リクエストボディ
| フィールド | 型 | 必須/任意 | 説明 |
|---|---|---|---|
| amount | 数値または10進数文字列 | 必須 | currencyでの金額を、その通貨のISO精度で指定します。ロックされたUSD換算額は$1,000,000.00を超えることはできません。アセットごとの最低金額も適用されます。 |
| currency | 文字列 | 任意 | GET /v1/currenciesに含まれる、有効な3文字の通貨コード。デフォルトはUSDです。 |
| asset | 文字列 | 必須 | ETHのようなシンボル、またはUSDT.TRC20のような省略形を指定します。 |
| network | 文字列 | 条件付き | シンボルが複数のネットワークに存在する場合に必須です。例:ERC20。 |
| order_ref | 文字列 | 任意 | 貴社側の注文識別子(最大128文字)。APIレスポンスおよびイベントに含めて返されます。 |
| customer_email | 文字列 | 任意 | 有効なメールアドレス(最大190文字)。加盟店の決済レコードとともに保存されます。 |
| redirect_url | 文字列 | 任意 | HTTPSのURL(最大255文字)。チェックアウト完了後に提示されます。 |
レスポンスフィールド
| フィールド | 型 | 説明 |
|---|---|---|
| id | 文字列 | P-で始まる、不変の決済識別子。 |
| status | 文字列 | 現在のライフサイクル状態。 |
| amount / amount_decimal / amount_minor | 数値 / 文字列 / 整数 | 要求された表示金額を、扱いやすい数値・正確な10進数・ISO補助単位の3形式で表します。 |
| currency / currency_minor_units | 文字列 / 整数 | 確定した表示通貨とその精度。 |
| amount_usd / amount_usd_cents | 数値 / 整数 | 内部会計用の、変更不可なUSD建て金額。 |
| fx_rate_usd / fx_source / fx_observed_at | 10進数文字列 / 文字列 / ISO 8601 | 表示通貨1単位あたりのUSDレートを確定したスナップショットと、その監査用メタデータ。 |
| asset / network | 文字列 | 解決済みのオンチェーンアセット。 |
| crypto_amount | 10進数文字列 | お客様が送金すべき正確な金額。暗号資産の小数値をバイナリの浮動小数点数として扱わないでください。 |
| crypto_received | 10進数文字列 | 現時点で入金アドレスに着金が確認されている合計額。 |
| deposit_address | 文字列 | この決済のために割り当てられた専用アドレス。 |
| exchange_rate | 10進数文字列 | crypto_amountの計算に使用された、確定済みの暗号資産/USDレート。このフィールドはv1当初の意味のまま維持されます。 |
| exchange_rate_source / exchange_rate_observed_at | 文字列 / ISO 8601 | 変更不可な、暗号資産レートの監査用スナップショット。 |
| confirmations | 整数 | 現在のネットワーク承認数。 |
| confirmations_required | 整数 | この決済に必要な承認数のしきい値。USD建て金額が高いほど、追加の承認が必要になる場合があります。 |
| checkout_url | URL | お客様に提示する、ホスト型の請求書ページ。 |
| expires_at | ISO 8601 | 未払いの請求書の期限。 |
| completed_at | ISO 8601 / null | 決済完了時の、最終的な決済確定日時。 |
作成の前に、2つのライブ換算レートについて、鮮度・情報源の数・乖離幅が検証されます。検証に失敗した場合、古いレートを使う代わりにエラーを返して作成を中止します。暗号資産の金額はアセットの実用的な精度で切り上げられるため、端数処理によって加盟店側が不足することはありません。
決済一覧を取得
/v1/payments240リクエスト/分/キー認証された加盟店アカウントの決済を、新しい順に返します。突合作業にはカーソルページネーションを使用し、履歴全体を辿ることなく特定の注文を見つけるには、正確な絞り込み条件を使用してください。
クエリパラメータ
| パラメータ | デフォルト | 説明 |
|---|---|---|
| limit | 20 | 1〜100の範囲で指定するページサイズ。 |
| starting_after | — | 前ページのnext_cursorとして返された決済ID。 |
| status | — | pending、completed、expiredのような、厳密なライフサイクルステータス。 |
| order_ref | — | 加盟店側の厳密な注文参照(最大128文字)。 |
curl "https://cryptopayin.com/v1/payments?status=completed&limit=20" \
--header "Authorization: Bearer $CPI_SECRET_KEY"{
"object": "list",
"data": [{
"id": "P-9F27C1E4KD",
"object": "payment",
"status": "completed",
"amount": 49.99,
"currency": "USD",
"asset": "ETH",
"network": "mainnet",
"crypto_amount": "0.01388612",
"crypto_received": "0.01388612",
"order_ref": "order_1042",
"confirmations": 12,
"confirmations_required": 12,
"completed_at": "2026-07-17T13:12:42+00:00"
}],
"has_more": true,
"next_cursor": "P-9F27C1E4KD"
}has_moreがtrueの場合は、next_cursorをそのままstarting_afterとして渡してください。未知の、または重複した配列形式のクエリパラメータは、無視されるのではなく拒否されます。
決済を取得
/v1/payments/{id}240リクエスト/分/キー作成時と同じ決済オブジェクトを、最新のステータス・着金額・トランザクションハッシュ・承認数とともに返します。キーは、自身の加盟店アカウントに属する決済のみを取得できます。
curl https://cryptopayin.com/v1/payments/P-9F27C1E4KD \
--header "Authorization: Bearer $CPI_SECRET_KEY"通常の注文更新はWebhookで駆動するようにしてください。タイムアウト後の突合、イベントの検証、バックエンドのステータスページ表示、配信漏れの復旧には、この取得エンドポイントを使用します。
決済のライフサイクル
常にAPIのステータスを正とみなしてください。ブラウザのリダイレクトや、お客様の「支払った」という申告から完了を推測しないでください。
| ステータス | 意味 | 加盟店側の対応 |
|---|---|---|
| created | 請求書とアドレスが割り当てられた状態。まだ入金は検出されていません。 | ホスト型チェックアウトを表示します。 |
| pending | 利用可能なオンチェーン入金を待っている状態。 | 注文をオープンのまま維持します。 |
| underpaid | 加盟店の許容範囲を下回る金額が着金した状態。 | 表示されている残額を送金するよう、支払人に依頼します。 |
| confirming | 十分な金額が検出され、承認を待っている状態。 | まだ商品・サービスを提供しないでください。 |
| completed | 必要な金額と承認数の両方に達した状態。 | 1回だけ確実に商品・サービスを提供します。 |
| overpaid | 想定より多い金額が承認された状態。 | 商品・サービスを提供したうえで、超過分を確認します。 |
| expired | 有効期限までに条件を満たす入金が検出されなかった状態。 | 新しい決済を作成します。 |
| failed | アドレス割り当てまたは処理に失敗した状態。 | エラーを記録し、新しい決済を作成します。 |
オンチェーンの送金は取り消しができず、CryptoPayInには返金の仕組みがありません — 承認された決済は最終的なものです。任意の返金対応が必要な場合は、プラットフォームの外で、貴社とお客様の間で直接行ってください。
ホスト型チェックアウト
APIで作成された各決済には、レスポンシブ対応のcheckout_urlが含まれます。加盟店名、要求された表示金額、該当する場合はロックされたUSD換算額、正確な暗号資産の金額、入金アドレス、QRコード、ネットワークに関する注意事項、カウントダウン、リアルタイムの承認進捗が表示されます。
お客様には、その請求書の有効期間中、APIが返したものと同じcrypto_amountが表示されます。
支払人はCryptoPayInのアカウントを作成したり、認証情報を共有したりする必要はありません。
ページは安全に決済状況をポーリングし、「待機中」から「承認中」、そして「支払い完了」へと状態を更新します。
成功後にはHTTPSのredirect_urlが提示されますが、これは支払いの証明にはなりません。
商品・サービスの提供判断は必ずバックエンドで行ってください。ブラウザの遷移は中断・繰り返し・偽装が可能であり、決済状態を証明できるのは検証済みのWebhookか、認証付きのGETリクエストのみです。
権限とスコープ
各APIキーには、ダッシュボード → 開発者向けで作成する際に選択した、固定の権限セットが付与されます。すべてのエンドポイントは、処理を行う前にキーのスコープを確認します。キーに付与された範囲外の呼び出しには、不足している権限名を記載したX-Required-Scopeヘッダーとともに403 insufficient_scopeが返されます。スコープは作成時に一度だけ設定され、後から拡張することはできません — 拡張が必要な場合は新しいキーを発行してください。スコープが存在する前に作成されたキーは、元の権限(payments:readとpayments:write)をそのまま維持します。
| スコープ | 付与される権限 | エンドポイント |
|---|---|---|
payments:read | 決済の一覧取得・取得 | GET /v1/payments, GET /v1/payments/{id} |
payments:write | ホスト型決済の作成 | POST /v1/payments |
links:read | 決済リンクの一覧取得・取得 | GET /v1/links, GET /v1/links/{id} |
links:write | 決済リンクの作成・編集・一時停止・削除 | POST/PATCH/DELETE /v1/links |
shops:read | ショップおよびその商品の一覧取得・取得 | GET /v1/shops, GET .../products |
shops:write | ショップ・商品・バリエーションの作成・編集 | POST/PATCH/DELETE /v1/shops および商品 |
balance:read | 暗号資産残高とUSD概算額の参照 | GET /v1/balance |
payouts:read | 出金の一覧取得・取得 | GET /v1/payouts, GET /v1/payouts/{id} |
payouts:write | オンチェーン出金のリクエスト | POST /v1/payouts |
payouts:writeはオンチェーンで資金を移動させる、取り消し不能な操作です。完全に信頼できるキーにのみ付与し、それらのキーは必ずサーバーサイドで保管し、自動化された処理ごとに専用のキーを用意することをおすすめします。GET /v1/accountでは、呼び出し元キーのスコープとアカウントの上限を確認できます。
決済リンク
お客様が何度でも支払える、再利用可能なホスト型リンクです。リンクは、ダッシュボードのリンク作成画面と同じ価格設定・アセット・配信・チェックアウト時の質問ロジックを保持しています — APIは単にそれを動かすだけです。1つのアカウントにつき、決済リンクは最大50件まで保持できます。
/v1/linkslinks:read/v1/linkslinks:write/v1/links/{id}links:read/v1/links/{id}links:write/v1/links/{id}links:writeリクエストボディ
| フィールド | 型 | 必須/任意 | 説明 |
|---|---|---|---|
| title | 文字列 | 必須 | 3–120文字。 |
| description | 文字列 | 任意 | 最大2,000文字。チェックアウト画面に表示されます。 |
| template | 文字列 | 任意 | チェックアウトのテーマ:signature(デフォルト)、midnight、atelier、horizon、compact、またはledger。 |
| public_label | 文字列 | 任意 | 購入者に表示される、公開用の販売者名(2–80文字)。アカウントIDを指定することはできません。 |
| amount_type | 文字列 | 任意 | fixed(デフォルト)、またはopen(お客様がmin/maxの範囲内で金額を選択)。 |
| currency | 文字列 | 任意 | GET /v1/currenciesに含まれる表示通貨。デフォルトはアカウントの既定通貨です。 |
| amount | 数値または文字列 | 条件付き | fixedの場合は必須です。currencyで、そのISO精度に従って指定します。 |
| min / max | 数値または文字列 | 条件付き | openリンクの上限・下限。上限を設けない場合、maxは0または省略できます。 |
| accepted_assets | 文字列の配列 | 任意 | ["BTC","USDT.TRC20"]のようなアセットコード。省略した場合は、利用可能なすべてのアセットが対象になります。 |
| max_uses | 整数 | 任意 | 完了済み決済数の上限。0は無制限を意味します。 |
| expires_at | ISO 8601 | 任意 | 現在時刻から少なくとも5分後、最大12か月後まで。UTCで指定します。 |
| delivery_type | 文字列 | 任意 | none、text、url、またはkeys — 支払い後にデジタル商品を配信します。 |
| delivery_text / delivery_url | 文字列 | 条件付き | 対応する配信タイプに応じた、コンテンツ本文(≤50,000文字)またはhttps URL。 |
| delivery_keys | 文字列の配列 | 条件付き | keys配信の場合、1要素につき1キー。最大10,000件、各≤500文字。 |
| checkout_fields | 配列 | 任意 | {label, type, required}の形式で、最大5個のオブジェクト。typeはtext、email、textarea、またはnumberのいずれかです。 |
| success_message / redirect_url | 文字列 | 任意 | 支払い完了後のメッセージ(≤500文字)とhttpsのリダイレクト先。 |
| status | 文字列 | 任意 | PATCHの場合のみ:activeまたはpaused。 |
curl -X POST https://cryptopayin.com/v1/links \
-H "Authorization: Bearer $CPI_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Pro license",
"amount": 49.99,
"currency": "EUR",
"accepted_assets": ["BTC", "ETH", "USDT.TRC20"],
"delivery_type": "keys",
"delivery_keys": ["ABC-1", "ABC-2", "ABC-3"]
}'{
"id": "PL-N5PKTYB7",
"object": "payment_link",
"url": "https://cryptopaylink.co/pay/PL-N5PKTYB7",
"status": "active",
"title": "Pro license",
"amount_type": "fixed",
"currency": "EUR",
"amount": 49.99,
"amount_decimal": "49.99",
"accepted_assets": [{"asset":"BTC","network":"mainnet"},{"asset":"ETH","network":"mainnet"},{"asset":"USDT","network":"TRC20"}],
"uses": {"started": 0, "completed": 0, "in_flight": 0},
"delivery": {"type": "keys", "keys_available": 3, "keys_total": 3},
"expires_at": null,
"created_at": "2026-07-19T19:00:00+00:00"
}PATCHは部分更新です。変更したいフィールドのみを送信すれば、未販売のライセンスキーを含め、それ以外はそのまま保持されます。keysリンクの場合、delivery_keysを送信すると未販売のキーのプールが置き換えられますが、すでに配信済みのキーには一切影響しません。決済履歴のあるリンクの削除は、履歴を維持するために暗黙的に拒否されます。
エージェント決済
有効な決済リンクはすべて、機械可読なチェックアウトとしても機能します。AIエージェントや任意のスクリプトは、ブラウザなしで — さらにAPIキーすら不要で — それを検出し、請求書を作成し、配信内容を読み取ることができます。これらはリンクドメイン上の公開の購入者向けエンドポイントであり、加盟店向けのエンドポイントではないためです。完全な仕様と実例はcryptopayin.com/agentsをご覧ください。
https://cryptopaylink.co/pay/{link}.json公開 · 検出状態、価格、対応アセット、そして請求書作成呼び出しの正確な入力仕様(必須フィールド、配送先スキーマ、バリエーション)を返します。
https://cryptopaylink.co/pay/{link}/invoice公開 · Idempotency-Key対応ホスト型ページと同じコアロジック・価格スナップショット・不正利用防止の制限を通じて請求書を作成し、入金アドレス・正確な暗号資産金額・ウォレットURI・領収書URLを返します。その後、エージェントは自身が管理する任意のウォレットからオンチェーンで支払いを行います。
https://cryptopaylink.co/pay/{link}/receipt?p={payment}公開 · 5〜10秒ごとにポーリングリアルタイムのステータスと承認数を返します。決済が完了すると、レスポンスにはその決済向けに確保された配信内容 — テキストコンテンツ、非公開URL、またはライセンスキー — に加え、成功メッセージとリダイレクトURLが含まれます。
ショップも同じプロトコルを話す
ストアフロントも、自身のドメイン上でまったく同じフローを提供します。リアルタイムの在庫状況を含むカタログを提示したうえで、カートを検証し、在庫を確保し、請求書を返す単一の呼び出しを行います。
https://shopycrypto.com/s/{shop}.json公開 · カタログhttps://shopycrypto.com/s/{shop}/order公開 · カート→請求書、Idempotency-Key対応https://shopycrypto.com/s/{shop}/o/{order}/receipt?p={payment}公開 · 5〜10秒ごとにポーリング販売者側の制御
エージェント決済はデフォルトで有効になっており、料金は同じ1%固定です。ダッシュボード → 設定 → 一般 → AI・エージェント決済から、アカウント全体で無効にできます。無効にすると、リンクおよびショップのマシン向けエンドポイントは403 agents_disabledを返すようになりますが、人間向けのチェックアウトページはそのまま機能し続けます。エージェントが作成した決済に特別なフラグは付きません — ダッシュボード・Webhook・エクスポートにおいて、通常の決済として扱われます。
ショップ
複数の商品を1つのブランドページにまとめる、ホスト型のストアフロントです。1つのアカウントにつき、ショップは最大10件まで保持できます。商品は、以下のネストされた商品エンドポイントを通じて管理します。
/v1/shopsshops:read/v1/shopsshops:write/v1/shops/{id}shops:read/v1/shops/{id}shops:write/v1/shops/{id}shops:writeリクエストボディ
| フィールド | 型 | 必須/任意 | 説明 |
|---|---|---|---|
| name | 文字列 | 必須 | 2–80文字。 |
| tagline | 文字列 | 任意 | 最大160文字。 |
| theme | 文字列 | 任意 | light(デフォルト)、またはdark。 |
| accent | 文字列 | 任意 | GET /v1/shopsでaccent_paletteとして返される、ショップのパレットに含まれるアクセントカラー(16進数)。 |
| accepted_assets | 文字列の配列 | 任意 | ショップの商品に対するデフォルトのアセット(例:["BTC","LTC","XMR"])。変更するとすべての商品に適用されます。 |
| status | 文字列 | 任意 | PATCHの場合のみ:activeまたはpaused。 |
ポリシー上の理由でCryptoPayInにより無効化されたショップは、APIを通じて再有効化・削除することができず、admin_disabled(403)が返されます。ショップを削除するとその商品も削除されますが、過去の決済には影響しません。
商品とバリエーション
商品はショップの中に存在します。1つのショップにつき、商品は最大50件まで保持できます。商品はデジタル(即時配信あり)または物理(配送先国あり)のいずれかで、1–3個のオプショングループから構成される、最大30通りのバリエーションの組み合わせを持てます。
/v1/shops/{shop}/productsshops:read/v1/shops/{shop}/productsshops:write/v1/shops/{shop}/products/{id}shops:read/v1/shops/{shop}/products/{id}shops:write/v1/shops/{shop}/products/{id}shops:writeリクエストボディ
| フィールド | 型 | 必須/任意 | 説明 |
|---|---|---|---|
| title | 文字列 | 必須 | 3–120文字。 |
| description / blurb | 文字列 | 任意 | 詳細な説明文と、≤200文字のショップカード用の紹介文。 |
| emoji | 文字列 | 任意 | 商品カードに表示される絵文字1つ。 |
| featured | 真偽値 | 任意 | 1つのショップにつき、おすすめ商品として設定できるのは最大1件です。 |
| product_type | 文字列 | 任意 | digital(デフォルト)、またはphysical。 |
| shipping_countries | 文字列の配列 | 条件付き | 物理商品の場合のみ:["FR","BE"]のようなISOコード、または全世界を対象とする場合は["*"]。 |
| amount_type / currency / amount / min / max | 複合 | 条件付き | 基本価格設定で、決済リンクと同一のルールが適用されます。物理商品ではfixedである必要があります。 |
| max_uses | 整数 | 任意 | 総販売数の上限(0は無制限を意味します)。 |
| delivery_type + delivery_text/url/keys | 複合 | 任意 | 基本商品のデジタル配信設定で、決済リンクと同じ形式です。 |
| variant_options | 配列 | 任意 | {name, values[]}形式で1–3個のグループ、各グループ2–10個の値。組み合わせ数は30を超えてはいけません。 |
| variants | 配列 | 条件付き | 組み合わせごとに1オブジェクト(詳細は下記)。variant_optionsが指定されている場合は必須で、全組み合わせを網羅する必要があります。 |
| status | 文字列 | 任意 | PATCHの場合のみ:activeまたはpaused。 |
バリエーションオブジェクト
| フィールド | 型 | 説明 |
|---|---|---|
| options | 文字列の配列 | オプショングループごとに1つの値を、グループの順序どおりに指定します(例:["Pro","Lifetime"])。 |
| price | 数値または文字列 | 商品の通貨建てでの、バリエーションの価格。 |
| stock | 整数またはnull | 残り在庫数。無制限の場合はnullを指定します。 |
| delivery_type + delivery_text/url/keys | 複合 | バリエーションごとのデジタル配信設定の上書き(省略可、デフォルトはinherit)。キーは商品全体を通じて一意である必要があります。 |
curl -X POST https://cryptopayin.com/v1/shops/SH-JYRK8TFJ/products \
-H "Authorization: Bearer $CPI_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Software license",
"amount": 30,
"currency": "USD",
"variant_options": [
{"name": "Edition", "values": ["Standard", "Pro"]},
{"name": "Term", "values": ["1 year", "Lifetime"]}
],
"variants": [
{"options": ["Standard","1 year"], "price": 30, "delivery_type": "keys", "delivery_keys": ["S1Y-1"]},
{"options": ["Standard","Lifetime"], "price": 79, "stock": 10, "delivery_type": "keys", "delivery_keys": ["SLT-1"]},
{"options": ["Pro","1 year"], "price": 59, "delivery_type": "keys", "delivery_keys": ["P1Y-1"]},
{"options": ["Pro","Lifetime"], "price": 149, "stock": 5, "delivery_type": "keys", "delivery_keys": ["PLT-1"]}
]
}'PATCHは、既存の注文や配信済みのキーをそのまま維持します。価格や在庫を調整するには、対応するvariants配列を再送してください。省略した組み合わせは、注文があれば一時停止となり、なければ削除されます。商品は、基本商品とバリエーションを合わせて最大10,000件の有効なライセンスキーを保持でき、キーは商品内で一意である必要があります。
残高
/v1/balancebalance:readアセットごとに確定済みの暗号資産残高を、ベストエフォートのUSD概算額および出金時に課されるネットワーク手数料とともに返します。内部会計は常にUSD建てで行われ、残高は加盟店手数料を差し引いた、完了済み決済から積み上がります。
{
"object": "list",
"accounting_currency": "USD",
"minimum_payout_usd": 25,
"data": [{
"asset": "USDT",
"network": "TRC20",
"amount": "99.099",
"usd_estimate": 99.02,
"payout_network_fee": "2.445463"
}]
}検証済みのライブレートが一時的に取得できない場合、usd_estimateはnullになりますが、残高そのものは正確です。これらの値は出金の判断に使用し、最終的な会計には使用しないでください。
出金
確定済みの暗号資産を外部ウォレットへ移動します。出金は取り消しができないため、このエンドポイントはダッシュボードと同じすべての安全策を適用します:アセットに対して有効な送金先、検証済みのライブレート、アカウントの最低金額、ネットワーク手数料を含めた十分な残高、そしてアカウントで2FAが有効な場合の二要素認証です。
/v1/payoutspayouts:read/v1/payoutspayouts:write · 30リクエスト/分/キー/v1/payouts/{id}payouts:readリクエストボディ
| フィールド | 型 | 必須/任意 | 説明 |
|---|---|---|---|
| asset | 文字列 | 必須 | シンボルまたは省略形(例:LTCまたはUSDT.TRC20)。 |
| network | 文字列 | 条件付き | シンボルが複数のネットワークに存在する場合に必須です。 |
| amount | 数値または文字列 | 必須 | 送金する金額(ネットワーク手数料を除く)を、アセットの精度で指定します。USD換算額はアカウントの最低金額を満たす必要があります。 |
| address | 文字列 | 必須 | 送金先アドレス。アセットのチェーンに対して検証されます。 |
| note | 文字列 | 任意 | 貴社側の任意の参照情報(最大255文字)。 |
| totp_code | 文字列 | 条件付き | 現在の6桁コード、またはリカバリーコード。アカウントで2FAが有効な場合に必須です。 |
curl -X POST https://cryptopayin.com/v1/payouts \
-H "Authorization: Bearer $CPI_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: withdraw-2026-07-19-01" \
-d '{
"asset": "USDT.TRC20",
"amount": "50",
"address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"note": "weekly settlement"
}'{
"id": "W-EM64ZCJB",
"object": "payout",
"status": "requested",
"asset": "USDT",
"network": "TRC20",
"amount": "50",
"fee": "2.445463",
"total_debited": "52.445463",
"address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"txid": null,
"confirmations": 0,
"created_at": "2026-07-19T19:10:00+00:00"
}ステータスのライフサイクル
| ステータス | 意味 |
|---|---|
requested | 残高から確保された状態。運営側のレビュー、または自動承認を待っています。 |
approved / processing | 承認済みで、実行エンジンによるブロードキャストの待機列に入っています。 |
sent | オンチェーンにブロードキャスト済みで、txidが設定されています。 |
confirmed | 必要な承認数に到達した、最終状態。 |
failed | 送金できなかった状態。理由はfailure_messageに記載され、残高は返却されます。 |
cancelled | ブロードキャスト前にキャンセルされた状態。確保されていた残高は返却されます。 |
Idempotency-Keyを送信することで、ネットワークの再試行によって出金が二重に作成されることはなくなります。同じキーで同じボディを送信した場合は、元の出金(Idempotent-Replayed: true)が返されます。同じキーで異なるボディを送信した場合は409 idempotency_conflictが返されます。2FAコードは、ローテーションによって誤った競合を引き起こさないよう、意図的に冪等性のフィンガープリントから除外されています。予約と同時に残高は即座に引き落とされ、出金が失敗またはキャンセルされた場合は返却されます。
アカウント
/v1/account有効な任意のキーアカウントプロフィール、呼び出し元キーのスコープ、プラットフォーム手数料、そしてすべての現行の上限値を返します — 自己設定型の統合や事前チェックに役立ちます。
{
"object": "account",
"id": "MC67T3PHQZ",
"fee_bps": 100,
"fee_percent": 1,
"default_currency": "USD",
"two_factor_enabled": false,
"api_key": {"label": "production", "scopes": ["payments:read","payments:write"]},
"limits": {
"shops": {"used": 1, "max": 10},
"payment_links": {"used": 0, "max": 50},
"products_per_shop_max": 50,
"variant_combinations_per_product_max": 30,
"license_keys_per_product_max": 10000,
"active_api_keys_max": 50,
"checkout_fields_per_link_max": 5
},
"minimum_payout_usd": 25
}Webhook
ダッシュボード → 開発者向けから、公開HTTPSエンドポイントを最大10件登録できます。各エンドポイントには、一度だけ表示される専用のwhsec_...署名シークレットが発行されます。アカウント全体を対象にすることも、特定の有効なAPIキーに紐づけることもでき、キーに紐づいたエンドポイントは、そのキーで作成された決済のみを受信します。
パース前に検証する
CryptoPayInは、エンドポイントのシークレットを使って、生のリクエストボディそのものに署名します。バージョン1ではtimestamp + "." + raw_bodyに署名します。イベントを受理する前に、古いタイムスタンプは必ず拒否してください。
import crypto from "node:crypto";
const timestamp = req.headers["x-cpi-timestamp"];
const signature = req.headers["x-cpi-signature"];
const rawBody = req.rawBody; // Buffer captured before JSON parsing
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
throw new Error("stale webhook");
}
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.CPI_WEBHOOK_SECRET)
.update(Buffer.concat([Buffer.from(`${timestamp}.`), rawBody]))
.digest("hex");
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
if (!valid) throw new Error("invalid webhook signature");
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_CPI_TIMESTAMP'] ?? '';
$received = $_SERVER['HTTP_X_CPI_SIGNATURE'] ?? '';
if (!ctype_digit($timestamp) || abs(time() - (int)$timestamp) > 300) {
http_response_code(400); exit('stale webhook');
}
$expected = 'sha256=' . hash_hmac(
'sha256', $timestamp . '.' . $rawBody, getenv('CPI_WEBHOOK_SECRET')
);
if (!hash_equals($expected, $received)) {
http_response_code(401); exit('invalid signature');
}
$event = json_decode($rawBody, true, flags: JSON_THROW_ON_ERROR);
import hashlib, hmac, os, time
raw_body = request.get_data() # bytes, before JSON decoding
timestamp = request.headers.get("X-CPI-Timestamp", "")
received = request.headers.get("X-CPI-Signature", "")
if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > 300:
raise ValueError("stale webhook")
signed = timestamp.encode() + b"." + raw_body
expected = "sha256=" + hmac.new(
os.environ["CPI_WEBHOOK_SECRET"].encode(), signed, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, received):
raise ValueError("invalid signature")配信ヘッダー
| ヘッダー | 例 | 用途 |
|---|---|---|
| Content-Type | application/json | UTF-8のJSON本文。 |
| X-CPI-Timestamp | 1784293200 | 署名対象メッセージに含まれる、Unix秒。 |
| X-CPI-Signature | sha256=... | 16進数表記のHMAC-SHA256。 |
| X-CPI-Signature-Version | v1 | 署名方式のバージョン。 |
| X-CPI-Event-Id | evt_a12b... | 不変の論理イベントID。再試行時も同一です。 |
| X-CPI-Delivery-Id | 1842 | 不変の、エンドポイント配信レコードID。 |
決済のペイロード
{
"event_id": "evt_a12b34c56d78e90f12345678",
"event": "payment.completed",
"id": "P-9F27C1E4KD",
"status": "completed",
"order_ref": "order_1042",
"amount": 49.99,
"amount_decimal": "49.99",
"amount_minor": 4999,
"currency_minor_units": 2,
"currency": "USD",
"amount_usd": 49.99,
"amount_usd_cents": 4999,
"fx_rate_usd": "1.000000000000",
"fx_source": "fixed:USD",
"fx_observed_at": "2026-07-17T13:00:00Z",
"fx_discrepancy_bps": 0,
"exchange_rate": "3600.00000000",
"exchange_rate_currency": "USD",
"exchange_rate_source": "median:cb,cg,cl",
"exchange_rate_source_count": 3,
"exchange_rate_observed_at": "2026-07-17T13:00:00Z",
"exchange_rate_discrepancy_bps": 12,
"asset": "ETH",
"network": "mainnet",
"crypto_amount": "0.01388612",
"crypto_received": "0.01388612",
"txid": "0x9d81...75af",
"confirmations": 12,
"confirmations_required": 12,
"deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
"sent_at": "2026-07-17T13:12:42Z"
}再試行とエンドポイントの安全性
配信はHTTP 200-299で成功と判定されます。重い処理は非同期に行い、応答は素早く返してください。
リクエストボディとイベントIDはそのまま保持され、失敗した場合はおよそ1分後、5分後、30分後、2時間後、6時間後に再試行されます。
3xxのレスポンスは追跡されません。最終的なHTTPS URLを直接登録してください。
プライベートIP・ループバックIP・リンクローカルIP・予約IPへの配信はブロックされます。すべてのDNS応答は検証され、接続はピン留めされます。
配信は少なくとも1回(at-least-once)行われます。提供処理の前に、event_idを一意制約付きで記録することで、ハンドラーを冪等にしてください。想定外のイベントを突合する際は、APIオブジェクトを取得してください。
イベントリファレンス
payment.completed想定額が承認されました。payment.overpaid想定を上回る金額が承認されました。payment.underpaid許容範囲を下回る入金を検出しました。payment.expired未払いの請求書の有効期間が終了しました。payment.failed決済の設定または処理に失敗しました。payout.sent出金がオンチェーンにブロードキャストされました。payout.confirmed出金が必要な承認数に達しました。payout.failed出金を完了できませんでした。webhook.test手動での接続テスト。出金イベントの形式
{
"event_id": "evt_b98c76d54e32a10f87654321",
"event": "payout.sent",
"id": "W-8J2K7M4RQP",
"status": "sent",
"asset": "ETH",
"network": "mainnet",
"amount": "0.25",
"fee": "0.00081768",
"address": "0x84f2...9bc1",
"txid": "0xa1c4...07ee",
"confirmations": 0,
"note": "weekly treasury",
"sent_at": "2026-07-17T14:08:31Z"
}エラーとレート制限
エラーは常に単一のJSON形式で返されます。分岐処理はerror.typeに基づいて行ってください。人が読むためのメッセージは、バージョンを変更せずに改善される場合があります。サポートに問い合わせる際は、error.request_idまたは対応するX-Request-Idレスポンスヘッダーを明記してください。
{
"error": {
"type": "ambiguous_asset",
"message": "specify network (e.g. USDT.ERC20 or USDT.TRC20)",
"request_id": "b942e21f8dca4b06b8672eb9"
}
}| HTTP | 代表的なtype | 意味 |
|---|---|---|
| 400 | invalid_request, unknown_parameter | JSON・クエリ・冪等性ヘッダーのいずれかの形式が不正です。 |
| 401 | unauthorized | 認証情報またはアカウントが未指定・無効・非アクティブのいずれかです。 |
| 403 | insufficient_scope, admin_disabled | 有効なキーに必要な権限がない場合(X-Required-Scopeを参照)、または管理者によってロックされたリソースです。 |
| 404 | not_found | 不明なエンドポイント、またはこの加盟店アカウントの範囲外のリソースです。 |
| 405 | method_not_allowed | Allowヘッダーに示されたメソッドを使用してください。 |
| 409 | idempotency_conflict | 同じキーが異なるJSONで再利用されました。 |
| 413 | request_too_large | JSON本文が64 KiBを超えています。 |
| 415 | unsupported_media_type | POST本文がapplication/jsonとして宣言されていません。 |
| 422 | invalid, limit, invalid_amount, below_minimum, bad_address, 2fa_required, unsupported_asset | 形式は正しいリクエストが、決定的なバリデーションに失敗したか、リソースの上限に達しました。 |
| 429 | rate_limited | Retry-Afterだけ待機してください。 |
| 500 | server_error | 予期しない失敗です。同じ冪等性キーで安全に再試行してください。 |
| 503 | maintenance, temporarily_unavailable, asset_unavailable, no_rate, price_stale, fiat_rate_unavailable, fiat_rate_stale, derive_failed | プラットフォーム・ノード・価格・アドレス割り当てにおける一時的な障害です。古いレートで代替されることはありません。 |
現在の制限
| 対象 | 上限 | 期間 |
|---|---|---|
| Nginxの IPごとの安全上限 | 10リクエスト/秒、バースト30 | 常時 |
| 未認証IPの上限 | 300リクエスト | 60秒 |
| POST /v1/payments, links, shops, products | APIキーごとに120リクエスト | 60秒 |
| POST /v1/payouts | APIキーごとに30リクエスト | 60秒 |
| GETエンドポイント | APIキーごとに240リクエスト | 60秒 |
アカウントの上限
| リソース | 上限 |
|---|---|
| アカウントごとのショップ数 | 10 |
| アカウントごとの決済リンク数 | 50 |
| ショップごとの商品数 | 50 |
| 商品ごとのバリエーション組み合わせ数 | 30 |
| 商品/リンクごとのライセンスキー数 | 10,000 |
| リンクごとのチェックアウト質問数 | 5 |
| アカウントごとの有効なAPIキー数 | 50 |
これらの上限に対する現在の使用状況は、GET /v1/accountから確認できます。
成功したアプリケーションレベルの制限付きレスポンスには、X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Resetが含まれます。429、500、503については、指数バックオフとジッターを用いて再試行してください。POSTの場合は、必ず元のIdempotency-Keyと同一のJSONを再利用してください。
統合のセキュリティ
実行時に読み込み、値全体をログに出力したり、ソース管理にコミットしたりしないでください。
ブラウザやモバイルクライアントは、加盟店のシークレットを安全に保持できません。
JSONをパースする前に、タイムスタンプの鮮度を確認し、署名の比較には定数時間比較を使用してください。
処理済みのイベント・注文をトランザクションとして記録し、再試行によって二重に提供されないようにしてください。
想定外のイベントを受信した場合や、ローカルの状態と食い違う場合は、決済情報を取得してください。
新しいキーを作成してデプロイし、トラフィックを確認したうえで、古いキーを削除してください。
アカウントへのアクセスは、復旧不可能な16桁の加盟店キーによって制御され、任意でTOTPによる保護を追加できます。加盟店アクセス情報とAPIシークレットは、いずれもウォレットの認証情報と同等の注意を払って保管してください。
本番移行チェックリスト
開発者個人用のキーを複数のサービスで使い回さないでください。
GET /v1/assetsとGET /v1/currenciesを使用し、存在しかつavailable: trueな項目のみを表示してください。
署名シークレットは一度だけ保存し、タイムスタンプと署名を検証したうえで、不変のイベントIDにより重複を排除してください。
重複した再試行を実際に試し、決済IDが1つしか存在しないことを確認してください。
古い法定通貨レート、利用不可なアセット、承認の遅延など、あらゆる非正常系を通じて、注文の状態が安全に保たれることを確認してください。
自社の注文と、APIの決済状態・Webhookログ・加盟店台帳を突き合わせてください。
統合を始める準備はできましたか?
数秒でアカウントを作成し、キーを生成して、このリファレンスをコードのそばに置いておきましょう。