開発者向けドキュメント
API ドキュメント
請求書、決済画面、入金通知を連携。
検索結果
見つかりませんでした。エンドポイント、フィールド、ガイド名を試してください。
クイックスタート
最初の請求書を作ろう。
- ストアを準備
決済方法を有効にし、プロバイダーを設定して、プロジェクトのウォレットをバックアップします。
- API認証情報を作成
コンソールの設定 → APIアクセスで読み書きを選び、プロジェクトを割り当てます。
- リクエストを送信
自分のAPIホストを使い、 プロジェクトとストアのIDをコピー。小数の金額は文字列で送ってください。
- 決済画面を開く
応答の次のURLに移動します:
links.checkout。注文を処理する前に決済完了を検証してください。
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new invoice.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: order-1042-attempt-1' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new invoice.
const body = `{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new invoice.
$body = <<<'JSON'
{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: order-1042-attempt-1", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new invoice.
headers = {
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))サンプルはプレースホルダーを使い、このページからリクエストは送信しません。 請求書の全フィールドと応答形式 →
プロジェクトとストアのID
YOUR_PROJECT_IDとYOUR_STORE_IDの場所。
コンソールのUUIDを使います。プロジェクト・ストアの名前や読みやすい識別子ではありません。
| プレースホルダー | 確認する場所 | 用途 |
|---|---|---|
| YOUR_PROJECT_ID | プロジェクト → 設定 → API IDs → Project API ID → コピー。ストアの基本タブにも表示されます。 | プロジェクト単位・ストア単位のリクエスト。 |
| YOUR_STORE_ID | プロジェクト → ストア → ストアを選択 → 基本 → API IDs → Store API ID → コピー。 | 請求書作成とストア決済方法のリクエスト。 |
- デフォルトストアでも請求書作成には両方のIDが必要です。ストアはそのプロジェクトに属し、API認証情報にプロジェクトへのアクセス権が必要です。
- 請求書の作成・一覧・詳細・決済画面はinvoice_idを返します。IPN/Webhookと同じUUIDです。請求書パスにはこれを使い、内部idやorder_idは使いません。merchant 4.0.0以降は旧public_id応答フィールドを削除しています。更新前に連携を直してください。
- REST APIにはプロジェクト・ストア一覧のルートはありません。コンソールでIDをコピーするか、merchant 5.0.0以降の範囲を限定したMCPツールlist_projectsとlist_storesを使ってください。
- ストア → 基本 → ストアのドメインで、有効なmerchant、pay、APIホストを選びます。返される決済リンクと新しい通知リンクは、そのストア、デフォルトストア、システム標準の順に使います。廃止済み・未有効化の名前は選びません。SDKには希望するAPIホストを設定してください。優先設定を変えても、ほかの有効な別名はリダイレクトされません。
認証とアクセス範囲
認証情報はサーバーに保管し、必要な権限だけを付けましょう。
| 標準ホスト | 用途 |
|---|---|
| merchant.example.com | 加盟店コンソールと設定 |
| pay.example.com | 顧客の決済画面 |
| api.example.com | Merchant APIリクエスト |
次を置き換えます: example.com を自分のドメインにします。既存の設定名はそのままです。別名は設定 → システムで管理できます。
Authorization: Bearer YOUR_MERCHANT_API_TOKEN| 設定項目 | 使い方 |
|---|---|
| アクセスレベル | 読み取り専用は一覧・取得が可能です。読み書き権限では請求書の作成と、文書化された資産ポリシーの更新もできます。 |
| プロジェクト | 認証情報が使えるプロジェクトを割り当てます。ストアと請求書のIDは割り当て済みプロジェクトに属する必要があります。 |
| IP制限 | 設定 → APIアクセスで、送信元の正確な公開IPv4/IPv6アドレスを任意で許可できます。 |
| 認証情報の保管 | トークンはバックエンド設定に保管します。Bearer認証情報をブラウザーや決済リンクに含めないでください。 |
公開決済ルートは請求書の公開IDを使い、決済向けの安全なデータだけを公開します。コンソールのセッションや管理機能はMerchant API認証情報とは別です。
資産とウォレット
ストアごとに決済方法を選べます。
- 次を取得します: プロジェクトの決済資産 と準備状態。
- ネイティブチェーンを有効にし、ウォレットとプロバイダーを設定します。
- 次を探します: トークン候補 と コントラクトまたはmintを検証 してからトークンを有効にします。
- ストアで順序付きの 決済方法を選びます。新しい請求書は準備済みの選択肢を使います。
トークンはネイティブチェーンのウォレットを共有します。 ウォレット残高 は正確な最小単位金額と参考法定通貨額を返します。返された準備状態のフィールドで、受け付け可能な方法を確認してください。
検証済みERC-20は対応EVMネットワーク、検証済みSPLはSolanaを使います。ネイティブ決済は統合済み30ネットワークで使えます。Moneroはプロジェクト専用の外部閲覧専用ウォレット接続です。
受取APIとネイティブ・トークン対応範囲
| 決済経路 | 対応状況 | 確認根拠 | 要件 |
|---|---|---|---|
| ネイティブ決済経路 | 対応 | トランザクションをスキャン | BTC、SOL、ETH(Ethereum/Base/Arbitrum/OP)、BNB、HYPE、AVAX、POL。Bitcoinの出力、正規チェーンのEVMトランザクション/receipt、解析済みSolana送金を請求書の根拠にします。 |
| ERC-20トークン決済経路 | 対応 | トランザクションをスキャン | Ethereum、Base、BNB Chain、HyperEVM、Avalanche、Polygon、Arbitrum、Optimismはオンチェーン検証が必要です。インデックス済みTransferログで入金を照合します。 |
| SPLトークン決済経路 | 対応 | トランザクションをスキャン | Solana候補はmainnetとmintの検証が必要です。解析済みトランザクションの正確なトークン残高差分で入金を照合します。 |
| その他のUTXOネイティブ経路 | 対応 | トランザクションをスキャン | BCH/LTC/DOGEはEsploraを使います。BCH/DOGEはBitcore、LTC/DOGE/DASHはBlockCypher、DashはInsight、透明ZECはzcash-explorerにも対応します。すべて完全な保存済みCore互換node-rpcブロックにも対応します。rawモードはmempool検出ではなく1〜48承認が必要です。シールドZcashは非対応です。 |
| インデックス型アカウントのネイティブ経路 | 対応 | トランザクションをスキャン | TRONはtron-indexerまたはsolidified node-rpc、XRPはxrpl-jsonrpc、Stellarはstellar-horizonまたは保存済みStellar node-rpc台帳、Cosmos Hubはcometbft-jsonrpc、Algorandはalgorand-indexerまたはalgod node-rpcを使います。Hederaはhedera-mirrorが必要で、EVM relayでは足りません。 |
| 台帳型ネイティブ決済経路 | 対応 | トランザクションをスキャン | Aptosはaptos-rest、Suiはsui-graphql、NEARはnear-jsonrpc、Kaspaはkaspa-restを使います。Polkadot Asset Hubはsubstrate-restまたはメタデータ対応の確定node-rpc、Tezosはtezos-tzktまたは完全なOctez node-rpc操作に対応します。ネイティブ入金のみで、古い請求書にはアーカイブ保持が必要です。 |
| CardanoとTONのネイティブ経路 | 対応 | トランザクションをスキャン | Cardanoにはcardano-koios、TONにはtoncenter-v3が必要です。XRPタグ、Stellar memo ID、TON請求書コメントはdestination_tagで返され、正確に送る必要があります。 |
| 決済確定の整合性 | 対応 | 独立した検証 | 標準では、正確なトランザクション/イベント、金額、正規ブロック/スロット、確定性について独立した2プロバイダーの一致が必要です。rawと共有EVMの範囲は網羅性も確認します。管理者は明示的にチェーンを信頼する1プロバイダーへ変更できます。独立照合はなくなりますが、識別・網羅性・確定性の確認は残ります。 |
| Moneroネイティブ経路 | 対応 | プロジェクト専用の閲覧専用wallet RPC | HTTPSのメソッド許可リスト付きゲートウェイの後ろに専用の外部閲覧専用wallet-RPCを置き、account-0のサブアドレスを作ります。設定したmainnet daemonの閾値(標準は独立2ソース、任意で1)が確定の根拠になります。ネイティブ--restricted-rpcはcreate_addressと非互換です。ウォレットのバックアップとspend keyがないことは運用者が明示的に確認し、キーデータはWholly Cryptoに送りません。 |
取引所残高と資産ごとのウォレット/取引所スイープ先の選択はコンソールで利用でき、公開v1 APIでは利用できません。 取引所の設定を見る.
請求書のライフサイクル
入金の根拠、決済確定、注文処理。
| ステータス | 意味 |
|---|---|
| new | 入金待ち |
| processing | 入金を検出済み。受入金額または確定を待機中 |
| settled | 請求書の決済ルールまたは手動で受理済み |
| expired | 期限切れ。遅延入金の監視は続く場合あり |
| invalid | 自動では受理できない支払い |
| cancelled | キャンセル済み。明示的な照合操作でのみ再開可能 |
amount_status を記録します none, partial, paid または overpaid. timing_status は期限内と遅延入金を区別します。必要承認数と許容する不足額はストアのルールで決まります。
請求書の invoice_id を使い、 請求書詳細ルートで確認します。決済画面からのリダイレクトだけでは確定の証明になりません。例外は次で確認してください: 照合機能.
安全な再試行
請求書作成には Idempotency-Keyが必要です。タイムアウト後は同じ認証情報、キー、正確なリクエスト本文で再試行します。新しいキーは新しい請求書にだけ使います。
EVM決済のスキャン
共有のネイティブブロック/ERC-20検出は、新しい請求書と過去分の追跡を分けます。各請求書は永続的な履歴カーソルを持ちます。トークン照会は1回最大100ブロックで、厳しいプロバイダー制限に合わせて縮小します。標準では独立した2プロバイダーが各範囲を検証します。設定 → チェーン接続 → 詳細で信頼する1ソースに変更できますが、独立照合はなくなります。正規トランザクション、金額、承認の確認は残ります。接続詳細はスキャン遅延、履歴制限、クォータ待機を基本的な稼働確認と区別します。公開RPCの処理能力は保証されません。
IPN と Webhook
決済イベントを受信して検証。
IPNは請求書の有効なipn_urlに生成された全イベントを送ります。Webhookは有効なストアのエンドポイントが選択したイベントだけを受け取ります。どちらも同じJSONスナップショットをPOSTしますが独立しているので、両方有効だとアプリに2回通知される場合があります。
設定する項目: ipn_url を請求書作成時に指定するか、ストア標準を継承します。IPNは次の ストア → IPN シークレットを使い、各 ストア → Webhook エンドポイントは独自のシークレットを持ちます。どちらもAPIキーではありません。
いつ注文を処理すればいい?
イベントベースならevent_type = invoice.settledとstatus = settledで注文確認を開始します。現在の請求書を検証し、注文は一度だけ処理してください。
statusはイベント作成時の請求書状態、event_typeは起きたことです。payment.receivedにはprocessingまたはsettledが入る場合があります。2回目の支払いを意味せず、単独の注文処理シグナルでもありません。
どんなイベントと状態が送られる?
| 設定・履歴のイベント | 本文のstatus | 意味 |
|---|---|---|
| invoice.created | new | 請求書が作成され入金待ちです。管理された再開操作でnewに戻る場合も使います。 |
| payment.received | Resulting invoice status | 入金が記録されたか、受取額が増えました。通常processingまたはsettledですが、このイベントだけでは確定の証明になりません。 |
| invoice.processing | processing | 入金を検出しましたが、受入金額または必要な確定性を満たしていません。部分入金も含みます。 |
| invoice.settled | settled | 確定ルールを満たしたか、手動で受理されました。注文処理前にresolutionと注文を確認してください。 |
| invoice.expired | expired | 支払期限が過ぎました。監視中は遅延入金で状態が変わる場合があります。 |
| invoice.invalid | invalid | 自動受理できない、入金の根拠が失われた、または加盟店が拒否しました。請求書を確認してください。 |
| invoice.cancelled | cancelled | 請求書はキャンセル済みです。注文を処理しないでください。キャンセルはオンチェーン支払いを返金しません。 |
EthereumとSolanaでイベントの流れが違う理由
承認が後から届く場合(Ethereumの例)
| シーケンス | event_type | status |
|---|---|---|
| 1 | invoice.created | new |
| 2 | payment.received | processing |
| 2 | invoice.processing | processing |
| 3 | invoice.settled | settled |
検出時にすでに確定済み(Solanaの例)
| シーケンス | event_type | status |
|---|---|---|
| 1 | invoice.created | new |
| 2 | payment.received | settled |
| 2 | invoice.settled | settled |
これはイベント生成順で、配信順を保証しません。検出タイミングと決済ルール次第で、ほかのチェーンでも両方の流れが起きます。settledの前にprocessingが来ることを必須にしないでください。
一度だけ注文処理:受信例と重複対策
| 方式 | 処理方法 |
|---|---|
| イベントベースの受信処理 | 署名付きevent_idで各イベントを区別し、status = settledのinvoice.settledを選びます。同じsequenceのpayment.receivedが先に届いても、このイベントを捨てないでください。 |
| SDKの注文状態インボックス | 付属のPHP、Python、Node受信例はproject + invoice_id + sequenceをまとめます。event_typeにかかわらず保存した状態を処理し、現在の請求書を取得してsettledなら一度だけ実行します。この統合の後にinvoice.settledだけのフィルターを追加しないでください。 |
再試行はevent_idと元の本文を保ちます。異なるイベントはsequenceが同じでもevent_idは異なります。イベント方式では署名付きevent_idで配信を重複排除し、別途、設定済みinstallation/project + invoice_idと注文で二重処理を防いでください。再確定しても注文に二重計上しないことが必要です。
HTTP receiver:
Verify raw-body signature, timestamp and configured project/store scope.
Save to a durable inbox; deduplicate the signed event_id.
Return HTTP 2xx only after persistence succeeds.
Event-based background worker:
Other events go to status/reconciliation handling, not fulfilment.
Continue here only for event_type = invoice.settled and status = settled.
Fetch the current invoice from your configured API origin.
Check settled status, project/store, order, amount, currency and review policy.
In one database transaction:
Lock the order and check the scoped invoice has not been fulfilled.
Credit/complete once and save the fulfilment record.
Queue any external fulfilment with the same business idempotency key.
SDK order-state worker:
Use the same current-invoice checks and fulfil-once transaction.
Do not filter event_type after collapsing events by invoice revision.そのまま使える受信プログラムではなく、疑似コードです。
全請求書状態と決済例外
| フィールド | 値 | 意味 |
|---|---|---|
| status | new, processing, settled, expired, invalid, cancelled | イベント作成時の請求書状態。配信時の現在状態とは限りません。 |
| amount_status | none, partial, paid, overpaid | 許容差を含む受取額の状態。paidは承認の確定ではありません。 |
| timing_status | on_time, late | 請求書の期限内に支払われたか。 |
| resolution | automatic, manually_settled, manually_invalidated | 通常ルールか手動の承認・拒否で結果が決まったか。 |
| requires_review | false, true | 例外の目安であり、別の請求書状態でも、自動で注文処理・返金してよいという許可でもありません。 |
| 状況 | 対応 |
|---|---|
| 不足入金・許容差 | 自動ルールではpartialは確定しません。paidには許容内の不足額を含む場合がありますが、確定性は必要です。金額比較だけでなく請求書状態を使ってください。 |
| 過払い | overpaidはsettledやrequires_review = trueと共存できます。過払いポリシーを適用し、注文への二重計上や未検証アドレスへの自動返金はしないでください。 |
| 遅延入金 | 監視中はexpiredから変わる場合があります。timing_status = lateは要確認です。キャンセル済み注文を自動で再開・発送しないでください。 |
| 手動受理 | 条件を満たすオンチェーン入金がなくても、invoice.settledにresolution = manually_settledが入る場合があります。この上書きを連携で受け入れるか決めてください。決済サマリーはnullの場合があります。 |
| 再編成・無効化 | 新しいリビジョンが以前の入金根拠を無効にする場合があります。現在状態を再取得し、照合で取消を扱ってください。一度settledになったからといって無視しないでください。 |
| 0承認・金額0 | 0承認では検出時に確定でき、再編成リスクがあります。明示的に許可した金額0の請求書は支払いなしで確定します。どちらも先にpayment.receivedが必要なわけではありません。 |
注文処理にはstatus = settledを使い、amount_status = paidや決済後リダイレクトだけに頼らないでください。必要承認数が0なら検出時に確定し、再編成リスクを伴います。
不足入金はamount_status = partial、過払いはoverpaidです。paidは請求書の不足許容差を含む受入最低額が届いたことです。これは金額状態で、請求書ステータスではありません。lateはtiming_statusで、別イベントではありません。
通常はnew → processing → settledですが、中間状態を飛ばす場合があります。明示的に許可した金額0の請求書は支払いなしで確定し、amount_status = noneのままです。手動受理はmanually_settledです。
通知は変更されないスナップショットで、現在状態の応答ではありません。遅延、順序違い、重複がありえます。入金イベントと状態イベントは同じ請求書sequenceと状態を共有できますが、署名付きevent_idとevent_typeは異なります。ブロックごとの承認数通知は保証しません。
受け取るデータ
{
"invoice_id": "11111111-2222-4333-8444-555555555555",
"status": "settled",
"amount_status": "paid",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 3,
"amount": "49.9",
"currency": "EUR",
"order_id": "order-1042",
"payload_version": 2,
"event_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
"event_type": "invoice.settled",
"occurred_at": "2026-09-14T12:05:00Z",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"description": "Annual plan",
"email": "ada@example.test",
"customer": {
"firstname": "Ada",
"lastname": "Lovelace",
"countryiso2": "GB"
},
"metadata": {
"firstname": "Ada",
"lastname": "Lovelace",
"countryiso2": "GB",
"cart_id": "cart-681"
},
"created_at": "2026-09-14T12:00:00Z",
"updated_at": "2026-09-14T12:05:00Z",
"expires_at": "2026-09-14T12:15:00Z",
"monitoring_expires_at": "2026-09-21T12:15:00Z",
"settled_at": "2026-09-14T12:05:00Z",
"paid_chain": "ethereum",
"paid_asset": "USDC",
"paid_asset_amount": "58.17342",
"paid_asset_amount_received": "58.17342",
"paid_payment_method_id": "33333333-3333-4333-8333-333333333333",
"settlement_exchange_rate": {
"rate": "1.17",
"units": "asset_per_invoice_currency",
"currency": "EUR",
"symbol": "USDC",
"observed_at": "2026-09-14T12:05:00Z",
"as_of": "2026-09-14T12:04:30Z",
"pricing_provider": "kraken",
"asset_provider": "kraken",
"pricing_fetched_at": "2026-09-14T12:04:30Z",
"asset_fetched_at": "2026-09-14T12:04:30Z",
"stale": false,
"is_fixed": false,
"reference_currency": "USD",
"uses_reference_proxy": false
},
"cancelled_at": null,
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"reason_code": "payment_confirmed",
"requires_review": false,
"links": {
"checkout": "https://pay.example.com/invoice/11111111-2222-4333-8444-555555555555",
"invoice": "https://api.example.com/v1/projects/11111111-1111-4111-8111-111111111111/invoices/11111111-2222-4333-8444-555555555555",
"payments": "https://api.example.com/v1/projects/11111111-1111-4111-8111-111111111111/invoices/11111111-2222-4333-8444-555555555555/payments"
},
"payment_info": {
"active_payment_method_id": "33333333-3333-4333-8333-333333333333",
"method_count": 1,
"methods_truncated": false,
"methods": [
{
"payment_method_id": "33333333-3333-4333-8333-333333333333",
"payment_rail": "onchain",
"chain_slug": "ethereum",
"network": "mainnet",
"caip_network_id": "eip155:1",
"asset_id": "44444444-4444-4444-8444-444444444444",
"asset_key": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"caip_asset_id": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"asset_name": "USD Coin",
"symbol": "USDC",
"asset_kind": "token",
"asset_decimals": 6,
"contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"token_standard": "erc20",
"destination_address": "0x1111111111111111111111111111111111111111",
"destination_tag": null,
"status": "paid",
"amounts": {
"expected_amount": "58.17342",
"expected_amount_atomic": "58173420",
"received_amount": "58.17342",
"received_amount_atomic": "58173420",
"confirmed_amount": "58.17342",
"confirmed_amount_atomic": "58173420",
"unconfirmed_amount": "0",
"unconfirmed_amount_atomic": "0",
"minimum_payment_amount": "57.591686",
"minimum_payment_amount_atomic": "57591686",
"remaining_amount": "0",
"remaining_amount_atomic": "0",
"remaining_to_full_amount": "0",
"remaining_to_full_amount_atomic": "0",
"overpaid_amount": "0",
"overpaid_amount_atomic": "0"
},
"acceptance": {
"finality_mode": "confirmations",
"required_confirmations": 2,
"observed_confirmations": 2,
"underpayment_tolerance_percent": "1"
},
"quote": {
"effective_rate": "1.1658",
"reference_rate": "1.16",
"units": "asset_per_invoice_currency",
"currency": "EUR",
"symbol": "USDC",
"exchange_rate_spread_percent": "0.5",
"quote_expires_at": "2026-09-14T12:15:00Z",
"provenance_available": true,
"rounding": "up",
"unrounded_payment_amount": "58.17342",
"rounding_adjustment": "0",
"pricing_provider": "kraken",
"asset_provider": "kraken",
"pricing_fetched_at": "2026-09-14T11:59:30Z",
"asset_fetched_at": "2026-09-14T11:59:30Z"
},
"market_rate_at_event": {
"rate": "1.17",
"units": "asset_per_invoice_currency",
"currency": "EUR",
"symbol": "USDC",
"observed_at": "2026-09-14T12:05:00Z",
"pricing_provider": "kraken",
"asset_provider": "kraken",
"pricing_fetched_at": "2026-09-14T12:04:30Z",
"asset_fetched_at": "2026-09-14T12:04:30Z",
"as_of": "2026-09-14T12:04:30Z",
"stale": false,
"is_fixed": false,
"reference_currency": "USD",
"uses_reference_proxy": false
},
"payment_count": 1,
"payments_truncated": false,
"payments": [
{
"payment_id": "55555555-5555-4555-8555-555555555555",
"payment_method_id": "33333333-3333-4333-8333-333333333333",
"transaction_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"payment_hash": null,
"event_index": 0,
"payment_rail": "onchain",
"chain_slug": "ethereum",
"network": "mainnet",
"asset_id": "44444444-4444-4444-8444-444444444444",
"asset_key": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"caip_asset_id": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"symbol": "USDC",
"asset_decimals": 6,
"amount": "58.17342",
"amount_atomic": "58173420",
"status": "final",
"counts_towards_received": true,
"confirmations": 2,
"block_height": 26000000,
"observed_at": "2026-09-14T12:04:30Z",
"chain_time": "2026-09-14T12:04:20Z",
"finalized_at": "2026-09-14T12:05:00Z",
"explorer_name": "Etherscan",
"explorer_url": "https://etherscan.io/tx/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
],
"links": {
"payments": "https://api.example.com/v1/projects/11111111-1111-4111-8111-111111111111/invoices/11111111-2222-4333-8444-555555555555/payments?payment_method_id=33333333-3333-4333-8333-333333333333"
}
}
]
}
}amount は元の請求総額です。 payment_info には検出した暗号資産送金、不足額、固定したレートが入ります。バージョン2ではイベント名、イベントID、プロジェクト/ストア範囲も署名対象です。
通知の全フィールドと追加請求書データ
| フィールド | 型 | 意味 |
|---|---|---|
| invoice_id | UUID | 認証付き請求書詳細ルートで使う公開請求書UUID |
| status | string | スナップショットの状態:new、processing、settled、expired、invalid、cancelled |
| amount_status | string | none、partial、paid、overpaid。paidは許容内の不足額を含み、承認の確定性は意味しません |
| timing_status | string | on_timeまたはlate |
| resolution | string | automatic、manually_settled、manually_invalidated |
| sequence | integer | 増加する請求書リビジョン。異なるイベントが同じリビジョンを共有できます。整数精度を失わず比較してください |
| amount | decimal string | 元の請求総額で、受取暗号資産額ではありません。小数精度を保ってください |
| currency | string | amountの通貨。例:USDCで払うEUR請求書ならEUR |
| order_id | string | null | 加盟店の注文番号 |
| payload_version | integer | 4.1.0以降に新規生成されたイベントは2。保持済みの旧イベントにはありません |
| event_id | UUID | 署名付きイベントID。再試行・手動再配信でも不変 |
| event_type | string | 7つの購読イベントのいずれか |
| occurred_at | timestamp | この固定イベントの作成時刻。配信時刻ではありません |
| project_id | UUID | 加盟店プロジェクトの範囲。受信側の設定と照合してください |
| store_id | UUID | 加盟店ストアの範囲。受信側の設定と照合してください |
| description | string | null | 元の請求書説明 |
| string | null | イベント作成時の任意の顧客メールアドレス | |
| customer | object | 認識される任意の顧客メタデータ。推測や外部情報による個人データの補完はありません |
| metadata | object | イベント作成時点の元の加盟店メタデータ |
| created_at | timestamp | 請求書の作成時刻 |
| updated_at | timestamp | 請求書状態の更新時刻 |
| expires_at | timestamp | 請求書の支払期限 |
| monitoring_expires_at | timestamp | 遅延入金の監視期限 |
| settled_at | timestamp | null | 決済確定時刻 |
| paid_chain | string | null | 4.1.2以降:確定に使われたと検証済みの方法のチェーンslug(例ethereum)。条件を満たす確定記録がなければnull |
| paid_asset | string | null | 4.1.2以降:BTC、ETH、USDCなどのネイティブコイン・トークンのティッカー。表示名であり一意な資産IDではありません |
| paid_asset_amount | decimal string | null | 5.0.1以降:許容差を引く前の、paid_asset単位で要求した固定総額。確定時に保存 |
| paid_asset_amount_received | decimal string | null | 5.0.1以降:確定時に採用された方法の有効な受取総額。許容された不足・過払いを含み、固定値であって現在残高ではありません |
| paid_payment_method_id | UUID | null | 4.1.2以降:確定に使ったintent ID。payment_info.methods[].payment_method_idおよび正確なネットワーク/コントラクトに一致 |
| settlement_exchange_rate | object | null | 4.1.2以降:確定時に保存したスプレッド前の市場スナップショット。単位、通貨、ソース時刻、品質フラグを明示し、配信時に再計算しません |
| cancelled_at | timestamp | null | キャンセル時刻 |
| exchange_rate_spread_percent | decimal string | 固定スプレッド。現在のストア標準値ではありません |
| underpayment_tolerance_percent | decimal string | 請求書に固定された許容差。各方法も有効な許容差を返します |
| reason_code | string | null | 機械可読の状態遷移理由 |
| requires_review | boolean | 決済例外の目安。自動注文処理や返金の許可ではありません |
| links | object | イベント作成時の決済・認証付き請求書・入金URL。ストア → 基本のドメイン設定、デフォルトストア、全体の優先ドメインの順に使い、有効で役割に合うドメインのみ選びます。再試行は元の署名付きリンクを保持。有効なホスト記録がなければnullです。 |
| payment_info | object | 実際に検出した方法、正確な金額、固定見積もり、参考市場スナップショット、件数制限付きの入金記録。下のフィールド群を参照 |
確定サマリー:settlement_exchange_rate
| フィールド | 型 | 意味 |
|---|---|---|
| rate / units / currency / symbol | strings | 請求通貨1単位あたりのスプレッド前資産量。小数文字列で、支払額や実際の取引ではありません。 |
| observed_at / as_of | timestamps | 確定の記録時刻 / 古い方のソース時刻。キャッシュをリアルタイム価格として扱わないでください。 |
| pricing_provider / asset_provider / pricing_fetched_at / asset_fetched_at | strings / timestamps | 確定時に保存した法定通貨・資産の価格ソースと取得時刻。 |
| stale / is_fixed / uses_reference_proxy / reference_currency | booleans / string | market_rate_at_eventと同じ品質フラグ。プロジェクト固定価格には表示が付き、基準通貨はUSDです。 |
| Missing snapshot or price | null | 過去レートを推測しません。確定前はサマリー全体がnull。価格だけがない場合も検証済みpaid_*識別子は残ります。 |
決済方法:payment_info
| フィールド | 型 | 意味 |
|---|---|---|
| active_payment_method_id | UUID | null | 採用済み、または選択された検出済み方法。検出前・無効化後はnull。標準の方法を推測しません。 |
| method_count / methods_truncated | integer / boolean | 検出した方法の総数と、埋め込み一覧が省略されているか。 |
| methods[] | object[] | 最大8件の検出済み方法。アクティブな方法が先頭。異なる資産の合算はしません。 |
| payment_method_id / payment_rail | UUID / string | 請求書intentの識別情報とonchain/lightningの経路。 |
| chain_slug / network / caip_network_id | string | ネットワークの識別情報。トークンIDは必ずネットワークと組み合わせます。 |
| asset_id / asset_key / caip_asset_id | UUID / string / nullable string | 検証済みレジストリの識別情報。シンボルだけでは一意ではありません。 |
| asset_name / symbol / asset_kind | string | 資産の表示名、ティッカー、native/tokenの種類。 |
| contract_address / token_standard | string | null | トークンのコントラクトまたはmintと規格。ネイティブ資産はnull。 |
| asset_decimals | integer | 最小単位の精度。Lightning BTCは11です。 |
| destination_address / destination_tag | string | null | 公開受取アドレスと必要なmemo/tag。Lightningのアドレスはnullで、秘密鍵は入りません。 |
| status | string | 方法の状態:pending、partial、paid、overpaid、expired、invalid。paidだけでは請求書確定を意味しません。 |
| payment_count / payments_truncated / payments[] | integer / boolean / object[] | 記録の総数と直近最大5件。各記録の説明は下にあります。 |
| links.payments | HTTPS URL | null | 設定したAPIオリジンで、この方法の認証付きページ分割履歴。 |
正確な金額:methods[].amounts
| フィールド | 型 | 意味 |
|---|---|---|
| expected_amount | decimal string | スプレッドと切り上げ後の固定見積もり総額。 |
| received_amount / confirmed_amount | decimal strings | 有効な検出済み資金 / この方法の承認・確定ルールを満たす資金。 |
| unconfirmed_amount | decimal string | max(received - confirmed, 0)。追加で送る金額ではありません。 |
| minimum_payment_amount | decimal string | 許容差適用後の受入基準額。見積もり総額より少ない場合があります。 |
| remaining_amount | decimal string | max(minimum accepted - received, 0)。受入基準までの追加必要額で、承認の進捗ではありません。 |
| remaining_to_full_amount | decimal string | max(full quote - received, 0)。許容差は考慮しません。 |
| overpaid_amount | decimal string | max(received - full quote, 0)。自動返金を許可する値ではありません。 |
| Every amount's *_atomic companion | integer string | 正確な最小単位表現。小数・整数ライブラリを使い、金額にfloatやJavaScript Numberを使わないでください。 |
承認ポリシー:methods[].acceptance
| フィールド | 型 | 意味 |
|---|---|---|
| finality_mode / required_confirmations | string / integer | 固定された承認数またはfinalizedポリシー。0承認は加盟店が明示的に許可するもので、ネットワーク全体の確定ではありません。 |
| observed_confirmations | integer | null | 有効な記録の中の最小値で、最新送金だけではありません。Lightningまたは有効記録なしはnull。 |
| underpayment_tolerance_percent | decimal string | この方法の有効な許容差。請求書のオンチェーン許容差が0以外でもLightningは0です。 |
レート:methods[].quoteとmarket_rate_at_event
| フィールド | 型 | 意味 |
|---|---|---|
| quote.effective_rate / units / currency / symbol | strings | スプレッド込みで固定されたasset_per_invoice_currencyレート。currencyとsymbolが換算方向を明示します。 |
| quote.exchange_rate_spread_percent / quote_expires_at | decimal string / timestamp | 固定スプレッドと見積もり期限。現在のストア設定で置き換えません。 |
| quote.reference_rate / unrounded_payment_amount / rounding_adjustment | decimal string | null | スプレッド前の基準値、丸め前の支払額、資産単位での切り上げ調整。 |
| quote.pricing_provider / asset_provider / pricing_fetched_at / asset_fetched_at | string or timestamp | null | 元の通貨・資産の価格ソースと時刻。APIキーやプロバイダー認証情報は入りません。 |
| quote.provenance_available / rounding | boolean / string | ソースの保存がない古い請求書ではfalse。丸め方向はupです。 |
| market_rate_at_event | object | null | イベント作成時の参考市場キャッシュ。欠損はnullのまま。請求額を変更せず、ネットワーク取得待ちも発生しません。 |
| market_rate_at_event.rate / units / currency / symbol | strings | quoteと同じ明示的方向の、スプレッド前市場レート。 |
| market_rate_at_event.observed_at / as_of / pricing_fetched_at / asset_fetched_at | timestamps | イベントのスナップショット時刻 / 2ソースの古い方 / 各ソースの時刻。 |
| market_rate_at_event.pricing_provider / asset_provider | strings | 設定したカスタムトークン価格を含む、通貨・資産のキャッシュソース。 |
| market_rate_at_event.stale / is_fixed / uses_reference_proxy / reference_currency | booleans / string | キャッシュが古いか、トークン価格が固定か、USD基準がステーブルコインを代用するか。基準通貨はUSD。古い値は参考情報で、新しい見積もりではありません。 |
送金記録:methods[].payments[]とGET …/payments
| フィールド | 型 | 意味 |
|---|---|---|
| payment_id / payment_method_id | UUID | 記録ID / 親intent ID。履歴の重複排除にはpayment_idを使います。 |
| transaction_id / payment_hash / event_index | string | null / integer | オンチェーンのハッシュと送金/log/outputインデックス、またはLightningハッシュ。Lightningにはトランザクションやエクスプローラーリンクがありません。 |
| payment_rail / chain_slug / network / asset_id / asset_key / caip_asset_id / symbol / asset_decimals | strings / UUID / integer | 親の決済方法と同じ資産・ネットワークID。 |
| amount / amount_atomic | decimal / integer strings | この送金の正確な値。法定通貨換算ではありません。 |
| status / counts_towards_received | string / boolean | detected、confirming、finalを算入し、reorged、replaced、invalidは算入しません。無効化された履歴も照合用に残してください。 |
| confirmations / block_height | integer | null | 記録のブロック情報。Lightningの承認数はnull。 |
| observed_at / chain_time / finalized_at | timestamp | null | ローカルで最初に検出した時刻、利用可能なら信頼するチェーン時刻、ルール上の確定に達した時刻。 |
| explorer_name / explorer_url | string | null | 対応している場合の、検証済み公開ブロックエクスプローラーリンク。 |
Merchant 5.13.3では検証済みの内部ガス資金移動を顧客の支払合計、payment_info、請求書入金API、返金上限、payment.receivedイベントから除外します。チェーン/資金管理記録はウォレット会計用に残ります。通常の送金や本当の過払いは算入します。既存の署名済み通知本文は書き換えません。過去の確定が顧客入金ではなく内部資金に依存していた場合、照合はreason_codeがinternal_gas_funding_excludedのinvoice.invalidを発行します。再度注文処理せず確認してください。
Merchant 4.1.0は元の9フィールドを移動・変更せずpayload_version 2を追加します。以前から待機中のイベントは元の本文を保ち、payload_versionがない場合があります。event_id、event_type、プロジェクト/ストアIDは署名本文内にあります。配信用イベント/配信ヘッダーは未署名のままです。
payment_infoは検出した支払いを表し、提示した全決済方法ではありません。検出前はactive_payment_method_idがnull、methodsが空です。アクティブ方法がnullになってもreorged/invalid記録はmethodsに残ることがあります。異なる資産やネットワークの金額を合計しないでください。
金額、最小単位整数、レート、割合はすべて文字列です。received_amountは未承認の有効な資金も含み、confirmed_amountはその方法の確定ルールを満たします。remaining_amountはmax(minimum_payment_amount - received_amount, 0)、remaining_to_full_amountはmax(expected_amount - received_amount, 0)です。例:100 USDC要求、99受取、許容差1%ならremaining_amountは0、remaining_to_full_amountは1。確定性は引き続き必要です。
quoteは固定された請求計算で、請求通貨1単位あたりの資産量です。スプレッドは切り上げ前に適用します。正確な比較にはexpected_amount_atomicを使ってください。表示レートだけでは切り上げを再現できない場合があります。出所を保存していない古い請求書はソース/基準/丸めフィールドがnull、provenance_availableがfalseで、今日のデータを過去の見積もりとして見せません。
market_rate_at_eventはイベント作成時に固定するスプレッド前の参考キャッシュです。ソース時刻、stale、基準代用フラグがあり、有効なペアがなければnullです。リアルタイム取得で通知を止めず、この市場値は請求額を変えません。固定カスタムトークンはis_fixedで示し、DEXトークンは同じシンボルの別トークンでなくプロジェクト専用ソースを使います。
上位のpaid_chain、paid_asset、paid_payment_method_id、settlement_exchange_rate(4.1.2以降)は確定後の検証済み採用方法です。画面の選択肢や異なる方法の合計ではありません。確定前、無効化後、未保存の旧確定、条件を満たす確定資金のない手動受理ではnullです。シンボルは表示名なので、正確なネットワーク/資産/コントラクトは方法IDで確認してください。
Merchant 5.0.1はpaid_asset単位の正確な小数文字列paid_asset_amountとpaid_asset_amount_receivedを追加し、payload_versionは2のままです。paid_asset_amountはスプレッドと切り上げを含む固定総額で、許容下限や残額ではありません。paid_asset_amount_receivedは確定時の採用方法の有効な受取総額で、未承認分、許容された不足・過払いを含みます。100 USDC要求、99受取を許容した場合は100と99で、99と99ではありません。両方とも確定スナップショットに固定されます。各イベント時の受取はpayment_info.methods[].amounts、現在記録は入金APIを使ってください。条件を満たす保存がない場合や5.0.1以前のスナップショットはnull。古い待機イベント本文は不変です。会計の小数文字列を浮動小数点に変換しないでください。
settlement_exchange_rateは確定時に記録するスプレッド前の市場キャッシュで、請求時固定レートや約定した取引ではありません。形はmarket_rate_at_eventと同じです。EUR/USDCで1.17 asset_per_invoice_currencyなら1 EUR = 1.17 USDC。ソース時刻とstale/fixed/proxyが品質を示します。ペアなしならレートはnullでも検証済み方法のpaid_*は残ります。請求額を変えず、ライブ呼び出しを待ちません。同じ方法の後続入金、再試行、再配信は保存したnullを含めスナップショットを置き換えません。本当の再確定や確定方法の変更時は新しく記録します。observed_atが記録時刻、settled_atは初回確定時刻のままの場合があります。古い本文は不変です。
最大8方法、各方法の直近5記録を件数と省略フラグ付きで含みます。本文サイズ制限でさらに減る場合があります。1記録は1送金/log/UTXO出力で、一意のトランザクションハッシュとは限りません。完全な現在履歴はGET /v1/projects/YOUR_PROJECT_ID/invoices/{invoice_id}/paymentsをpayment_method_id、limit、offset付きで使います。請求書詳細は全見積もり方法とquote_detailsを保持します。APIリンクには設定済みホストと認証情報を使い、通知内の任意URLにBearerトークンを転送しないでください。
Lightningはtransaction_idの代わりにpayment_hashを使い、受取アドレス、エクスプローラー、検出承認数はnullです。BTCは11桁(ミリサトシ)の精度で、許容差は0です。BOLT11の支払preimage、ウォレットキー、署名シークレット、プロバイダー認証情報は含みません。顧客/metadataは加盟店応答と署名通知だけに含み、公開決済には出しません。metadataに認証情報を入れないでください。
安全に受信する
- 解析前に、対応するシークレットで正確な生本文を検証します。ストア → IPNのシークレットは個別ipn_urlへの配信にも使います。ストア → Webhookの各エンドポイントには別のシークレットがあります。APIトークンではなく、どれかのローテーションは他を変更しません。
- 署名時刻を確認します(SDK標準は前後5分)。署名付きプロジェクト/ストアIDがあれば受信設定と照合し、HTTP 2xxを返す前に永続キューに保存します。イベント単位ではv2のevent_idが署名対象です。ヘッダーは未署名なのでヘッダーIDだけでは再送攻撃を防げません。状態インボックスではinvoice_idとsequenceで重複排除し、v2本文全体でなく元の状態フィールドを比較します。異なるevent type/IDが同じリビジョンを共有できるためです。
- ワーカーで、任意の通知リンクではなく設定済みAPIオリジンから現在の請求書を取得します。保存済み注文、プロジェクト/ストア、金額、通貨を照合し、現在のsettledと手動受理・例外ポリシーを確認します。イベント重複排除とは別に、DBトランザクションで注文をロックし一度だけ処理してください。
- 新しいsequenceを古いもので上書きしないでください。異なるイベントが同じリビジョンを共有できるので、リビジョン単位の排除とinvoice.settled限定フィルターを混ぜないでください。再開/照合で状態は変わります。固定の状態順位でなくsequenceで順序を判断し、取消は再処理せず確認用に記録します。
受信側のサンプル: PHP · Python · Node.js / TypeScript.
署名検証と配信ルール
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyWhollySignature(rawBody, header, signingSecret, toleranceSeconds = 300) {
const match = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || "");
if (!match) return false;
const timestamp = Number(match[1]);
if (!Number.isSafeInteger(timestamp)) return false;
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - timestamp) > toleranceSeconds) return false;
// rawBody must be the exact request Buffer, before JSON parsing.
const expected = createHmac("sha256", signingSecret)
.update(String(timestamp))
.update(".")
.update(rawBody)
.digest();
const presented = Buffer.from(match[2], "hex");
return timingSafeEqual(expected, presented);
}| 配信ルール | 詳細 |
|---|---|
| ヘッダー | Wholly-Signature、Wholly-Event-Id、Wholly-Delivery-Id。Content-Typeはapplication/jsonです。 |
| 署名 | <unix timestamp>.<exact raw body>に対するHMAC-SHA256。ヘッダー形式はt=<timestamp>,v1=<64 lowercase hex>です。 |
| 成功 | HTTP 2xxなら成功です。リダイレクトは追跡せず、2xx以外は失敗です。 |
| タイムアウト | 接続5秒、リクエスト全体10秒です。 |
| 再試行スケジュール | 再試行可能な失敗は最大8回:直ちに実行し、以後は前回終了から10秒、1分、5分、15分、1時間、6時間、24時間後です。IPNは自動再試行し、Webhookはエンドポイントごとに自動再試行を無効にできます。 |
| 送信先の安全性 | 公開HTTPSのみ。配信時にDNSを再検証して固定し、ローカル/プライベート/予約済み宛先を拒否します。 |
| イベント保持期間 | 通知本文と配信記録は90日保持の予定で、上限付きバッチで削除されます。 |
| 重複排除 | 設定済みプロジェクトの範囲で署名付きinvoice_idとsequenceを永続保存します。Wholly-Event-Idはイベント、Wholly-Delivery-Idは配信記録(再試行は同じ、手動再配信は別)を示します。どちらのIDヘッダーも未署名です。 |
| イベントの名前 | バージョン2は本文内event_idとevent_typeを署名します。旧待機イベントにはありません。異なる種類が同じsequenceを共有するので、状態はリビジョンで照合するか、個別イベントは署名付きevent_idで重複排除します。 |
| シークレットのローテーション | 重複有効期間やバージョンヘッダーはなく、待機・再試行・手動配信の署名が直ちに変わります。 |
| 配信の一時停止 | 処理クレジット不足では再試行を含めIPN/Webhookが止まります。入金は続き、チャージ後、本文保持期間内の待機通知は再開します。 |
AI アシスタント · MCP
アシスタントを自分の加盟店環境に接続。
Merchant 5.0.0には設定済みAPIドメイン上の任意で有効にするMCPサーバーがあります。共有Wholly Crypto中継ではなく、自分の環境内で動きます。
- 設定 → APIアクセスを開きます。専用認証情報を作り、必要なプロジェクトだけを割り当て、読み取り専用から始めます。運営者がホストするアカウントでは、まず運営者がMCPサービスを有効にします。管理できるのは自分の認証情報と許可だけです。
- AI接続 · MCPでMCPを有効にし、認証情報を選んでMCPアクセスを保存します。既存認証情報は明示的に有効にするまでMCP権限がありません。
- MCPサーバーURLをクライアントのリモートHTTP設定へコピーします。OAuthでは加盟店コンソールにログインし、クライアント名と戻り先を確認して認証情報を選び承認します。Basic AuthとTOTP保護は継続します。
- 請求書作成には読み書き権限、MCPポリシーの「読み取り+請求書作成」、mcp:invoice:create OAuthスコープ、明示的な承認が追加で必要です。承認後に認証情報へ追加されたプロジェクトを、OAuth接続が自動で取得することはありません。
{
"mcpServers": {
"whollycrypto": {
"url": "https://api.example.com/mcp"
}
}
}| ツール | アクセス | 用途 |
|---|---|---|
| list_projects | 次を取得します: | 接続に割り当てられた有効なプロジェクト。limit/offsetでページ分割。 |
| list_stores | 次を取得します: | project_id内のストア、ID、有効状態。limit/offsetでページ分割。 |
| list_payment_methods | 次を取得します: | project_id + store_idに設定したチェーン、トークン、Lightningの決済方法。 |
| get_wallet_balances | 次を取得します: | 受取アドレスとキャッシュ残高、鮮度/可用性フィールド。ウォレットの秘密情報は返しません。 |
| list_invoices | 次を取得します: | ストア、状態、検索で絞れるプロジェクトの請求書。limit/offsetでページ分割。 |
| get_invoice | 次を取得します: | project_id + invoice_idで完全な請求書詳細と決済リンクを取得。 |
| get_delivery_history | 次を取得します: | ストアのIPN/Webhook状態、試行、HTTP結果。任意のinvoice_id/kindフィルター。シークレットや通知本文は含みません。 |
| convert_amount | 次を取得します: | from、to、小数文字列amountによる参考キャッシュ換算。請求書見積もりではありません。 |
| create_invoice | 明示的な書き込み | project_id、store_id、idempotency_key、invoice(既存の請求書作成本文)。invoice.payment_methodsは有効なストア方法を絞ります。5.4.0以降は無効・未許可を無視し、一致なしならストア標準に戻ります。チェーンのみなら有効な許可済み資産を全選択。チェーン別asset_tickersは5.3.0以降対応。通常の請求書応答を返します。 |
プロトコル、OAuth、安全性
HTTPS上のStreamable HTTPを使います。公開されたバージョンを交渉し、以後のPOSTにMCP-Protocol-Versionを含めます。Content-Type: application/json、Accept: application/json, text/event-streamを送ります。応答は有限JSONで、再接続にMCPセッションIDは不要です。
OAuthは短期アクセストークン(15分)、一度限りのS256 PKCEコード(5分)、更新トークンのローテーション(接続寿命30日)を使います。使用済み更新トークンの再利用で接続を取り消します。期限切れ、認証情報のローテーション、ポリシー変更、正規APIドメイン変更後は再接続してください。
OAuth検出はMCP有効時だけ公開されます。resourceは/mcpを含め、検出が返す正規URLと一致する必要があります。動的登録に対応しますが、リモートclient-IDメタデータ文書やクライアントシークレットには対応しません。
カスタムAuthorizationヘッダー対応クライアントは、MCP有効の加盟店APIトークンをBearerとして使えます。REST権限は別途残るため、MCP限定接続にはOAuthが適しています。認証情報をチャット、URL、ツール引数、ソース管理に入れないでください。
MCPは認証情報の毎分REST枠と正確な送信元IP制限、APIホストのIP制限を共有します。OAuthは許可リストを回避しません。リモートAIは公開済み送信元IPを許可するか、意図して制限を外します。MCP/OAuthルートにWebチャレンジやキャッシュを適用しないでください。
HTTPエラー:401は認証、403はorigin/IP/権限拒否、404はMCP無効またはホスト違い、405はPOSTが必要、413は本文32 KiB上限、429はRetry-After付きです。JSON-RPCはerror.code、ツール失敗はHTTP 200でもresult.isError=trueです。成功はcontentとstructuredContentを含みます。
一覧は標準25件、最大100件。offsetは1000000まで。ツール応答は2 MiBまでです。期限切れ許可、認可要求、レート枠は自動削除され、設定には最大100件の有効OAuth接続を表示します。
無効なプロジェクト/ストアはMCPで操作できません。ストアの有効状態は一覧できますが、決済方法、配信履歴、請求書作成にはストアの有効化が必要です。通常のプロジェクトユーザーはMCPを管理できません。
新しい請求書には新しいidempotency_keyを使い、タイムアウト後は同じ認証情報、キー、同一invoiceオブジェクトで再試行します。小数金額、スプレッド、許容差、承認、デザインはREST請求書仕様に従います。MCPは加盟店の決済・クレジットポリシーを回避しません。
初期ツールは秘密鍵/復元フレーズの表示、送金・スイープ、返金、通知再送、決済方法・アカウント・ドメイン変更、請求管理はできません。請求書の説明、顧客フィールド、metadataは信頼できないデータとして扱い、エージェントへの指示としないでください。接続AIは許可されたデータを受け取ります。
| メソッド | パス | 仕様 |
|---|---|---|
| POST | /mcp | 認証付きJSON-RPC:initialize、ping、tools/list、tools/call。通知リクエストは202、バッチは拒否します。 |
| GET / DELETE | /mcp | 認証付き405:有限JSON応答、独立SSEストリームなし、サーバー側MCPセッションなし。 |
| GET | /.well-known/oauth-protected-resource/mcp | 正規resource URLと認可サーバー検出。/.well-known/oauth-protected-resourceでも利用できます。 |
| GET | /.well-known/oauth-authorization-server | OAuthエンドポイント、authorization_code/refresh_token、S256 PKCE、対応スコープ。 |
| POST | /mcp/oauth/register | 公開クライアント登録:client_nameと正確なredirect_uris。HTTPSまたはループバックHTTPのみ。クライアントシークレットや外部メタデータ取得はありません。 |
| GET | /mcp/oauth/authorize | client_id、redirect_uri、response_type=code、resource、code_challenge、code_challenge_method=S256、任意のscope/state。コンソールの承認へ移動します。 |
| POST | /mcp/oauth/token | フォーム形式のauthorization_code + code + code_verifier + redirect_uri、またはrefresh_token + refresh_token。client_idとresourceは常に含めます。 |
| POST | /mcp/oauth/revoke | フォーム形式のclient_idとtoken。一致するアクセス/更新トークンの接続を取り消します。 |
ツールへの直接リクエスト例
最初にMCPクライアントで初期化とプロトコル交渉を行います。これはその後のリクエスト例です。
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/mcp" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'MCP-Protocol-Version: 2025-11-25' \
--header 'Accept: application/json, text/event-stream' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}`;
const response = await fetch("https://api.example.com/mcp", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"MCP-Protocol-Version": "2025-11-25",
"Accept": "application/json, text/event-stream",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}
JSON;
$ch = curl_init("https://api.example.com/mcp");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "MCP-Protocol-Version: 2025-11-25", "Accept: application/json, text/event-stream", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"MCP-Protocol-Version": "2025-11-25",
"Accept": "application/json, text/event-stream",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}""".encode("utf-8")
request = Request("https://api.example.com/mcp",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))運営者 API
独立した範囲限定のサーバー側キーで、ホストする加盟店を準備。
api.example.com/v1/operatorで複数事業者の環境を作成・自動化できます。7.4.0以降のOperatorモード専用です。通常のMerchant APIは変わりません。
- Operator → 設定 → Operator APIで有効にします(標準では無効)。必要な権限と加盟店だけにアクセスする独立した認証情報を作成します。
- wc_operator_キーはサーバーに保管します。Operatorパネルのホストや加盟店キーではなく、APIホストを使ってください。
- Operator POSTごとにIdempotency-Keyと正確な本文を送信前に保存します。結果が不明ならアカウントを読み直し、再試行だけのためにキーを変えないでください。
- onboarding: directとパスワード、またはonboarding: invitationでパスワードなしで加盟店を作成します。その後プロジェクト/ストアを作り、決済連携用のプロジェクト限定加盟店キーを発行します。
| スコープ | アクセス |
|---|---|
| merchants.read / merchants.write | ホストする加盟店の一覧・取得・作成・更新。 |
| users.read / users.write / users.security | ユーザーの取得・作成・更新。パスワード変更とセッション取消は別権限です。Operator管理者は作成しません。 |
| invitations.read / invitations.write | 一度限りの招待/リセットリンクの一覧・取得・作成・置換・取消。新規ユーザーにはusers.write、リセットにはusers.securityも必要です。 |
| credits.read / credits.write / fees.write | 残高・台帳の取得、ローカルクレジットの付与・修正、今後の手数料設定。0以外の初期クレジットにはcredits.writeが必要です。 |
| topups.read / topups.write | 加盟店のクレジットチャージ決済を取得・作成。APIから支払い済みにする操作はありません。 |
| projects.read / projects.write / reports.read | 加盟店のプロジェクト、ストア、デザイン、決済設定を作成し、請求書、残高、財務レポートを取得。 |
| merchant_credentials.read / merchant_credentials.write | 通常の範囲限定加盟店キーを管理。発行後は独立して動く強い権限です。 |
| events.read / webhooks.write / audit.read / health.read | ライフサイクル履歴、署名付き通知の設定、監査・機能・ノード状態の取得。 |
初期登録、クレジット、権限、安全な再試行
| 項目 | ルール |
|---|---|
| 認証情報 | 任意の期限と正確なIPv4/IPv6許可リスト。標準毎分60回、1〜600に設定可能。毎回、発行した管理者と現在の権限を確認します。HTTP 429にはRetry-Afterが付きます。 |
| 分離 | キーは割り当てられた加盟店だけにアクセスします。加盟店作成と全体レポートには全加盟店アクセスが必要です。Operator自身の事業は対象外です。 |
| 初回ログイン | 直接作成されたアカウントはホストがウォレットキーへアクセスできることを確認します。require_password_changeは初回パスワード変更を要求します。招待受諾は保管権限への明示的同意後、通常ログインです。Basic Authと既存TOTPは継続します。 |
| 招待 | 新規招待リンクは48時間、パスワードリセットは1時間です。トークンは一度限り。再発行は旧リンクを取り消します。SMTP受付は受信箱への到着を保証しないためemail_deliveryを確認してください。 |
| 安全な再試行 | 全Operator POSTには16〜128文字のキー(英字・数字・-・_・.)が必要です。同じキーと正確なURL/本文なら保存済み結果を返し、バイトが違えば409です。再応答では秘密情報/リンクを省くので、必要なら新しい明示的操作でローテーション・再発行します。 |
| 結果が不明な場合 | operator_request_in_progressは実行中、または結果記録前に中断されたことを示します。リソースと監査を調べ、新しいキーで無条件に再送しないでください。完了記録は30日後に圧縮されても、古いキーは再実行できません。 |
| クレジットと手数料 | 金額は小数6桁までの文字列です。starting_creditは一度限りのローカル付与。調整には符号付き金額、メモ、request_idとHTTP再試行キーが必要です。fee_bps=100は1%で、変更は今後の請求書に適用します。付与は設置環境自身のクレジットを増やしません。 |
| 一時停止 | enabled=falseは加盟店アカウントを無効にし、コンソールセッションを取り消します。payments_paused=trueは新規請求書を止めます。既存入金の監視は継続します。プロジェクト/ストア作成と自動化には環境のクレジットポリシーが適用されます。 |
| 公開しない操作 | ウォレット秘密情報、署名、送金、返金、完全削除、TOTPリセット、ドメイン変更、サーバー設定はありません。通常の請求書操作には加盟店キーとMerchant APIを使います。 |
OperatorのライフサイクルWebhook
| イベント | データ |
|---|---|
| merchant.created / merchant.updated | merchant_id、enabled、payments_paused、fee_bps。 |
| user.created / user.updated | merchant_id、user_id、enabled。更新イベントはemail、有効状態、管理者ロールの変更を含みます。 |
| invitation.accepted / password_reset.completed | merchant_id、user_id、invitation_id。 |
| topup.settled / credit.balance_changed | merchant_id、ledger_id、kind、amount、balance。照合時は加盟店のクレジット通貨または台帳詳細を取得します。 |
Operatorのライフサイクルイベントは請求書IPN/ストアWebhookとは別です。購読は作成したOperator認証情報に属し、キーあたり最大10エンドポイントです。以後の一致イベントだけをキューに入れ、保存履歴はGET /eventsで取得します。
本文はevent_id、event_type、merchant_id、occurred_at、dataです。初回だけ表示されるエンドポイントのsigning_secretを使い、正確な生本文のWholly-Signatureを検証します:HMAC-SHA256(secret, timestamp + '.' + raw_body)、ヘッダーt=...,v1=...。短い時刻許容幅を適用してください。
SDKの汎用署名検証を使い、請求書通知パーサーは使いません。merchant_idとevent_typeを検証し、トランザクションでevent_idを保存・重複排除し、永続保存後にだけ2xxを返します。Wholly-Event-Idは署名本文と一致する必要があります。未署名ヘッダーを業務データとして信用しないでください。
配信は少なくとも1回方式で、順序が前後し、最大8回試行します。現在リソースを読んで照合してください。occurred_atは単調増加シーケンスではありません。配信前に権限と有効/期限を再確認します。無効購読は既存キューを止め、無効中の新規イベントは追加しません。
イベントと配信履歴は30日保持します。環境の自動化ポリシーで配信が止まることがあります。GET /webhooks/{id}/deliveriesは結果と固定本文を表示し、公開APIは期限切れ記録を強制配信しません。
{
"event_id": "55555555-5555-4555-8555-555555555555",
"event_type": "merchant.created",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"occurred_at": "2026-10-01T12:00:00Z",
"data": {
"merchant_id": "11111111-1111-4111-8111-111111111111",
"enabled": true,
"payments_paused": false,
"fee_bps": 300
}
}エラーと制限
検証、利用枠、再試行を確実に扱おう。
応答を解析する前にHTTP状態と Content-Type を確認します。次の場合は 429、少なくとも Retry-After の時間を待ってから再試行します。
| 上限 | 詳細 |
|---|---|
| リクエスト頻度 | 認証情報ごとの枠:標準はUTCの1分あたり120回、設定 → APIで1〜6000に変更可能です。認証済みv1の読み書き、冪等な再試行、認証後の権限/検証失敗は、ドメイン・プロジェクト・プロセス間で枠を共有します。無効認証、コンソールルート、公開決済は消費しません。 |
| レート制限ヘッダー | 認証済みv1応答はX-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset(次のUTC分境界のUnix秒)を含みます。超過はJSON 429 rate_limit_exceededと整数秒のRetry-Afterです。指定時間以上待ち、再試行に揺らぎを加えます。固定窓なので分境界の集中は可能で、毎秒リクエスト数の保証ではありません。 |
| 加盟店リクエスト本文 | アプリのルーターで最大32 KiB。JSONエラーを生成する前にエッジが大きすぎるリクエストを拒否する場合があります。 |
| 請求書一覧 | limitは標準50、1〜100。offsetは0〜1,000,000。検索は100文字までです。新しい順でtotal/has_moreを含みます。 |
| ストアの方法 | ストアあたり最大64資産。30のネイティブチェーンと件数制限付き検証トークンに対応します。プロジェクト方針、スキャナー機能、準備・バックアップ済みウォレットは請求書作成条件です。 |
| トークンの検索 | 候補limitは標準50、1〜100。オンチェーン検証が成功するまで検索結果は決済資産ではありません。 |
| 登録済みプロジェクトトークン | プロジェクトあたり永続トークン資産は最大20件。登録済み資産の再利用は追加枠を使いません。 |
| 冪等性 | 請求書作成に必須。空白なしの表示可能ASCIIで1〜128文字。キーはストア内で一意、再試行は元の認証情報と正確な生本文が必要です。 |
| メタデータ | JSONオブジェクトのみ。符号化後最大4,096バイト、入れ子5階層まで。 |
| 通知 | 公開HTTPS URLは最大2,048バイト。通知リクエスト本文は256 KiB、保存する請求書イベントは履歴件数を制限して64 KiBまでです。 |
| 決済用アセット | 不足入金で正確な残額が変わるため、QR SVGはprivateかつno-storeです。リビジョン付きPNGロゴは公開キャッシュ1年でimmutableです。 |
| APIエッジ | 管理対象APIの上流読み取りは30秒でタイムアウトします。呼び出し元はジョブ全体の許容時間より短い明示的タイムアウトを設定してください。 |
| JSON以外のエラー | 不正なUUID/クエリ、違うメソッド、32 KiBガードはフレームワークのテキスト/空応答になる場合があります。未知の/v1パスは現在404のコンソールHTMLを返すので、解析前に状態とContent-Typeを確認してください。 |
エラーリファレンス
| HTTP | エラーコード | 意味 |
|---|---|---|
| 400 | invalid_reconciliation_action | 例外の状態、理由、検索、履歴ページのフィルターが不正です。 |
| 500 | reconciliation_unavailable | 例外一覧または根拠を読み込めませんでした。待機時間を増やして読み取りを再試行してください。 |
| 402 | billing_required | 新しい請求書には検証済み連携クレジットアカウントと有効な認可が必要です。クレジット不足は作成や入金を止めず、IPN、Webhook、Sweepを止め、手数料は計上され続けます。停止アカウント、期限切れ/不正な請求検証、クレジットサービス不通、許可されない法定通貨基準では作成は拒否されます。手数料は受取暗号資産、スプレッド、過払い、ネットワーク手数料でなく元の法定通貨額が基準です。その金額と独立換算を決済画面作成前に登録します。障害中も既存監視と取得は続きます。チャージ後、保持期間内の通知と有効スイープが再開します。設定 → 手数料を確認し、失敗した作成は同じIdempotency-Keyで再試行してください。 |
| 400 | invalid_json | 不正なJSON、未知のフィールド、または文書化された形式に合わない本文です。 |
| 400 | idempotency_key_required | 請求書作成でIdempotency-Keyがありません。 |
| 400 | invalid_idempotency_key | キーが空、128バイト超、非ASCII、空白または制御バイトを含みます。 |
| 400 | invalid_payment_request | フィールド検証または選択した有効方法が失敗しました。error.messageとerror.details.payment_methods(PaymentMethodIssue[])で原因を確認してください。SDK 2.4.0以降は安全で対処しやすい例外概要と補助機能を追加。旧PHP SDKではgetApiMessage()を使えます。 |
| 400 | invalid_invoice_status | 一覧statusが文書化された6状態以外です。 |
| 400 | invalid_callback_url | 有効なIPN送信先がHTTPS、公開アドレス、DNS、SSRF検証に失敗しました。 |
| 400 | invalid_wallet_request | ウォレット/アドレス準備の入力が不正です。 |
| 400 | invalid_token_asset | トークンのチェーン、候補クエリ、CoinGecko ID、カタログ情報、コントラクト/mint入力が不正です。 |
| 401 | authentication_required | Bearerトークンがない、不正、無効、ローテーション済み、または未知です。 |
| 403 | source_ip_denied | 認証情報のIP制限に、リクエストの正確な公開送信元アドレスが含まれません。 |
| 403 | source_ip_not_allowed | ホストの接続元IP制限がクライアントを除外しています。管理者は設定 → システムで有効ホストの許可リストを管理できます。認証情報のIP制限に加えて適用されます。 |
| 503 | source_access_unavailable | ホストアクセス検証が一時的に利用できません。後で再試行してください。検証不能時は拒否します。 |
| 403 / 409 / 500 | merchant_api_access_denied | 認可失敗:権限/プロジェクト範囲は403、無効プロジェクト/ストアは409、認可バックエンド失敗は500の場合があります。Operator受取ウォレットはOperatorパネル専用で、古い明示的プロジェクト許可があってもMerchant APIやMCPからは使えません。 |
| 403 | project_access_denied | 作成時のトランザクション内再確認で、認証情報のプロジェクトアクセスが失われていました。 |
| 404 | invoice_not_found | 許可プロジェクトにその公開IDの請求書がないか、決済画面で公開できません。 |
| 404 | payment_resource_not_found | 準備に必要なプロジェクト、ストア、資産、ウォレットが存在しなくなりました。 |
| 404 | token_candidate_not_found | プロジェクトが利用できないか、トークンが現在の対応済み検索カタログにありません。 |
| 409 | idempotency_conflict | ストア内のキーがすでに存在し、認証情報または正確な本文バイトが異なります。 |
| 409 | store_unavailable | プロジェクト/ストアが無効または利用できません。 |
| 409 | no_ready_payment_methods | 準備済みストア方法がありません。error.messageとerror.details.payment_methodsでchain_slug、asset_ticker、reason_codeを確認してください。バックアップ/有効化、導入済みアダプター、価格が有効である必要があります。6.0.6以降はスキャナー待機、失敗・古い稼働確認、プロバイダー定足数不足で作成を止めません。 |
| 409 | payment_method_unavailable | 作成時の原子的な再確認で選択方法が利用できなくなりました。 |
| 409 | store_payment_method_not_selected | ストアが選択していない資産の承認数上書きを要求しました。 |
| 409 | wallet_unavailable | 作成時の原子的な再確認で決済ウォレットが利用できなくなりました。 |
| 409 | ipn_secret_required | 有効なIPN URLがありますが、ストアにIPN署名シークレットがありません。 |
| 409 | payment_resource_not_ready | 必要な資産・ウォレットが無効、未バックアップ、共有アカウント有効化証明待ち、枯渇、その他の未準備状態です。 |
| 409 | account_activation_unverified | 設定した数の正常なmainnetエンドポイント(標準2、任意で1)でXRP LedgerまたはStellarの有効化を証明できませんでした。正確なアカウントに入金して再検証してください。 |
| 400 | invalid_monero_wallet_rpc | HTTPSエンドポイント、正確なmainnet基本アドレス、ラベル、またはDigest/Basic/ヘッダー認証一式が不正です。 |
| 404 | monero_wallet_rpc_not_found | プロジェクト専用Monero wallet-RPCの紐付けがありません。 |
| 409 | monero_wallet_rpc_not_ready | Monero資産、2 daemonの定足数、固定紐付け、バックアップ/閲覧専用の明示的確認が準備できていません。 |
| 409 | monero_wallet_rpc_unavailable | 請求書作成には、有効・検証・確認済みのプロジェクトMonero wallet-RPC紐付けと有効なサーバー側認証情報が必要です。 |
| 503 | lightning_unavailable | 唯一の準備済み方法がLightningですが、ウォレットまたは見積もりを検証できませんでした。同じ冪等キーで再試行してください。ほかに準備済みオンチェーン方法があるなら、使えないLightningを除外します。 |
| 422 | monero_wallet_rpc_verification_failed | 正確なウォレット、HTTPS固定、同期、mainnet daemon定足数、ゲートウェイのメソッド拒否証明のいずれかが失敗しました。 |
| 503 | monero_wallet_rpc_failed | 外部閲覧専用wallet-RPCで請求書サブアドレスを安全に作成・再取得できませんでした。代替アドレスを作り上げることはありません。 |
| 409 | token_chain_not_ready | ネイティブ資産が無効、検証中に対応付けが変更、またはプロジェクトの登録トークンが上限20件です。 |
| 503 | dex_price_unavailable | DEXプロバイダーが不通、混雑、制限中、古い応答、または不正データです。1分後に再試行してください。固定価格は使えます。 |
| 422 | invalid_dex_price | 価格モードの組み合わせが不正か、選択プールが正確なコントラクトの条件を満たす価格を提供できません。別のプールまたは固定USD価格を選んでください。 |
| 422 | token_verification_failed | すべての適格ノードで、チェーン識別、コントラクトコード、小数桁、残高照会、mint検証のいずれかが失敗しました。 |
| 422 | invalid_store_confirmation_policy | この確定モードで上書きできない、返されたチェーン別範囲外、または非対応の0承認受理を要求しています。 |
| 409 | invoice_not_payable | 決済請求書が終了状態か、支払期限を過ぎています。 |
| 409 | invoice_payment_method_locked | 有効な支払いが別の資産を選択済みです。active_payment_method_idで続けてください。 |
| 409 | payment_method_not_payable | 選択方法は完了済み、または追加の支払いを受け付けません。 |
| 422 | payment_qr_unavailable | 決済リクエストが大きすぎてSVG QRにできません。 |
| 503 | payment_rates_unavailable | 準備済み方法のどれにも、新しく信頼できる見積もりがありません。 |
| 500 | authentication_unavailable | Bearer認証が保存済み認証情報を安全に読み取り・検証できませんでした。 |
| 429 | rate_limit_exceeded | この認証情報は現在のUTC分の枠を使い切りました。Retry-After秒以上待ち、請求書作成は同じ冪等キーで再試行してください。 |
| 500 | database_error / internal_error | 一時的なサーバー障害。同じ冪等キーで安全に再試行してください。 |
APIの概要
エンドポイントを選ぶと、フィールド、例、応答を確認できます。
請求書
POST請求書を作成/v1/projects/{project_id}/stores/{store_id}/invoicesGET請求書一覧/v1/projects/{project_id}/invoicesGET請求書を取得/v1/projects/{project_id}/invoices/{invoice_id}GET請求書の入金一覧/v1/projects/{project_id}/invoices/{invoice_id}/payments決済方法
GETプロジェクトの決済資産一覧/v1/projects/{project_id}/payment-assetsPUTプロジェクトの資産ポリシーを更新/v1/projects/{project_id}/payment-assets/{asset_id}GET決済用トークン候補を見る/v1/projects/{project_id}/payment-token-candidatesPOSTトークンを検証して登録/v1/projects/{project_id}/payment-token-assetsGETカスタムトークンのDEXプールを検索/v1/projects/{project_id}/payment-token-dex-poolsPOSTカスタムトークンを追加・価格変更/v1/projects/{project_id}/payment-token-assets/customGETストアの決済方法一覧/v1/projects/{project_id}/stores/{store_id}/payment-assetsPUTストアの決済方法を置き換え/v1/projects/{project_id}/stores/{store_id}/payment-assetsPUTストアの承認ポリシーを設定/v1/projects/{project_id}/stores/{store_id}/payment-assets/{asset_id}/confirmation-policyウォレット
GETプロジェクトのウォレットと残高一覧/v1/projects/{project_id}/wallets照合
GET決済の例外一覧/v1/projects/{project_id}/reconciliationGET照合の根拠を取得/v1/projects/{project_id}/reconciliation/{invoice_id}運営者 API
GET利用可能な機能/v1/operator/capabilitiesGET稼働状態/v1/operator/healthGET加盟店一覧/v1/operator/merchantsPOST加盟店を作成/v1/operator/merchantsGET加盟店を取得/v1/operator/merchants/{merchant_id}POST加盟店を更新/v1/operator/merchants/{merchant_id}GETユーザー一覧/v1/operator/merchants/{merchant_id}/usersPOSTユーザーを作成/v1/operator/merchants/{merchant_id}/usersGETユーザーを取得/v1/operator/merchants/{merchant_id}/users/{user_id}POSTユーザーを更新/v1/operator/merchants/{merchant_id}/users/{user_id}POSTユーザーのパスワードを設定/v1/operator/merchants/{merchant_id}/users/{user_id}/passwordPOSTユーザーのセッションを取り消す/v1/operator/merchants/{merchant_id}/users/{user_id}/revoke-sessionsGET招待一覧/v1/operator/merchants/{merchant_id}/invitationsPOST招待を作成/v1/operator/merchants/{merchant_id}/invitationsGET招待を取得/v1/operator/invitations/{invitation_id}POST招待を再送/v1/operator/invitations/{invitation_id}/resendPOST招待を取り消す/v1/operator/invitations/{invitation_id}/revokeGETクレジットを取得/v1/operator/merchants/{merchant_id}/creditsGETクレジット台帳一覧/v1/operator/merchants/{merchant_id}/credits/ledgerPOSTクレジットを調整/v1/operator/merchants/{merchant_id}/credits/adjustmentsGETチャージ一覧/v1/operator/merchants/{merchant_id}/topupsPOSTチャージを作成/v1/operator/merchants/{merchant_id}/topupsGETチャージを取得/v1/operator/merchants/{merchant_id}/topups/{topup_id}GETレポート/v1/operator/reportsGET監査一覧/v1/operator/auditGETイベント一覧/v1/operator/eventsGETWebhook一覧/v1/operator/webhooksPOSTWebhookを作成/v1/operator/webhooksPOSTWebhookを更新/v1/operator/webhooks/{webhook_id}POSTWebhookシークレットをローテーション/v1/operator/webhooks/{webhook_id}/rotateGETWebhook配信一覧/v1/operator/webhooks/{webhook_id}/deliveriesGETプロジェクト一覧/v1/operator/merchants/{merchant_id}/projectsPOSTプロジェクトを作成/v1/operator/merchants/{merchant_id}/projectsGETプロジェクトを取得/v1/operator/merchants/{merchant_id}/projects/{project_id}POSTプロジェクトを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}GETストア一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/storesPOSTストアを作成/v1/operator/merchants/{merchant_id}/projects/{project_id}/storesGETストアを取得/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}POSTストアを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}GETストアのデザインを取得/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearancePOSTストアのデザインを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearanceGETストアの決済資産一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assetsPOSTストアの決済資産を更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assetsGETストアのWebhook一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooksPOSTストアのWebhookを作成/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooksPOSTストアのWebhookを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooks/{webhook_id}GET請求書の一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoicesGET請求書を取得する/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoices/{invoice_id}GETウォレット一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/walletsGETウォレットのアドレス一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/wallets/{wallet_id}/addressesGET加盟店の認証情報一覧/v1/operator/merchants/{merchant_id}/api-credentialsPOST加盟店の認証情報を作成/v1/operator/merchants/{merchant_id}/api-credentialsPOST加盟店の認証情報を更新/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}POST加盟店の認証情報をローテーション/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/rotatePOST加盟店の認証情報を取り消す/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/revokePOST招待トークンを確認/v1/onboarding/invitations/checkPOST招待の承諾・パスワードリセット/v1/onboarding/invitations/accept決済画面
GET決済ページの枠組み/GETホスト型決済ページ/invoice/{invoice_id}GET決済ページ向けの安全な請求書データ/checkout-api/invoices/{invoice_id}GETストアの決済プレビュー/invoice/preview/{project_id}GET決済プレビューデータ/checkout-api/previews/{project_id}GETストアの決済画像/checkout-api/invoices/{invoice_id}/appearance-images/{kind}/{revision}/image.pngGETストアのプレビュー画像/checkout-api/previews/{project_id}/stores/{store_id}/appearance-images/{kind}/{revision}/image.pngGETリビジョン付きプレビューロゴ/checkout-api/previews/{project_id}/logo/{revision}/image.pngGET決済QR画像/checkout-api/invoices/{invoice_id}/payment-methods/{intent_id}/qr.svgGETリビジョン付き決済ロゴ/checkout-api/invoices/{invoice_id}/logo/{revision}/image.pngサービス
GETAPIサービスの検出/GETサービスの稼働状態/healthzGET利用可能な機能/v1/operator/capabilities読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- health.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/capabilities" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/capabilities", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/capabilities");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/capabilities",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"api_version": "v1",
"operator_version": "7.4.0",
"scopes": [
"health.read"
],
"all_merchants": false,
"merchant_ids": [
"11111111-1111-4111-8111-111111111111"
],
"onboarding": [
"direct",
"invitation"
],
"write_methods": [
"POST"
],
"idempotency_required": true
}GET稼働状態/v1/operator/health読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- health.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/health" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/health", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/health");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/health",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"version": "7.4.0",
"nodes": []
}GET加盟店一覧/v1/operator/merchants読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchants.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POST加盟店を作成/v1/operator/merchants読み取り+書き込み
パスワードを直接指定するか招待で、加盟店と最初の管理者を原子的に作成します。
- merchants.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 全加盟店アクセスが必要です。手数料の明示上書きにはfees.write、0以外のstarting_creditにはcredits.write、招待方式にはinvitations.writeも必要です。自動ログイン、Basic Auth回避、再試行による追加クレジットはありません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| name, email | string · required | 加盟店名と、全体で一意な最初の管理者メール。 |
| onboarding | direct | invitation · required | directはpassword必須で招待メールなし。invitationはpasswordを省きます。 |
| password | string · direct only | 12〜128文字(UTF-8で最大512バイト)。返却やメール送信はしません。仮パスワードにはrequire_password_changeを使います。 |
| require_password_change | boolean · default false | 初回ログインで新パスワードを要求します。直接作成した全アカウントはホストによるウォレット管理を確認する必要があります。 |
| currency | fiat code · optional | クレジット通貨。標準は地域設定の通貨で、後から変更できません。 |
| fee_bps | integer · optional | 0〜10000。100は1%。省略時はOperator標準を使い、fees.writeが必要です。 |
| starting_credit | decimal string · default 0 | 正確な一度限りのローカル付与。0以外はcredits.writeが必要。Operator自身の設置環境残高は増えません。 |
| external_id | string · optional | 一意の連携用参照値、1〜120文字。 |
| default_timezone | IANA timezone · optional | 標準は環境の地域タイムゾーンです。 |
| send_invitation_email | boolean · default false | 招待のみ。設定済みSMTPが必要で、応答は中継受付とアカウント作成を区別します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"merchant_id": "11111111-1111-4111-8111-111111111111",
"user_id": "22222222-2222-4222-8222-222222222222",
"merchant": {
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "0"
},
"onboarding": "direct",
"access_link": null,
"email_delivery": {
"status": "not_requested"
},
"custody_acceptance_required": true
}GET加盟店を取得/v1/operator/merchants/{merchant_id}読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchants.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "10",
"fee_bps": 300,
"enabled": true,
"payments_paused": false,
"external_id": "customer-1042"
}POST加盟店を更新/v1/operator/merchants/{merchant_id}読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchants.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name, enabled, payments_paused, fee_bps, external_id | optional fields | 無効化はセッションを取り消します。payments_pausedは新規請求書を止めますが既存監視は続けます。手数料変更にはfees.writeが必要で今後の請求書に適用。アカウント通貨は変更できません。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"payments_paused": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"payments_paused": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"payments_paused": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"payments_paused": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "10",
"fee_bps": 300,
"enabled": true,
"payments_paused": false
}GETユーザー一覧/v1/operator/merchants/{merchant_id}/users読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- users.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POSTユーザーを作成/v1/operator/merchants/{merchant_id}/users読み取り+書き込み
加盟店管理者、または選択プロジェクト限定ユーザーを追加します。
- users.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| email, display_name | strings · required | メールは環境全体で一意です。 |
| onboarding, password, require_password_change, send_invitation_email | same as merchant creation | 招待作成にはinvitations.writeも必要です。 |
| access_level | admin | projects · default admin | adminはこの加盟店の管理者で、環境全体/Operator管理者ではありません。 |
| project_ids | UUID[] | 加盟店所有プロジェクトのみ。プロジェクト限定アクセスには選択が必須で、テナントをまたぎません。 |
| default_timezone | IANA timezone · optional | 省略時は地域の標準値。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"user": {
"id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"email": "admin@example.test",
"display_name": "Shop administrator",
"access_level": "admin",
"project_ids": [],
"enabled": true,
"password_setup_required": false,
"custody_acceptance_required": true,
"password_change_required": true
},
"user_id": "22222222-2222-4222-8222-222222222222",
"access_link": null,
"email_delivery": {
"status": "not_requested"
},
"merchant_id": "11111111-1111-4111-8111-111111111111"
}GETユーザーを取得/v1/operator/merchants/{merchant_id}/users/{user_id}読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- users.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| user_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"email": "admin@example.test",
"display_name": "Shop administrator",
"access_level": "admin",
"project_ids": [],
"enabled": true,
"password_setup_required": false,
"custody_acceptance_required": true,
"password_change_required": true
}POSTユーザーを更新/v1/operator/merchants/{merchant_id}/users/{user_id}読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- users.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| user_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| email, display_name, enabled, access_level, project_ids, default_timezone | optional fields | 指定フィールドを更新し、最後の管理者の保護は継続します。パスワードは別のusers.security操作です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"display_name": "Store manager"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"display_name": "Store manager"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"display_name": "Store manager"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"display_name": "Store manager"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"email": "admin@example.test",
"display_name": "Shop administrator",
"access_level": "admin",
"project_ids": [],
"enabled": true,
"password_setup_required": false,
"custody_acceptance_required": true,
"password_change_required": true
}POSTユーザーのパスワードを設定/v1/operator/merchants/{merchant_id}/users/{user_id}/password読み取り+書き込み
ホストするアカウントのパスワードを設定してセッションを取り消します。既存TOTPは保持します。
- users.securityが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| user_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| password | string · required | パスワードを変更し、TOTPを保持したままセッションを取り消します。users.securityが必要です。 |
| require_password_change | boolean · default true | 次回ログイン成功時に、自分のパスワードを設定する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"user_id": "11111111-1111-4111-8111-111111111111",
"sessions_revoked": true,
"totp_preserved": true
}POSTユーザーのセッションを取り消す/v1/operator/merchants/{merchant_id}/users/{user_id}/revoke-sessions読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- users.securityが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| user_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"user_id": "11111111-1111-4111-8111-111111111111",
"sessions_revoked": true,
"totp_preserved": true
}GET招待一覧/v1/operator/merchants/{merchant_id}/invitations読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- invitations.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POST招待を作成/v1/operator/merchants/{merchant_id}/invitations読み取り+書き込み
一度限りの招待・パスワードリセットリンクを作成または置き換えます。
- invitations.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| user_id, send_email | UUID, boolean | 既存アカウントへ一度限りのリンクを発行/置換。有効化済みユーザーは1時間のリセットリンクとなり、users.securityが必要です。 |
| new user fields | alternative to user_id | email、display_name、access_level、project_idsで招待ユーザーを作成。users.writeが必要です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"user_id": "22222222-2222-4222-8222-222222222222",
"email": "admin@example.test",
"kind": "invitation",
"expires_at": "2026-10-03T12:00:00Z",
"url": "https://merchant.example.com/account-access.html#token=YOUR_PRIVATE_INVITATION_TOKEN"
}GET招待を取得/v1/operator/invitations/{invitation_id}読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- invitations.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invitation_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"user_id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"kind": "invitation",
"status": "pending",
"created_at": "2026-10-01T12:00:00Z",
"expires_at": "2026-10-03T12:00:00Z"
}POST招待を再送/v1/operator/invitations/{invitation_id}/resend読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- invitations.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invitation_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| send_email | boolean · default false | 旧トークンを置換し、クレジットは追加しません。新しいリンクは一度だけ返します。有効化済みアカウントにはusers.securityが必要です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"send_email": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"send_email": false
}`;
const response = await fetch("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"send_email": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"send_email": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"user_id": "22222222-2222-4222-8222-222222222222",
"email": "admin@example.test",
"kind": "invitation",
"expires_at": "2026-10-03T12:00:00Z",
"url": "https://merchant.example.com/account-access.html#token=YOUR_PRIVATE_INVITATION_TOKEN"
}POST招待を取り消す/v1/operator/invitations/{invitation_id}/revoke読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- invitations.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invitation_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"revoked": true,
"invitation_id": "44444444-4444-4444-8444-444444444444"
}GETクレジットを取得/v1/operator/merchants/{merchant_id}/credits読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- credits.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "10",
"fee_bps": 300,
"enabled": true,
"payments_paused": false,
"external_id": "customer-1042"
}GETクレジット台帳一覧/v1/operator/merchants/{merchant_id}/credits/ledger読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- credits.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, q | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POSTクレジットを調整/v1/operator/merchants/{merchant_id}/credits/adjustments読み取り+書き込み
この加盟店のクレジット台帳へ、理由付きの付与・修正を追記します。
- credits.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| amount | signed decimal string · required | 加盟店クレジット通貨で小数6桁まで。正の付与または負の修正で、オンチェーン送金ではありません。 |
| note | string · required | 追記専用台帳に保持する理由。 |
| request_id | UUID · required | HTTP Idempotency-Keyに加え、金額と理由とともに永続保存します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"balance": "25"
}GETチャージ一覧/v1/operator/merchants/{merchant_id}/topups読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- topups.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POSTチャージを作成/v1/operator/merchants/{merchant_id}/topups読み取り+書き込み
前払いクレジットの決済画面を作成。手動で支払い済みにはできません。
- topups.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| amount | decimal string · required | 加盟店のクレジット通貨で1単位以上。準備済みのOperator受取ストアが必要です。 |
| request_id | UUID · required | 再試行でも保持します。作成済みなら既存請求書を返し、検出・確定後だけクレジットを適用します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"invoice_id": "33333333-3333-4333-8333-333333333333",
"checkout_url": "https://pay.example.com/invoice/33333333-3333-4333-8333-333333333333"
}GETチャージを取得/v1/operator/merchants/{merchant_id}/topups/{topup_id}読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- topups.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| topup_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"invoice_id": "33333333-3333-4333-8333-333333333333",
"amount": "25",
"currency": "EUR",
"status": "pending",
"invoice_status": "new",
"checkout_url": "https://pay.example.com/invoice/33333333-3333-4333-8333-333333333333"
}GETレポート/v1/operator/reports読み取り専用
Operatorの財務概要を取得。全加盟店へのアクセスが必要です。
- reports.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| period, start, end, currency, timezone, merchant_id | query · optional | 財務フィルター。periodは標準last30。customではYYYY-MM-DDのstart/endを使います。全加盟店権限のみ。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/reports" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/reports", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/reports");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/reports",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"summary": {
"fees": "10",
"costs": "3",
"margin": "7",
"credits": "25",
"pending": 0,
"missing_rates": 0
},
"merchants": [],
"filters": {
"period": "last30",
"currency": "EUR",
"timezone": "UTC"
},
"basis": "first_settlement_latest_net_fees"
}GET監査一覧/v1/operator/audit読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- audit.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id, event_type / search | query · optional | 許可加盟店、正確なイベント種別(events)、操作文(audit)で絞ります。イベント保持は30日。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/audit" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/audit", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/audit");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/audit",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}GETイベント一覧/v1/operator/events読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- events.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id, event_type / search | query · optional | 許可加盟店、正確なイベント種別(events)、操作文(audit)で絞ります。イベント保持は30日。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/events" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/events", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/events");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/events",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}GETWebhook一覧/v1/operator/webhooks読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- events.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/webhooks", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/webhooks",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POSTWebhookを作成/v1/operator/webhooks読み取り+書き込み
今後のOperatorライフサイクルイベントを購読。ストア決済Webhookではありません。
- webhooks.write + events.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| url | public HTTPS URL · required | 認証情報、プライベートIP、リダイレクトは禁止。配信時にDNS/IPを再確認します。 |
| events | string[] · required | 請求書通知ではなく、Operatorガイドのライフサイクルイベントを選びます。 |
| merchant_ids | UUID[] · optional | 空なら認証情報が許可する全加盟店。現在の範囲制限を再確認します。 |
| enabled | boolean · default true | 停止中もキューを保持し、再有効化で有効な保存済み配信を再開します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/operator/webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/webhooks",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"id": "11111111-1111-4111-8111-111111111111",
"signing_secret": "wco_whsec_EXAMPLE_ONLY_SAVE_ONCE"
}POSTWebhookを更新/v1/operator/webhooks/{webhook_id}読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- webhooks.write + events.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| webhook_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| url | public HTTPS URL · required | 認証情報、プライベートIP、リダイレクトは禁止。配信時にDNS/IPを再確認します。 |
| events | string[] · required | 請求書通知ではなく、Operatorガイドのライフサイクルイベントを選びます。 |
| merchant_ids | UUID[] · optional | 空なら認証情報が許可する全加盟店。現在の範囲制限を再確認します。 |
| enabled | boolean · default true | 停止中もキューを保持し、再有効化で有効な保存済み配信を再開します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}`;
const response = await fetch("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"signing_secret": null
}POSTWebhookシークレットをローテーション/v1/operator/webhooks/{webhook_id}/rotate読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- webhooks.write + events.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| webhook_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "11111111-1111-4111-8111-111111111111",
"signing_secret": "wco_whsec_EXAMPLE_ONLY_SAVE_ONCE"
}GETWebhook配信一覧/v1/operator/webhooks/{webhook_id}/deliveries読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- events.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| webhook_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}GETプロジェクト一覧/v1/operator/merchants/{merchant_id}/projects読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POSTプロジェクトを作成/v1/operator/merchants/{merchant_id}/projects読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name, slug | strings · required | 名前と一意で固定のプロジェクト識別子。既存初期化でローカルウォレットを作り、送金はしません。 |
| enabled, reporting_timezone, checkout_title, checkout_description, checkout_theme, checkout_accent_color | optional | enabledは標準true。停止状態で作り、先にストアを設定するのがおすすめです。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"id": "33333333-3333-4333-8333-333333333333",
"slug": "example-shop",
"name": "Example shop",
"enabled": false,
"reporting_currency": "EUR",
"reporting_timezone": "Europe/Berlin",
"stores": []
}GETプロジェクトを取得/v1/operator/merchants/{merchant_id}/projects/{project_id}読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "33333333-3333-4333-8333-333333333333",
"slug": "example-shop",
"name": "Example shop",
"enabled": false,
"reporting_currency": "EUR",
"reporting_timezone": "Europe/Berlin",
"stores": []
}POSTプロジェクトを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name, enabled, reporting_currency, reporting_timezone, checkout_title, checkout_description, checkout_theme, checkout_accent_color | optional | 部分更新。識別子と加盟店の所有関係は変更できません。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "33333333-3333-4333-8333-333333333333",
"slug": "example-shop",
"name": "Example shop",
"enabled": false,
"reporting_currency": "EUR",
"reporting_timezone": "Europe/Berlin",
"stores": []
}GETストア一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POSTストアを作成/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name, slug | strings · required | ストア名と固定識別子。 |
| default_currency, invoice_expiry_minutes, exchange_rate_spread_percent, underpayment_tolerance_percent | optional | 割合は小数文字列を使います。新規ストアはプロジェクトのデフォルトストアのデザインを継承します。 |
| enabled, is_default, allow_zero_amount_invoices, allow_underpayments, allow_overpayments, allowed_chain_slugs | optional | payment-assetsで許可資産を設定。金額0の請求書は標準で無効です。 |
| ipn_enabled, default_ipn_url, default_redirect_url, default_cancel_url, redirect_automatically | optional | IPNと戻り先URLは既存URL検証に従います。任意HTML/JavaScriptは禁止です。 |
| checkout_language, embed_enabled, allowed_embed_origins, domains | optional | 対応言語と有効な役割ドメインを使い、埋め込みオリジンは明示設定します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"slug": "online",
"name": "Online shop",
"enabled": false,
"default_currency": "EUR",
"invoice_expiry_minutes": 60
}GETストアを取得/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"slug": "online",
"name": "Online shop",
"enabled": false,
"default_currency": "EUR",
"invoice_expiry_minutes": 60
}POSTストアを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store fields | optional | slug以外はストア作成時と同じ変更可能設定。指定項目のみ変更します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"slug": "online",
"name": "Online shop",
"enabled": false,
"default_currency": "EUR",
"invoice_expiry_minutes": 60
}GETストアのデザインを取得/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearance読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"revision": 1,
"settings": {
"inherit_default_store": true
},
"effective": {
"title": "Pay securely"
}
}POSTストアのデザインを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearance読み取り+書き込み
検証・リビジョン保護付きのストアデザインを保存します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| revision | integer · required | 先にGETで現リビジョンを読んでください。古い値なら失敗し、他の編集を上書きしません。 |
| settings | appearance object · required | inherit_default_store、ブランド、intro/outro、文字サイズ、表示設定を含む検証済みデザイン。任意HTML/JavaScriptなし。画像バイトのアップロードはコンソール専用です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
},
"revision": 2
}GETストアの決済資産一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assets読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": []
}POSTストアの決済資産を更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assets読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| assets | array · required | オンチェーン方法を完全置換:asset_id UUIDとdisplay_order。[]でオンチェーン許可資産を解除します。検証済みプロジェクト資産のみ。Lightningは設定しません。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": []
}GETストアのWebhook一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooks読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POSTストアのWebhookを作成/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooks読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name, url, event_types | strings / array · required | 公開HTTPS受信先と、IPN/Webhook文書の請求書イベント名。 |
| enabled, automatic_redelivery | booleans · default true | 作成時だけ署名シークレットを返します。Operatorライフサイクルでなくストア決済通知です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"signing_secret": "EXAMPLE_ONLY_SAVE_ONCE",
"endpoint": {
"id": "44444444-4444-4444-8444-444444444444",
"name": "Orders",
"enabled": true
},
"secret_visible_once": true
}POSTストアのWebhookを更新/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooks/{webhook_id}読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- projects.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| store_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| webhook_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name, url, event_types | strings / array · required | 公開HTTPS受信先と、IPN/Webhook文書の請求書イベント名。 |
| enabled, automatic_redelivery | booleans · default true | 作成時だけ署名シークレットを返します。Operatorライフサイクルでなくストア決済通知です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "44444444-4444-4444-8444-444444444444",
"name": "Orders",
"enabled": true
}GET請求書の一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoices読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- reports.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| limit, offset, search, status, store_id | query · optional | プロジェクト請求書一覧と同じページ分割・フィルター。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"pagination": {
"limit": 25,
"offset": 0,
"total": 0,
"has_more": false
}
}GET請求書を取得する/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoices/{invoice_id}読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- reports.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
- invoice_idは作成時と通知で返す公開IDで、内部idではありません。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| invoice_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"invoice_id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"amount": "25",
"currency": "EUR",
"status": "new",
"metadata": {},
"payment_intents": []
}GETウォレット一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/wallets読み取り専用
公開ウォレット残高のキャッシュを読みます。秘密鍵や復元フレーズは返しません。
- reports.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 残高は鮮度情報付きのキャッシュで、送金可能額の保証ではありません。このAPIに送金やキー出力はありません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}GETウォレットのアドレス一覧/v1/operator/merchants/{merchant_id}/projects/{project_id}/wallets/{wallet_id}/addresses読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- reports.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| project_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| wallet_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| limit, before, search, has_balance, hide_small_balances | query · optional | limitは1〜50、標準25。次ページはnext_cursorをbeforeとして渡し、1ページ目はbeforeを省略。has_balance=falseとhide_small_balances=falseで空・少額残高を含めます。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"wallet": {
"id": "22222222-2222-4222-8222-222222222222",
"chain_slug": "ethereum"
},
"items": [],
"total": 0,
"total_pages": 1,
"next_cursor": null,
"reporting_currency": "EUR",
"has_balance": true,
"hide_small_balances": true,
"small_balance_threshold": {
"amount": "0.20",
"currency": "EUR"
}
}GET加盟店の認証情報一覧/v1/operator/merchants/{merchant_id}/api-credentials読み取り専用
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchant_credentials.readが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| page, search | query · optional | 1からのページ番号、1ページ25件。加盟店、ユーザー、プロジェクト、ストア、ウォレット、認証情報、Webhookは検索対応。個別イベント一覧は専用フィルターを使います。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}POST加盟店の認証情報を作成/v1/operator/merchants/{merchant_id}/api-credentials読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchant_credentials.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name | string · required | 新しい通常加盟店キーのラベル。Operatorキーではありません。 |
| access_level | read_only | read_write · default read_only | 読み書きで既存Merchant API仕様を使えます。 |
| project_ids | UUID[] | 選択加盟店のプロジェクトのみ。空リストは既存の全加盟店プロジェクトポリシーに従います。 |
| enabled, ip_restriction_enabled, allowed_ips, requests_per_minute | optional | 既存加盟店キーの制御。シークレットは一度だけ返し、merchant_credentials.writeが必要です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201または200 application/json
{
"credential": {
"id": "22222222-2222-4222-8222-222222222222",
"name": "Checkout",
"access_level": "read_only",
"project_ids": [
"33333333-3333-4333-8333-333333333333"
],
"enabled": true
},
"token": "wc_live_EXAMPLE_ONLY_SAVE_ONCE"
}POST加盟店の認証情報を更新/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchant_credentials.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| credential_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| name, access_level, enabled, ip_restriction_enabled, allowed_ips | required fields | 変更込みの現在の認証設定全体を送ります。project_idsは標準[]、requests_per_minuteはMerchant API標準枠です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"id": "22222222-2222-4222-8222-222222222222",
"name": "Checkout",
"access_level": "read_only",
"project_ids": [
"33333333-3333-4333-8333-333333333333"
],
"enabled": true
}POST加盟店の認証情報をローテーション/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/rotate読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchant_credentials.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| credential_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"credential": {
"id": "22222222-2222-4222-8222-222222222222",
"name": "Checkout",
"access_level": "read_only",
"project_ids": [
"33333333-3333-4333-8333-333333333333"
],
"enabled": true
},
"token": "wc_live_EXAMPLE_ONLY_SAVE_ONCE"
}POST加盟店の認証情報を取り消す/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/revoke読み取り+書き込み
独立したOperator認証情報で、指定した加盟店リソースを管理・確認します。
- merchant_credentials.writeが必要。許可された加盟店のみ。Operatorキーはオーナー自身の事業スペースにアクセスできません。
- 送信前に一意のIdempotency-Keyと正確な本文を保存します。確定した操作は再試行で繰り返しません。再応答は秘密情報を省くので、応答を失ったらリソースを調べ、明示的にローテーション/再発行します。409 operator_request_in_progressは結果不明の中断を含みます。リソース/監査を調べ、新しいキーで無条件再試行しないでください。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | 必須 | 英字・数字・-・_・.で16〜128文字。この操作用に永続保存します |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| merchant_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
| credential_id | path UUID | 正規の小文字リソースUUID。認証情報の加盟店範囲に属する必要があります。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"revoked": true
}POST招待トークンを確認/v1/onboarding/invitations/check公開
トークンだけの初期登録。Operatorキーは受け付けず、自動ログインしません。コンソールにはBasic Authと既存TOTPが必要です。
- 招待は48時間、パスワードリセットは1時間。一度限りのハッシュ済みトークン。再発行で旧リンクを無効にし、受諾はTOTPを保持して旧セッションを取り消します。
- 自動再試行なし。受諾がタイムアウトしたらリンク状態とログインを確認し、失敗と決めつけないでください。観測送信元IPで制限されます。受取人本人が保管権限に同意する必要があります。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| token | string · required | 招待URLフラグメントのシークレット。ログに残さないでください。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/onboarding/invitations/check" \
--header 'Content-Type: application/json' \
--data-raw '{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}'// Node.js 18+ · run on your server, never in browser code.
const body = `{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}`;
const response = await fetch("https://api.example.com/v1/onboarding/invitations/check", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$body = <<<'JSON'
{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}
JSON;
$ch = curl_init("https://api.example.com/v1/onboarding/invitations/check");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
body = """{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/onboarding/invitations/check",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"kind": "invitation",
"email": "admin@example.test",
"merchant_name": "Example shop"
}POST招待の承諾・パスワードリセット/v1/onboarding/invitations/accept公開
トークンだけの初期登録。Operatorキーは受け付けず、自動ログインしません。コンソールにはBasic Authと既存TOTPが必要です。
- 招待は48時間、パスワードリセットは1時間。一度限りのハッシュ済みトークン。再発行で旧リンクを無効にし、受諾はTOTPを保持して旧セッションを取り消します。
- 自動再試行なし。受諾がタイムアウトしたらリンク状態とログインを確認し、失敗と決めつけないでください。観測送信元IPで制限されます。受取人本人が保管権限に同意する必要があります。
- 応答例は一部フィールドを示しています。追加フィールドは互換的な追加として扱ってください。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| token | string · required | 招待URLフラグメントのシークレット。ログに残さないでください。 |
| password | string · required | 新パスワードは12〜128文字、UTF-8で最大512バイト。 |
| custody_acknowledged | boolean | 新しいホスト型ウォレット招待の受諾時はtrue必須です。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/onboarding/invitations/accept" \
--header 'Content-Type: application/json' \
--data-raw '{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}'// Node.js 18+ · run on your server, never in browser code.
const body = `{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}`;
const response = await fetch("https://api.example.com/v1/onboarding/invitations/accept", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$body = <<<'JSON'
{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/onboarding/invitations/accept");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
body = """{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/onboarding/invitations/accept",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"password_set": true
}GET決済の例外一覧/v1/projects/{project_id}/reconciliation読み取り専用
不足・過払い・遅延・再編成・不明瞭な決済、通知失敗、無効/期限切れ方法を1つのページ分割キューで確認。確認済み案件も新しい根拠で再開します。
- 読み取り専用、プロジェクト範囲、認証情報の枠内。金融判断と返金はコンソール専用です。
- 行はid(内部UUID)、invoice_id(通知と同じ公開UUID)、ストア、元の法定金額/通貨、invoice_status、案件状態、理由、revision、updated_atを含みます。加盟店詳細にはinvoice_idを使います。
- 自動検出は元の監視期間に従います。Rescanは決済を有効にせず1時間監視を延長します。確定後/キャンセル済み方法も期間内は監視を続けます。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | この認証情報に割り当てたプロジェクト。 |
| status | query string | open(標準)、resolved、all。 |
| reason | query string | underpaid、overpaid、late、reorged、ambiguous、delivery_failed、disabled_method、expired_method。 |
| search | query string | 最大100文字:請求書ID、注文、顧客、ストア。 |
| store_id | query UUID | 任意のストアフィルター。 |
| page | query integer | 1〜40001。1ページ25案件固定。 |
例外キューの応答
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| data | ExceptionRow[] | 常に | 更新の新しい順。詳細URLには内部idでなくinvoice_idを使います。 |
| pagination | object | 常に | page(1〜40001)、per_page(25)、一致総数total、has_more。 |
| counts | object | 常に | 現在のフィルターと無関係な、プロジェクト全体のopen/resolved総数。 |
ExceptionRow
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id / invoice_id | UUID | 常に | 内部記録ID / 顧客向け請求書UUID。invoice_idは通知と一致。 |
| store_id / store_name | UUID / string | 常に | 所有ストア。 |
| order_id / email | string | null | 常に | 非公開の注文参照値と顧客メール。 |
| amount / currency | decimal string / string | 常に | 元の法定請求額と通貨。 |
| invoice_status | invoice status | 常に | 現在の決済ライフサイクル状態。 |
| status / reasons | open|resolved / string[] | 常に | 案件状態と、reasonフィルターにある例外種別。 |
| revision / updated_at | integer / timestamp | 常に | 現在の確認リビジョンと更新時刻。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{"data":[],"pagination":{"page":1,"per_page":25,"total":0,"has_more":false},"counts":{"open":0,"resolved":0}}GET照合の根拠を取得/v1/projects/{project_id}/reconciliation/{invoice_id}読み取り専用
請求書、案件、方法ごとの正確な合計と返金可能額、観測トランザクション、配信履歴、加盟店の判断、関連返金を返します。署名キーや通知シークレットは出しません。
- 例外がなければcaseはnull。直近100観測・50配信を返し、判断履歴はページ分割です。
- refundable_atomicは少なくとも1承認が必要で、返金予約済み分を除きます。実際に使える資金の保証ではありません。ライブ見積もりではウォレット準備、送信元残高、手数料も検証します。
- 返金のbroadcastはチェーンのエンドポイントへの提出で、顧客の受取確認ではありません。手数料は別途必要で、返金しても法定通貨の処理手数料は自動返還されません。
- コンソールのプロジェクト → 要確認で、キャンセル、受理、拒否、再開、確認、メモ、Rescan、通知再試行、対応チェーン返金を行います。CSRF保護セッション、一意のrequest_id、現在revision、必須メモ、明示確認が必要で、Bearerトークンでは変更できません。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 割り当て済みプロジェクト。 |
| invoice_id | path UUID | 内部idでなく公開請求書UUID。 |
| page | query integer | 判断履歴のページ。1から、1ページ25件。 |
照合の応答
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| invoice | InvoiceDetail | 常に | 完全な加盟店請求書:サマリー、非公開metadata、payment_intents。dataラップなし。 |
| case | object | null | 常に | 状態、理由、revision、時刻を含む現在案件。例外なしはnull。内部根拠は除外。 |
| methods | object[] | 常に | id、wallet_id、asset_id、symbol、chain、decimals、expected_atomic、received_atomic、confirmed_atomic、refundable_atomic、address、tag、monitor_error、last_checked_at、monitoring_expires_at、spending_supported。最小単位金額は文字列です。 |
| history | object[] | 常に | このページの直近25判断:id、action、note、actor、result、created_at。 |
| history_pagination | object | 常に | page、per_page(25)、total。pageで分割するのは判断履歴だけです。 |
| refunds | object[] | 常に | 直近100返金:id、payment_intent_id、amount_atomic、destination、status、request、treasury_intent_id、transfer_status、created_at、transactions(id/status)。返金送信はコンソール専用。 |
| observations | object[] | 常に | 直近100件:payment_intent_id、transaction_id、event_index、amount、status、confirmations、observed_at、symbol、chain、disabled_at_detection。対応時はexplorer_name/explorer_url付き。 |
| deliveries | object[] | 常に | 直近50件:id、kind、status、attempts、response_status、error、next_attempt_at、event_type、created_at。通知シークレットなし。 |
請求書サマリー
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | 内部請求書UUID。加盟店詳細や決済パスに使わないでください。 |
| invoice_id | UUID | 常に | 加盟店詳細・決済パスで使う公開請求書UUID。 |
| project_id | UUID | 常に | 所有プロジェクト。 |
| store_id | UUID | 常に | 所有ストア。 |
| source | manual | api | 常に | 請求書の作成経路。 |
| order_id | string | null | 常に | 加盟店の注文参照値。 |
| string | null | 常に | 加盟店専用の顧客メール。公開決済には返しません。 | |
| customer_name | string | null | 常に | 非公開firstname、lastname、companyメタデータから作る表示名。 |
| customer_address | string | null | 常に | 非公開company、street、street2、zip、city、country、countryiso2、vatidから作る1行住所。 |
| description | string | null | 常に | 顧客向け説明。 |
| amount | decimal string | 常に | 正規化した請求額。 |
| currency | string | 常に | 正規化した請求通貨/資産コード。 |
| exchange_rate_spread_percent | decimal string | 常に | 固定スプレッド:作成時の上書き、なければストア標準。切り上げ前に適用し、この請求書では変わりません。 |
| underpayment_tolerance_percent | decimal string | 常に | 作成時に保存した不変の不足許容率。 |
| status | invoice status | 常に | new、processing、settled、expired、invalid、cancelled。 |
| amount_status | amount status | 常に | none、partial、paid、overpaid。明示許可した金額0はnoneで確定し、決済方法はありません。 |
| timing_status | timing status | 常に | on_timeまたはlate。 |
| resolution | resolution | 常に | automatic、manually_settled、manually_invalidated。 |
| sequence | integer | 常に | 1から単調増加する請求書状態シーケンス。 |
| winning_payment_intent_id | UUID | null | 常に | 選択された場合の、請求書を確定させた決済方法。 |
| expires_at | RFC 3339 timestamp | 常に | 見積もり/支払期限。 |
| monitoring_expires_at | RFC 3339 timestamp | 常に | 各方法の設定済み遅延監視期限のうち最も遅い時刻。 |
| settled_at | timestamp | null | 常に | settledになった時刻。 |
| cancelled_at | timestamp | null | 常に | キャンセル時刻。 |
| archived_at | timestamp | null | 常に | アーカイブ時刻。 |
| created_at | RFC 3339 timestamp | 常に | 作成時刻。 |
| updated_at | RFC 3339 timestamp | 常に | 最終状態更新時刻。 |
請求書詳細の追加項目
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ipn_url | string | null | 常に | 請求書ごとの有効IPN送信先。加盟店応答のみで公開決済からは省きます。 |
| redirect_url | string | null | 常に | 確定後に使う有効な成功URL。 |
| cancel_url | string | null | 常に | 支払い成功せず終了する場合の有効な戻り先URL。 |
| redirect_automatically | boolean | 常に | 成功後に自動リダイレクトするか。 |
| checkout_language | string | 常に | 有効な決済画面の言語タグ。 |
| metadata | object | 常に | 加盟店メタデータ。公開決済には返しません。 |
| payment_intents | PaymentIntent[] | 常に | 見積もり済みの決済方法と監視状態。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{"invoice":{"invoice_id":"YOUR_PUBLIC_INVOICE_ID","status":"processing"},"case":{"status":"open","reasons":["underpaid"],"revision":1},"methods":[],"history":[],"history_pagination":{"page":1,"per_page":25,"total":0},"refunds":[],"observations":[],"deliveries":[]}GETAPIサービスの検出/公開
v1公開APIの役割を確認する管理APIホストのエッジ応答。加盟店Axumルーターではなく管理プロキシが生成します。
- Bearerトークンは不要です。
- この正確なルート応答を保証するのは管理APIホストだけです。
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/"// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://api.example.com/", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://api.example.com/");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://api.example.com/",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"service": "Wholly Crypto API",
"status": "ready",
"version": "v1"
}GETサービスの稼働状態/healthz公開
アプリ到達性と2秒のDB pingを確認します。監視用で、請求書状態の代わりではありません。
- Bearerトークンは不要です。
- versionは稼働パッケージのバージョンで、APIパスのバージョンではありません。
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/healthz"// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://api.example.com/healthz", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://api.example.com/healthz");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://api.example.com/healthz",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 正常200、DB利用不可503
{
"status": "ok",
"database": "ok",
"version": "0.1.0"
}GETプロジェクトの決済資産一覧/v1/projects/{project_id}/payment-assets読み取り専用
ネイティブ資産と検証トークンに、プロジェクト方針、チェーンウォレット準備、導入済みスキャナー/残高機能を付けて返します。scanner_readyはアダプタービルドの条件で、現在のノード定足数ではありません。6.0.6以降はスキャナー停止中も設定方法を保持して作成します。入金検証には設定した正常・適切な役割のプロバイダー数(標準2、任意1)が必要です。
- 全体一覧にあるトークンでもscanner_readyまたはpayment_supportedがfalseなら選べません。
- Operator機能表でもスキャナーと正確に一致するエンドポイント役割が必要です。健康でも非互換APIなら数えません。
- トークンはネイティブチェーンのプロジェクトウォレットを共有し、別のseedフレーズを作りません。
- 埋め込みウォレットサマリーは準備状態のみで残高は空です。残高付きはGET /v1/projects/{project_id}/walletsを使ってください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てた有効なプロジェクト。 |
PaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | プロジェクト・ストアのポリシールートで使う永続的な決済資産ID。 |
| asset_key | string | 常に | 正規CAIP形式のネイティブ/コントラクト資産ID。 |
| chain_slug / network | string | 常に | Wholly Cryptoのチェーン識別子と設定ネットワーク。 |
| caip_network_id / caip_asset_id | string / string|null | 常に | 正規のネットワーク・資産ID。 |
| asset_kind | native | token | 常に | チェーン通貨か検証済みコントラクト/mintで決済するか。 |
| payment_rail | string | 常に | 実行経路:utxo、evm-native、solana-native、account-native、privacy-native、token-transfer。 |
| symbol / name / decimals | string / string / integer | 常に | 表示情報と正確な最小単位精度。 |
| contract_address | string | null | 常に | トークンは正規ERC-20コントラクトまたはSPL mint、ネイティブはnull。 |
| coingecko_id | string | null | 常に | 検索・価格用ID。カスタムコントラクトはnullで、ティッカーから市場価格を推測しません。CoinGecko情報だけで選択可能にはなりません。 |
| custom_token | boolean | 常に | オンチェーン検証済みのカスタムコントラクト。プロジェクト単位の固定USD価格または選択DEXプールを使います。 |
| icon_path | path | null | 常に | 利用可能ならローカルキャッシュのトークンアイコン。 |
| token_standard | erc20 | spl-token | null | 常に | 検証済みの実行トークン規格。ネイティブはnull。 |
| metadata_verified_at | timestamp | null | 常に | 登録トークンのオンチェーン情報検証時刻。 |
| payment_supported / scanner_ready / balance_ready | boolean | 常に | ビルド時の登録条件。scanner_readyは決済スキャナー実装が導入済みという意味です。入金確定には正常で適切な役割のプロバイダーが設定数必要(標準2、任意1)。6.0.6以降は一時的なスキャナー不通で請求書作成を止めません。balance_readyは実装済み残高アダプターだけtrueです。 |
| default_finality_mode | confirmations | finalized | 常に | 新しいプロジェクトポリシーが継承する標準確定モデル。 |
| default_required_confirmations / default_monitoring_minutes | integer | 常に | 標準の承認・監視ポリシー。 |
ProjectPaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| asset | PaymentAsset | 常に | 永続登録のネイティブまたは検証済みトークン資産。 |
| policy | ProjectAssetPolicy | null | 常に | プロジェクト有効化/確定ポリシー。未設定ならnull。custom_price_mode(fixed/dex)、custom_price_usd(固定小数文字列またはnull)、custom_dex_pair(選択プールまたはnull)、custom_dex(dex_id、quote_symbol、現在のprice_usdまたはnull、liquidity_usd、fetched_at、last_error)を含みます。カスタム価格は同じプロジェクトのストアで共有します。 |
| wallet | WalletSummary | null | 常に | チェーンの非カストディアルなプロジェクトウォレット。トークンもネイティブウォレットを共有します。 |
| wallet_readiness | readiness enum | 常に | unsupported、project_disabled、project_asset_disabled、store_disabled、store_asset_disabled、wallet_missing、wallet_pending、wallet_disabled、wallet_error、backup_required、account_activation_required、external_wallet_rpc_required、ready。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | 共通の受取準備評価。ウォレットと独立スキャナープロバイダー確認を含み、残高鮮度や送信用ガスとは別です。ポリシーなしはnull。通貨/レートは請求書作成時に確認します。 |
WalletSummary
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id / project_id / native_asset_id | UUID | 常に | ウォレット、所有プロジェクト、チェーンネイティブ資産のID。 |
| chain_slug / network | string | 常に | ウォレットのチェーンとネットワーク。 |
| asset_symbol / asset_name | string | 常に | ネイティブ資産の表示情報。 |
| status | pending | active | disabled | error | 常に | ウォレットの運用状態。 |
| label | string | 常に | 運用者が付けたラベル。 |
| public_key / primary_address | string | null | 常に | 公開ウォレット情報。seedフレーズや秘密鍵は公開しません。 |
| derivation_scheme / address_format | string | null | 常に | アドレス方針と形式。 |
| backup_confirmed_at | timestamp | null | 常に | 運用者が復元用バックアップを確認すると非nullになります。 |
| activation_required / activation_verified_at | boolean / timestamp|null | 常に | XRPとStellarの共有アカウントは、表示アドレスに入金し、設定スキャナープロバイダーがその正確なアカウントを検証するまで利用できません。保存済み証明は失効しません。ライブのスキャナー状態は請求書作成ではなく入金検証時に別途確認します。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | ウォレット一覧に含むプロジェクト受取準備とスキャナー要件。残高、トークンガス、送金準備とは別です。他のウォレット応答ではnullの場合があります。 |
| monero_wallet_rpc | MoneroWalletRpcBinding | null | 常に | Moneroの外部閲覧専用wallet-RPC紐付け状態から秘密情報を除いたもの。endpoint、認証方式、account-0基本アドレス、技術証明フラグ/高さ、運用者確認時刻を含みます。認証情報、ウォレットキー、ファイルは出力しません。 |
| last_secret_revealed_at / secret_reveal_count | timestamp|null / integer | 常に | コンソールで秘密情報を表示した監査メタデータ。 |
| next_receive_index | integer | 常に | 次に予約する子アドレスのインデックス。 |
| last_scanned_height / last_scanned_at / last_error | integer|null / timestamp|null / string|null | 常に | ウォレットスキャナーの状態。 |
| balances | WalletAssetBalance[] | 常に | 30ネイティブチェーンすべてと検証済みERC-20/SPLのキャッシュ残高。Moneroは外部閲覧専用wallet-RPC設定が必要です。 |
| total_value_usd | decimal string | null | 常に | 現在のUSD価格がある残高の参考合計。 |
| balance_status | pending | refreshing | fresh | stale | error | unknown | 常に | 集計キャッシュの鮮度。unknownは安全側の代替値で、どの状態も請求書の決済確定を証明しません。 |
| balance_checked_at | timestamp | null | 常に | 集計に含まれる関連する成功残高確認の最古時刻。 |
| recent_payments | WalletRecentPayment[] | 常に | このウォレットに対応する、有効なdetected/confirming/finalの直近最大3件。 |
| created_at / updated_at | RFC 3339 timestamp | 常に | 作成時刻と最終ウォレット更新時刻。 |
ReceiveReadiness
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ready | boolean | 常に | 受取準備の確認に合格。送金準備、ガス、残高更新、将来の見積もり保証を意味しません。 |
| invoice_creatable | boolean | 6.0.6+ | 一時スキャナー警告があっても設定上は請求方法を作成可能です。通貨価格は作成時確認。入金検証とは異なり、ready=falseでもinvoice_creatable=trueになれます。ウォレット不足、無効方針、非対応アダプターは安全に拒否します。 |
| checked_at | timestamp | 常に | 評価時刻。一覧取得でネットワーク照会やアドレス割当は行いません。 |
| issues | PaymentMethodIssue[] | 常に | 準備済みなら空。それ以外は受取警告や設定上の障害。invoice_creatableで一時スキャナー警告と作成準備の失敗を区別します。 |
PaymentMethodIssue
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug / asset_id / asset_ticker | string / UUID / string | 判明している場合 | 対象チェーンと資産を示します。Lightningはasset_idを省く場合があります。 |
| reason_code | string | 常に | scanner_provider_quorum、scanner_not_checked、scanner_unavailable、wallet_missing、wallet_disabled、wallet_backup_required、wallet_key_unavailable、wallet_activation_required、monero_binding_unavailable、rate_unavailable、custom_rate_unavailable、lightning_unavailable、project_disabled、store_disabled、chain_disabled、asset_disabled、asset_not_accepted。 |
| message / action | string | 利用可能な場合 | 加盟店向け説明と操作ID:chain_connections、wallets、rates、payment_methods、project_settings、store_settings。認証情報や非公開プロバイダーURLは含みません。 |
| required_endpoint_role | string | null | オンチェーン | 優先スキャナーAPI役割(旧フィールド)。全互換リストはaccepted_endpoint_rolesを使います。基本稼働確認は支払履歴対応を証明しません。 |
| accepted_endpoint_roles | string[] | null | オンチェーン | 互換APIの種類で、履歴や処理能力の証明ではありません。raw node-rpcはBTC/BCH/LTC/DOGE/DASHと透明ZEC(完全復号ブロック、1〜48承認)、solidifiedネイティブTRX、algodのALGO、OctezのXTZ、SCALEメタデータの確定Asset Hub DOT、請求memo ID付きStellar RPCのXLMに対応。pruned・不完全履歴は対象外で、トークン経路は追加しません。インデックスAPIも選べます。raw/インデックス混合ソースは範囲を独立検証し、標準は同じ運営者の別名でなく独立2プロバイダーです。基本ノード高さ、ORDnet情報、非EVM経路へのEVM relayは入金証明になりません。Moneroには専用閲覧wallet-RPCが必要です。 |
| healthy_endpoints | integer | オンチェーン | 正常で一致するエンドポイント数。独立プロバイダー数ではありません。 |
| usable_independent_providers / required_independent_providers | integer | オンチェーン | 利用できる検証枠、最大2。required_independent_providersはチェーン設定で標準2、管理者の明示選択後は1。2の場合はプロバイダーキーとホストの両方が異なる必要があります。無効、10分超古い、クールダウン中は枠に入りません。Lightningは別ルールです。 |
| last_checked_at | timestamp | null | オンチェーン | 一致するエンドポイントの最新稼働確認。評価時刻とは別です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{
"asset": {
"id": "10000000-0000-4000-8000-000000000003",
"asset_key": "eip155:1/slip44:60",
"chain_slug": "ethereum",
"network": "mainnet",
"caip_network_id": "eip155:1",
"caip_asset_id": "eip155:1/slip44:60",
"asset_kind": "native",
"payment_rail": "evm-native",
"symbol": "ETH",
"name": "Ethereum",
"decimals": 18,
"contract_address": null,
"coingecko_id": "ethereum",
"icon_path": "/assets/coingecko/ethereum.png",
"token_standard": null,
"metadata_verified_at": null,
"payment_supported": true,
"scanner_ready": true,
"balance_ready": true,
"default_finality_mode": "confirmations",
"default_required_confirmations": 12,
"default_monitoring_minutes": 60
},
"policy": {
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 12,
"monitoring_minutes": 60,
"late_monitoring_days": 30
},
"wallet": null,
"wallet_readiness": "wallet_missing",
"receive_readiness": { "ready": false, "invoice_creatable": false, "checked_at": "2026-09-16T09:00:00Z", "issues": [{ "chain_slug": "ethereum", "asset_id": "10000000-0000-4000-8000-000000000003", "asset_ticker": "ETH", "reason_code": "wallet_missing", "message": "ethereum / ETH: Create a project wallet for this chain.", "action": "wallets" }] }
}
]
}PUTプロジェクトの資産ポリシーを更新/v1/projects/{project_id}/payment-assets/{asset_id}読み取り+書き込み
1つの永続資産のプロジェクト方針を作成・置換し、最新一覧を返します。ネイティブチェーン無効化はそのコインとトークンを新規請求書で使えなくしますが、後で再開できるようトークン方針、ウォレット、ストア選択を保持します。
- 本文はポリシー全置換で、未知のフィールドは拒否します。
- プロジェクトで有効にしてもストアの選択には入りません。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | 必須 | application/json |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てた有効なプロジェクト。 |
| asset_id | path UUID | プロジェクト資産一覧またはトークン登録が返すasset id。 |
プロジェクト資産ポリシー更新
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| enabled | boolean | 必須 | プロジェクトで資産を有効/無効にします。トークンより先にネイティブチェーンを有効にします。 |
| finality_mode | confirmations | finalized | 必須 | 資産経路が対応する確定方針。finalizedではrequired_confirmations=1が必要です。 |
| required_confirmations | integer | 必須 | BitcoinとEVMは0を許可。他の承認数型は1以上、finalized専用はちょうど1です。EVMは送金を再検証範囲内に保つため0〜48に制限します。 |
| monitoring_minutes | integer | 必須 | 請求書が有効な間のポーリング期間、1〜10,080分。 |
| late_monitoring_days | integer | 必須 | 請求期限後の監視、0〜3,650日。 |
PaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | プロジェクト・ストアのポリシールートで使う永続的な決済資産ID。 |
| asset_key | string | 常に | 正規CAIP形式のネイティブ/コントラクト資産ID。 |
| chain_slug / network | string | 常に | Wholly Cryptoのチェーン識別子と設定ネットワーク。 |
| caip_network_id / caip_asset_id | string / string|null | 常に | 正規のネットワーク・資産ID。 |
| asset_kind | native | token | 常に | チェーン通貨か検証済みコントラクト/mintで決済するか。 |
| payment_rail | string | 常に | 実行経路:utxo、evm-native、solana-native、account-native、privacy-native、token-transfer。 |
| symbol / name / decimals | string / string / integer | 常に | 表示情報と正確な最小単位精度。 |
| contract_address | string | null | 常に | トークンは正規ERC-20コントラクトまたはSPL mint、ネイティブはnull。 |
| coingecko_id | string | null | 常に | 検索・価格用ID。カスタムコントラクトはnullで、ティッカーから市場価格を推測しません。CoinGecko情報だけで選択可能にはなりません。 |
| custom_token | boolean | 常に | オンチェーン検証済みのカスタムコントラクト。プロジェクト単位の固定USD価格または選択DEXプールを使います。 |
| icon_path | path | null | 常に | 利用可能ならローカルキャッシュのトークンアイコン。 |
| token_standard | erc20 | spl-token | null | 常に | 検証済みの実行トークン規格。ネイティブはnull。 |
| metadata_verified_at | timestamp | null | 常に | 登録トークンのオンチェーン情報検証時刻。 |
| payment_supported / scanner_ready / balance_ready | boolean | 常に | ビルド時の登録条件。scanner_readyは決済スキャナー実装が導入済みという意味です。入金確定には正常で適切な役割のプロバイダーが設定数必要(標準2、任意1)。6.0.6以降は一時的なスキャナー不通で請求書作成を止めません。balance_readyは実装済み残高アダプターだけtrueです。 |
| default_finality_mode | confirmations | finalized | 常に | 新しいプロジェクトポリシーが継承する標準確定モデル。 |
| default_required_confirmations / default_monitoring_minutes | integer | 常に | 標準の承認・監視ポリシー。 |
ProjectPaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| asset | PaymentAsset | 常に | 永続登録のネイティブまたは検証済みトークン資産。 |
| policy | ProjectAssetPolicy | null | 常に | プロジェクト有効化/確定ポリシー。未設定ならnull。custom_price_mode(fixed/dex)、custom_price_usd(固定小数文字列またはnull)、custom_dex_pair(選択プールまたはnull)、custom_dex(dex_id、quote_symbol、現在のprice_usdまたはnull、liquidity_usd、fetched_at、last_error)を含みます。カスタム価格は同じプロジェクトのストアで共有します。 |
| wallet | WalletSummary | null | 常に | チェーンの非カストディアルなプロジェクトウォレット。トークンもネイティブウォレットを共有します。 |
| wallet_readiness | readiness enum | 常に | unsupported、project_disabled、project_asset_disabled、store_disabled、store_asset_disabled、wallet_missing、wallet_pending、wallet_disabled、wallet_error、backup_required、account_activation_required、external_wallet_rpc_required、ready。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | 共通の受取準備評価。ウォレットと独立スキャナープロバイダー確認を含み、残高鮮度や送信用ガスとは別です。ポリシーなしはnull。通貨/レートは請求書作成時に確認します。 |
ReceiveReadiness
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ready | boolean | 常に | 受取準備の確認に合格。送金準備、ガス、残高更新、将来の見積もり保証を意味しません。 |
| invoice_creatable | boolean | 6.0.6+ | 一時スキャナー警告があっても設定上は請求方法を作成可能です。通貨価格は作成時確認。入金検証とは異なり、ready=falseでもinvoice_creatable=trueになれます。ウォレット不足、無効方針、非対応アダプターは安全に拒否します。 |
| checked_at | timestamp | 常に | 評価時刻。一覧取得でネットワーク照会やアドレス割当は行いません。 |
| issues | PaymentMethodIssue[] | 常に | 準備済みなら空。それ以外は受取警告や設定上の障害。invoice_creatableで一時スキャナー警告と作成準備の失敗を区別します。 |
PaymentMethodIssue
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug / asset_id / asset_ticker | string / UUID / string | 判明している場合 | 対象チェーンと資産を示します。Lightningはasset_idを省く場合があります。 |
| reason_code | string | 常に | scanner_provider_quorum、scanner_not_checked、scanner_unavailable、wallet_missing、wallet_disabled、wallet_backup_required、wallet_key_unavailable、wallet_activation_required、monero_binding_unavailable、rate_unavailable、custom_rate_unavailable、lightning_unavailable、project_disabled、store_disabled、chain_disabled、asset_disabled、asset_not_accepted。 |
| message / action | string | 利用可能な場合 | 加盟店向け説明と操作ID:chain_connections、wallets、rates、payment_methods、project_settings、store_settings。認証情報や非公開プロバイダーURLは含みません。 |
| required_endpoint_role | string | null | オンチェーン | 優先スキャナーAPI役割(旧フィールド)。全互換リストはaccepted_endpoint_rolesを使います。基本稼働確認は支払履歴対応を証明しません。 |
| accepted_endpoint_roles | string[] | null | オンチェーン | 互換APIの種類で、履歴や処理能力の証明ではありません。raw node-rpcはBTC/BCH/LTC/DOGE/DASHと透明ZEC(完全復号ブロック、1〜48承認)、solidifiedネイティブTRX、algodのALGO、OctezのXTZ、SCALEメタデータの確定Asset Hub DOT、請求memo ID付きStellar RPCのXLMに対応。pruned・不完全履歴は対象外で、トークン経路は追加しません。インデックスAPIも選べます。raw/インデックス混合ソースは範囲を独立検証し、標準は同じ運営者の別名でなく独立2プロバイダーです。基本ノード高さ、ORDnet情報、非EVM経路へのEVM relayは入金証明になりません。Moneroには専用閲覧wallet-RPCが必要です。 |
| healthy_endpoints | integer | オンチェーン | 正常で一致するエンドポイント数。独立プロバイダー数ではありません。 |
| usable_independent_providers / required_independent_providers | integer | オンチェーン | 利用できる検証枠、最大2。required_independent_providersはチェーン設定で標準2、管理者の明示選択後は1。2の場合はプロバイダーキーとホストの両方が異なる必要があります。無効、10分超古い、クールダウン中は枠に入りません。Lightningは別ルールです。 |
| last_checked_at | timestamp | null | オンチェーン | 一致するエンドポイントの最新稼働確認。評価時刻とは別です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request PUT \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID", {
method: "PUT",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID",
method="PUT", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{ "asset": { "id": "ASSET_UUID", "symbol": "USDC", "asset_kind": "token", "scanner_ready": true }, "policy": { "enabled": true, "finality_mode": "confirmations", "required_confirmations": 2, "monitoring_minutes": 60, "late_monitoring_days": 30 }, "wallet_readiness": "ready" }
]
}GET決済用トークン候補を見る/v1/projects/{project_id}/payment-token-candidates読み取り専用
トークンスキャナーと残高アダプターを実装したチェーンだけで、ローカルCoinGeckoコントラクト対応表を検索します。結果は候補であり信頼済み決済資産ではありません。
- 対応:Ethereum、Base、BNB Chain、HyperEVM、Avalanche、Polygon、Arbitrum、OptimismのERC-20とSolanaのSPL。
- 非対応カタログチェーンは選択可能に見せず拒否します。
- CoinGecko順位、アイコン、価格は参考検索データです。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てた有効なプロジェクト。 |
| chain_slug | query string | 対応EVMチェーンslugまたはsolanaが必須。 |
| q | query string | 任意の名前、シンボル、CoinGecko id、コントラクト/mintの部分文字列。最大80文字。 |
| limit | query integer | 任意で1〜100。標準50。 |
TokenCandidate
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| coingecko_id | string | 常に | 登録リクエストで使うCoinGecko候補ID。 |
| chain_slug | string | 常に | 対応するWholly Cryptoチェーン。 |
| symbol / name | string | 常に | カタログ上の表示情報。 |
| contract_address | string | 常に | 対応するコントラクト/mint。登録前にオンチェーン検証します。 |
| market_cap_rank | integer | null | 常に | 検索順位。信頼や決済準備の証明ではありません。 |
| icon_path | path | 常に | ローカルキャッシュのCoinGeckoアイコンパス。 |
| current_price_usd | decimal string | null | 常に | 参考キャッシュUSD価格。 |
| token_standard | erc20 | spl-token | 常に | 選択チェーンアダプターが対応するトークン規格。 |
| scanner_ready | boolean | 常に | このビルドで実装済みのトークン経路の候補だけtrue。 |
| registered_asset_id | UUID | null | 常に | 登録済みなら既存の永続資産。 |
| project_enabled | boolean | 常に | 登録資産がこのプロジェクトで有効か。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{
"coingecko_id": "usd-coin",
"chain_slug": "ethereum",
"symbol": "USDC",
"name": "USDC",
"contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"market_cap_rank": 7,
"icon_path": "/assets/coingecko/usd-coin.png",
"current_price_usd": "1.0001",
"token_standard": "erc20",
"scanner_ready": true,
"registered_asset_id": null,
"project_enabled": false
}
]
}POSTトークンを検証して登録/v1/projects/{project_id}/payment-token-assets読み取り+書き込み
設定ノードがチェーン、コントラクト/mint、小数桁、有効な残高照会を検証してから候補を永続登録します。CoinGecko情報だけは信用せず、プロジェクトは登録トークン20件までです。
- トークン登録前にチェーンのネイティブ資産を有効にしてください。
- プロジェクトのトークンは最大20件。上限後の新候補はtoken_chain_not_ready(409)です。登録済みの再利用は追加枠を使いません。
- ノード検証はカタログ取得より時間がかかるので、明示的なクライアントタイムアウトを設定してください。
- 登録後、提供する各ストアで資産を選択します。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | 必須 | application/json |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てた有効なプロジェクト。 |
トークン登録本文
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug | string | 必須 | ethereum、base、bnb-chain、hyperliquid、avalanche、polygon、arbitrum、optimism、solana。 |
| coingecko_id | string | 必須 | 検索結果の正確な候補ID。_や-6など先頭のアンダースコア/ハイフンを保持します。名前やティッカーからIDを作らないでください。 |
| enabled | boolean | 任意 | 検証後のプロジェクト方針状態。標準true。 |
RegisteredTokenAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| asset_id | UUID | 常に | 永続決済資産ID。 |
| chain_slug / coingecko_id | string | 常に | 検証チェーンと保持された検索/価格ID。 |
| contract_address | string | 常に | 正規の検証コントラクト/mint。 |
| token_standard | erc20 | spl-token | 常に | 検証済み実行トークン規格。 |
| symbol / name / decimals | string / string / integer | 常に | 登録された表示情報と正確な精度。 |
| enabled | boolean | 常に | 初期プロジェクト方針状態。 |
| metadata_verified_at | RFC 3339 timestamp | 常に | オンチェーン検証時刻。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 201 application/json
{
"data": {
"asset_id": "44444444-4444-4444-8444-444444444444",
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"token_standard": "erc20",
"symbol": "USDC",
"name": "USDC",
"decimals": 6,
"enabled": true,
"metadata_verified_at": "2026-08-31T18:00:00Z"
}
}GETカスタムトークンのDEXプールを検索/v1/projects/{project_id}/payment-token-dex-pools読み取り専用
DEX Screenerで正確なチェーンとベーストークン契約に合う最大12プールを流動性順に検索します。トークン登録・有効化はしません。
- dataが空なら適格プールなし。指定契約がベーストークンのプールだけ返し、クォート側USD価格を推測しません。
- DEX掲載はセキュリティ監査ではありません。最低流動性と最近の取引は使えない価格を減らしますが、価格操作は防ぎません。
- 既存スキャナーがトークンに対応するチェーンではUniswap、PancakeSwapなど索引対象DEXに対応します。APIはプロジェクト範囲と回数制限を維持し、プロバイダー呼び出しも直列化・間隔制限します。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 割り当て済みプロジェクト。 |
| chain_slug | query string | 対応EVMトークンチェーンまたはsolana。 |
| contract_address | query string | 正確なERC-20コントラクトまたはclassic SPL mint。 |
CustomDexPool
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| pair_address / dex_id / quote_symbol | string | 常に | 正確なプールID、取引所ID(例uniswap/pancakeswap)、表示用ペアティッカー。 |
| price_usd / liquidity_usd | decimal string | 常に | 要求したベーストークンのUSD価格とプール総流動性。最低$10,000の流動性と直近1時間の取引が必要です。 |
| fetched_at | RFC 3339 timestamp | 常に | サーバーが観測値を取得した時刻。オンチェーン取引の時刻ではありません。 |
| url | HTTPS URL | 常に | このプールへの検証済みDEX Screenerリンク。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{"data":[{"pair_address":"0x2222222222222222222222222222222222222222","dex_id":"uniswap","quote_symbol":"WETH","price_usd":"0.25","liquidity_usd":"250000.00","fetched_at":"2026-09-09T12:00:00Z","url":"https://dexscreener.com/ethereum/0x2222222222222222222222222222222222222222"}]}POSTカスタムトークンを追加・価格変更/v1/projects/{project_id}/payment-token-assets/custom読み取り+書き込み
設定ノードで独自契約を検証し、CoinGecko掲載なしで登録します。固定USD価格や自動DEXプールはこのプロジェクトに属し、ティッカーや他プロジェクトには属しません。同じIDの再送は有効/無効方針を変えず価格を更新します。
- 登録後、ストアのpayment-assetsエンドポイントでasset_idを選びます。登録だけでストア方法を有効にはしません。
- カスタムとカタログは20トークン枠を共有します。異なるチェーンの同じ契約は別資産です。
- 既存カタログ契約は409。自動市場価格を保つにはカタログ登録を使います。カスタムティッカーは同名トークンの価格を借りません。
- 固定価格は運用者の見積もり。DEX自動価格は選択プールのDEX Screener観測値で、操作耐性オラクルではありません。新しい法定通貨レートにストアスプレッドと切り上げを適用します。発行済み見積もりは不変です。
- DEXモードは先にプールを探し、price_mode: dexとdex_pair_addressを送りprice_usdを省きます。共通バックグラウンド処理が毎分更新。検証失敗や5分超の価格は新見積もりから除外し、固定価格やティッカーへ黙って代替しません。
- 標準ERC-20とclassic SPLのみ。Token-2022/拡張やネイティブ専用チェーンは拒否します。技術検証は発行者/契約監査ではありません。送金課税、rebasing、ブラックリスト型は非互換動作の場合があります。
- クライアントタイムアウトは60秒以上にしてください。検証は上限付きで代替ノードを試せます。不正入力400、チェーン/契約失敗422、ID競合や上限409です。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | 必須 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 書き込み可能な認証情報に割り当てたプロジェクト。 |
カスタムトークン登録
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug | string | 必須 | ethereum、base、bnb-chain、hyperliquid、avalanche、polygon、arbitrum、optimism、solana。この契約では固定です。 |
| contract_address | string | 必須 | ERC-20契約(0x+16進40文字)またはclassic SPL mint。ノードがネットワークと桁数を検証し、呼び出し側のdecimals/RPC URLは拒否します。 |
| name / symbol | string / string | 必須 | 表示名1〜80文字、ティッカー1〜16文字(英数字・ドット・アンダースコア・ハイフン、先頭英数字)。既存IDをこのエンドポイントで改名できません。 |
| price_mode | fixed | dex | 任意 | 後方互換の標準はfixed。DEXは正確なチェーン/契約で検索した特定プールを使います。 |
| price_usd | decimal string | fixedモード | 1トークンの固定USD価格。正数、小数30桁まで、最大1000000000000000000000000。指数やfloatは禁止。dexでは省略します。 |
| dex_pair_address | string | dexモード | payment-token-dex-poolsのプールアドレス。dex必須、fixedでは省略。保存ごとにID、価格、流動性、活動を再確認します。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{"data":{"asset_id":"44444444-4444-4444-8444-444444444444"}}GETストアの決済方法一覧/v1/projects/{project_id}/stores/{store_id}/payment-assets読み取り専用
dataにオンチェーン資産、lightningに別の準備状態を返します。オンチェーンには準備済みウォレットが必要。Lightningはストアが選んだ検証済み外部受取接続を使い、Bitcoinオンチェーンウォレットと独立です。
- selectedはオンチェーン設定、wallet_readinessは現在の適格条件です。
- lightningにはpayment_rail: lightning、symbol: BTC、asset_decimals: 11、enabled、readyが入ります。ノード認証情報は含みません。ストアのコンソールで設定し、assets配列の更新では変わりません。
- confirmation_policyはオンチェーンだけ。Lightningはブロック承認なしで確定し、部分許容なしでBOLT11全額が必要です。
- 同じチェーンのネイティブとトークンは、そのウォレットの同じ請求書受取先を使います。
- 埋め込みウォレット概要は準備状態のみで残高は空。現在値には専用プロジェクトウォレットルートを使います。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てたプロジェクト。停止中でも可。 |
| store_id | path UUID | project_idに属するストア。停止中でも可。 |
PaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | プロジェクト・ストアのポリシールートで使う永続的な決済資産ID。 |
| asset_key | string | 常に | 正規CAIP形式のネイティブ/コントラクト資産ID。 |
| chain_slug / network | string | 常に | Wholly Cryptoのチェーン識別子と設定ネットワーク。 |
| caip_network_id / caip_asset_id | string / string|null | 常に | 正規のネットワーク・資産ID。 |
| asset_kind | native | token | 常に | チェーン通貨か検証済みコントラクト/mintで決済するか。 |
| payment_rail | string | 常に | 実行経路:utxo、evm-native、solana-native、account-native、privacy-native、token-transfer。 |
| symbol / name / decimals | string / string / integer | 常に | 表示情報と正確な最小単位精度。 |
| contract_address | string | null | 常に | トークンは正規ERC-20コントラクトまたはSPL mint、ネイティブはnull。 |
| coingecko_id | string | null | 常に | 検索・価格用ID。カスタムコントラクトはnullで、ティッカーから市場価格を推測しません。CoinGecko情報だけで選択可能にはなりません。 |
| custom_token | boolean | 常に | オンチェーン検証済みのカスタムコントラクト。プロジェクト単位の固定USD価格または選択DEXプールを使います。 |
| icon_path | path | null | 常に | 利用可能ならローカルキャッシュのトークンアイコン。 |
| token_standard | erc20 | spl-token | null | 常に | 検証済みの実行トークン規格。ネイティブはnull。 |
| metadata_verified_at | timestamp | null | 常に | 登録トークンのオンチェーン情報検証時刻。 |
| payment_supported / scanner_ready / balance_ready | boolean | 常に | ビルド時の登録条件。scanner_readyは決済スキャナー実装が導入済みという意味です。入金確定には正常で適切な役割のプロバイダーが設定数必要(標準2、任意1)。6.0.6以降は一時的なスキャナー不通で請求書作成を止めません。balance_readyは実装済み残高アダプターだけtrueです。 |
| default_finality_mode | confirmations | finalized | 常に | 新しいプロジェクトポリシーが継承する標準確定モデル。 |
| default_required_confirmations / default_monitoring_minutes | integer | 常に | 標準の承認・監視ポリシー。 |
StorePaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| asset | PaymentAsset | 常に | プロジェクトから見えるネイティブ/検証トークン資産。 |
| project_policy | ProjectAssetPolicy | null | 常に | 親プロジェクトのポリシー。 |
| selected | boolean | 常に | ストアに保存した希望設定に含むか。プロジェクト方針、ウォレット、導入アダプター、価格が有効なら提供します。一時スキャナー不通で新請求書から除外しません。 |
| display_order | integer | null | 常に | 選択時の決済表示順。 |
| confirmation_policy | StoreConfirmationPolicy | null | 常に | 設定済み資産の有効ストア方針。プロジェクト方針なしはnull。 |
| wallet | WalletSummary | null | 常に | ネイティブとトークンで共有するチェーンウォレット。 |
| wallet_readiness | readiness enum | 常に | ウォレット/ポリシー状態のみ。スキャナー要件はreceive_readinessを使います。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | 共通受取設定とストア受入。キャッシュ評価で、予約や保証ではありません。作成時に要件と実際の換算レートを再確認します。 |
StoreConfirmationPolicy
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| finality_mode | confirmations | finalized | 常に | 設定可能なブロック数かネットワーク確定性を使うか。 |
| project_required_confirmations | integer | 常に | ストア上書きなしで今後の請求書が使う現在のプロジェクト標準。 |
| override_required_confirmations | integer | null | 常に | ストア専用数、または継承するnull。 |
| effective_required_confirmations | integer | 常に | このストア/資産の新請求書に保存する数。 |
| editable | boolean | 常に | 確定方針を変更できないfinalizedネットワークではfalse。 |
| minimum_required_confirmations | integer | 常に | チェーン別の下限(含む)。検出時受理に対応する経路のみ0を提示します。 |
| maximum_required_confirmations | integer | 常に | チェーン別の上限(含む)。 |
WalletSummary
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id / project_id / native_asset_id | UUID | 常に | ウォレット、所有プロジェクト、チェーンネイティブ資産のID。 |
| chain_slug / network | string | 常に | ウォレットのチェーンとネットワーク。 |
| asset_symbol / asset_name | string | 常に | ネイティブ資産の表示情報。 |
| status | pending | active | disabled | error | 常に | ウォレットの運用状態。 |
| label | string | 常に | 運用者が付けたラベル。 |
| public_key / primary_address | string | null | 常に | 公開ウォレット情報。seedフレーズや秘密鍵は公開しません。 |
| derivation_scheme / address_format | string | null | 常に | アドレス方針と形式。 |
| backup_confirmed_at | timestamp | null | 常に | 運用者が復元用バックアップを確認すると非nullになります。 |
| activation_required / activation_verified_at | boolean / timestamp|null | 常に | XRPとStellarの共有アカウントは、表示アドレスに入金し、設定スキャナープロバイダーがその正確なアカウントを検証するまで利用できません。保存済み証明は失効しません。ライブのスキャナー状態は請求書作成ではなく入金検証時に別途確認します。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | ウォレット一覧に含むプロジェクト受取準備とスキャナー要件。残高、トークンガス、送金準備とは別です。他のウォレット応答ではnullの場合があります。 |
| monero_wallet_rpc | MoneroWalletRpcBinding | null | 常に | Moneroの外部閲覧専用wallet-RPC紐付け状態から秘密情報を除いたもの。endpoint、認証方式、account-0基本アドレス、技術証明フラグ/高さ、運用者確認時刻を含みます。認証情報、ウォレットキー、ファイルは出力しません。 |
| last_secret_revealed_at / secret_reveal_count | timestamp|null / integer | 常に | コンソールで秘密情報を表示した監査メタデータ。 |
| next_receive_index | integer | 常に | 次に予約する子アドレスのインデックス。 |
| last_scanned_height / last_scanned_at / last_error | integer|null / timestamp|null / string|null | 常に | ウォレットスキャナーの状態。 |
| balances | WalletAssetBalance[] | 常に | 30ネイティブチェーンすべてと検証済みERC-20/SPLのキャッシュ残高。Moneroは外部閲覧専用wallet-RPC設定が必要です。 |
| total_value_usd | decimal string | null | 常に | 現在のUSD価格がある残高の参考合計。 |
| balance_status | pending | refreshing | fresh | stale | error | unknown | 常に | 集計キャッシュの鮮度。unknownは安全側の代替値で、どの状態も請求書の決済確定を証明しません。 |
| balance_checked_at | timestamp | null | 常に | 集計に含まれる関連する成功残高確認の最古時刻。 |
| recent_payments | WalletRecentPayment[] | 常に | このウォレットに対応する、有効なdetected/confirming/finalの直近最大3件。 |
| created_at / updated_at | RFC 3339 timestamp | 常に | 作成時刻と最終ウォレット更新時刻。 |
ReceiveReadiness
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ready | boolean | 常に | 受取準備の確認に合格。送金準備、ガス、残高更新、将来の見積もり保証を意味しません。 |
| invoice_creatable | boolean | 6.0.6+ | 一時スキャナー警告があっても設定上は請求方法を作成可能です。通貨価格は作成時確認。入金検証とは異なり、ready=falseでもinvoice_creatable=trueになれます。ウォレット不足、無効方針、非対応アダプターは安全に拒否します。 |
| checked_at | timestamp | 常に | 評価時刻。一覧取得でネットワーク照会やアドレス割当は行いません。 |
| issues | PaymentMethodIssue[] | 常に | 準備済みなら空。それ以外は受取警告や設定上の障害。invoice_creatableで一時スキャナー警告と作成準備の失敗を区別します。 |
PaymentMethodIssue
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug / asset_id / asset_ticker | string / UUID / string | 判明している場合 | 対象チェーンと資産を示します。Lightningはasset_idを省く場合があります。 |
| reason_code | string | 常に | scanner_provider_quorum、scanner_not_checked、scanner_unavailable、wallet_missing、wallet_disabled、wallet_backup_required、wallet_key_unavailable、wallet_activation_required、monero_binding_unavailable、rate_unavailable、custom_rate_unavailable、lightning_unavailable、project_disabled、store_disabled、chain_disabled、asset_disabled、asset_not_accepted。 |
| message / action | string | 利用可能な場合 | 加盟店向け説明と操作ID:chain_connections、wallets、rates、payment_methods、project_settings、store_settings。認証情報や非公開プロバイダーURLは含みません。 |
| required_endpoint_role | string | null | オンチェーン | 優先スキャナーAPI役割(旧フィールド)。全互換リストはaccepted_endpoint_rolesを使います。基本稼働確認は支払履歴対応を証明しません。 |
| accepted_endpoint_roles | string[] | null | オンチェーン | 互換APIの種類で、履歴や処理能力の証明ではありません。raw node-rpcはBTC/BCH/LTC/DOGE/DASHと透明ZEC(完全復号ブロック、1〜48承認)、solidifiedネイティブTRX、algodのALGO、OctezのXTZ、SCALEメタデータの確定Asset Hub DOT、請求memo ID付きStellar RPCのXLMに対応。pruned・不完全履歴は対象外で、トークン経路は追加しません。インデックスAPIも選べます。raw/インデックス混合ソースは範囲を独立検証し、標準は同じ運営者の別名でなく独立2プロバイダーです。基本ノード高さ、ORDnet情報、非EVM経路へのEVM relayは入金証明になりません。Moneroには専用閲覧wallet-RPCが必要です。 |
| healthy_endpoints | integer | オンチェーン | 正常で一致するエンドポイント数。独立プロバイダー数ではありません。 |
| usable_independent_providers / required_independent_providers | integer | オンチェーン | 利用できる検証枠、最大2。required_independent_providersはチェーン設定で標準2、管理者の明示選択後は1。2の場合はプロバイダーキーとホストの両方が異なる必要があります。無効、10分超古い、クールダウン中は枠に入りません。Lightningは別ルールです。 |
| last_checked_at | timestamp | null | オンチェーン | 一致するエンドポイントの最新稼働確認。評価時刻とは別です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{ "asset": { "id": "ASSET_UUID", "chain_slug": "ethereum", "symbol": "USDC", "asset_kind": "token", "token_standard": "erc20", "scanner_ready": true }, "project_policy": { "enabled": true, "required_confirmations": 12 }, "selected": true, "display_order": 0, "confirmation_policy": { "finality_mode": "confirmations", "project_required_confirmations": 12, "override_required_confirmations": 3, "effective_required_confirmations": 3, "editable": true, "minimum_required_confirmations": 0, "maximum_required_confirmations": 48 }, "wallet": { "id": "WALLET_UUID", "status": "active" }, "wallet_readiness": "ready" }
],
"lightning": { "payment_rail": "lightning", "symbol": "BTC", "asset_decimals": 11, "enabled": true, "ready": true }
}PUTストアの決済方法を置き換え/v1/projects/{project_id}/stores/{store_id}/payment-assets読み取り+書き込み
ストアの順序付き全資産を原子的に置換し、最新一覧を返します。省略資産は選択解除です。
- 配列は一意の資産と表示順を最大64件受け付けます。
- 選択は希望設定として保存され、バックアップ前やチェーン停止中でも準備できます。請求書ではプロジェクト/親ネイティブ方針、ウォレット、実行チェックが準備済みの方法だけ提供します。
- 決済方法なしにするには空のassets配列を送ります。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | 必須 | application/json |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てたプロジェクト。停止中でも可。 |
| store_id | path UUID | project_idに属するストア。停止中でも可。 |
ストア決済資産の選択本文
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| assets | StoreAssetSelection[] | 必須 | 最大64件の全置換リスト。各項目は一意のasset_idと0〜10,000の一意のdisplay_orderを持ちます。 |
PaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | プロジェクト・ストアのポリシールートで使う永続的な決済資産ID。 |
| asset_key | string | 常に | 正規CAIP形式のネイティブ/コントラクト資産ID。 |
| chain_slug / network | string | 常に | Wholly Cryptoのチェーン識別子と設定ネットワーク。 |
| caip_network_id / caip_asset_id | string / string|null | 常に | 正規のネットワーク・資産ID。 |
| asset_kind | native | token | 常に | チェーン通貨か検証済みコントラクト/mintで決済するか。 |
| payment_rail | string | 常に | 実行経路:utxo、evm-native、solana-native、account-native、privacy-native、token-transfer。 |
| symbol / name / decimals | string / string / integer | 常に | 表示情報と正確な最小単位精度。 |
| contract_address | string | null | 常に | トークンは正規ERC-20コントラクトまたはSPL mint、ネイティブはnull。 |
| coingecko_id | string | null | 常に | 検索・価格用ID。カスタムコントラクトはnullで、ティッカーから市場価格を推測しません。CoinGecko情報だけで選択可能にはなりません。 |
| custom_token | boolean | 常に | オンチェーン検証済みのカスタムコントラクト。プロジェクト単位の固定USD価格または選択DEXプールを使います。 |
| icon_path | path | null | 常に | 利用可能ならローカルキャッシュのトークンアイコン。 |
| token_standard | erc20 | spl-token | null | 常に | 検証済みの実行トークン規格。ネイティブはnull。 |
| metadata_verified_at | timestamp | null | 常に | 登録トークンのオンチェーン情報検証時刻。 |
| payment_supported / scanner_ready / balance_ready | boolean | 常に | ビルド時の登録条件。scanner_readyは決済スキャナー実装が導入済みという意味です。入金確定には正常で適切な役割のプロバイダーが設定数必要(標準2、任意1)。6.0.6以降は一時的なスキャナー不通で請求書作成を止めません。balance_readyは実装済み残高アダプターだけtrueです。 |
| default_finality_mode | confirmations | finalized | 常に | 新しいプロジェクトポリシーが継承する標準確定モデル。 |
| default_required_confirmations / default_monitoring_minutes | integer | 常に | 標準の承認・監視ポリシー。 |
StorePaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| asset | PaymentAsset | 常に | プロジェクトから見えるネイティブ/検証トークン資産。 |
| project_policy | ProjectAssetPolicy | null | 常に | 親プロジェクトのポリシー。 |
| selected | boolean | 常に | ストアに保存した希望設定に含むか。プロジェクト方針、ウォレット、導入アダプター、価格が有効なら提供します。一時スキャナー不通で新請求書から除外しません。 |
| display_order | integer | null | 常に | 選択時の決済表示順。 |
| confirmation_policy | StoreConfirmationPolicy | null | 常に | 設定済み資産の有効ストア方針。プロジェクト方針なしはnull。 |
| wallet | WalletSummary | null | 常に | ネイティブとトークンで共有するチェーンウォレット。 |
| wallet_readiness | readiness enum | 常に | ウォレット/ポリシー状態のみ。スキャナー要件はreceive_readinessを使います。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | 共通受取設定とストア受入。キャッシュ評価で、予約や保証ではありません。作成時に要件と実際の換算レートを再確認します。 |
StoreConfirmationPolicy
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| finality_mode | confirmations | finalized | 常に | 設定可能なブロック数かネットワーク確定性を使うか。 |
| project_required_confirmations | integer | 常に | ストア上書きなしで今後の請求書が使う現在のプロジェクト標準。 |
| override_required_confirmations | integer | null | 常に | ストア専用数、または継承するnull。 |
| effective_required_confirmations | integer | 常に | このストア/資産の新請求書に保存する数。 |
| editable | boolean | 常に | 確定方針を変更できないfinalizedネットワークではfalse。 |
| minimum_required_confirmations | integer | 常に | チェーン別の下限(含む)。検出時受理に対応する経路のみ0を提示します。 |
| maximum_required_confirmations | integer | 常に | チェーン別の上限(含む)。 |
ReceiveReadiness
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ready | boolean | 常に | 受取準備の確認に合格。送金準備、ガス、残高更新、将来の見積もり保証を意味しません。 |
| invoice_creatable | boolean | 6.0.6+ | 一時スキャナー警告があっても設定上は請求方法を作成可能です。通貨価格は作成時確認。入金検証とは異なり、ready=falseでもinvoice_creatable=trueになれます。ウォレット不足、無効方針、非対応アダプターは安全に拒否します。 |
| checked_at | timestamp | 常に | 評価時刻。一覧取得でネットワーク照会やアドレス割当は行いません。 |
| issues | PaymentMethodIssue[] | 常に | 準備済みなら空。それ以外は受取警告や設定上の障害。invoice_creatableで一時スキャナー警告と作成準備の失敗を区別します。 |
PaymentMethodIssue
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug / asset_id / asset_ticker | string / UUID / string | 判明している場合 | 対象チェーンと資産を示します。Lightningはasset_idを省く場合があります。 |
| reason_code | string | 常に | scanner_provider_quorum、scanner_not_checked、scanner_unavailable、wallet_missing、wallet_disabled、wallet_backup_required、wallet_key_unavailable、wallet_activation_required、monero_binding_unavailable、rate_unavailable、custom_rate_unavailable、lightning_unavailable、project_disabled、store_disabled、chain_disabled、asset_disabled、asset_not_accepted。 |
| message / action | string | 利用可能な場合 | 加盟店向け説明と操作ID:chain_connections、wallets、rates、payment_methods、project_settings、store_settings。認証情報や非公開プロバイダーURLは含みません。 |
| required_endpoint_role | string | null | オンチェーン | 優先スキャナーAPI役割(旧フィールド)。全互換リストはaccepted_endpoint_rolesを使います。基本稼働確認は支払履歴対応を証明しません。 |
| accepted_endpoint_roles | string[] | null | オンチェーン | 互換APIの種類で、履歴や処理能力の証明ではありません。raw node-rpcはBTC/BCH/LTC/DOGE/DASHと透明ZEC(完全復号ブロック、1〜48承認)、solidifiedネイティブTRX、algodのALGO、OctezのXTZ、SCALEメタデータの確定Asset Hub DOT、請求memo ID付きStellar RPCのXLMに対応。pruned・不完全履歴は対象外で、トークン経路は追加しません。インデックスAPIも選べます。raw/インデックス混合ソースは範囲を独立検証し、標準は同じ運営者の別名でなく独立2プロバイダーです。基本ノード高さ、ORDnet情報、非EVM経路へのEVM relayは入金証明になりません。Moneroには専用閲覧wallet-RPCが必要です。 |
| healthy_endpoints | integer | オンチェーン | 正常で一致するエンドポイント数。独立プロバイダー数ではありません。 |
| usable_independent_providers / required_independent_providers | integer | オンチェーン | 利用できる検証枠、最大2。required_independent_providersはチェーン設定で標準2、管理者の明示選択後は1。2の場合はプロバイダーキーとホストの両方が異なる必要があります。無効、10分超古い、クールダウン中は枠に入りません。Lightningは別ルールです。 |
| last_checked_at | timestamp | null | オンチェーン | 一致するエンドポイントの最新稼働確認。評価時刻とは別です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request PUT \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "PUT",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="PUT", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{ "asset": { "id": "44444444-4444-4444-8444-444444444444", "symbol": "USDC" }, "selected": true, "display_order": 0, "confirmation_policy": { "finality_mode": "confirmations", "project_required_confirmations": 12, "override_required_confirmations": null, "effective_required_confirmations": 12, "editable": true, "minimum_required_confirmations": 0, "maximum_required_confirmations": 48 }, "wallet_readiness": "ready" }
]
}PUTストアの承認ポリシーを設定/v1/projects/{project_id}/stores/{store_id}/payment-assets/{asset_id}/confirmation-policy読み取り+書き込み
ストア専用の承認数上書き1件を設定/解除し、最新一覧を返します。資産は選択済みである必要があります。プロジェクト、ストア、チェーン、ウォレット停止中も設定できます。
- {"strategy":"inherit"}でストア上書きを解除し、今後の請求書に現在のプロジェクト標準を使います。
- finalizedネットワークはeditable falseでNetwork finalityを使い、独自ブロック数上書きは受け付けません。
- 0はネットワーク承認なしで検出時受理し、再編成保護がありません。minimum_required_confirmationsが0の場合だけ許可します。
- 変更は新請求書だけに適用。既存請求書は作成時のプロジェクト/ストア承認方針を保持します。
- 更新は1資産ずつ。同一ストア資産の同時編集は直列化し、更新応答を現在状態に使います。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | 必須 | application/json |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てたプロジェクト。停止中でも可。 |
| store_id | path UUID | project_idに属するストア。停止中でも可。 |
| asset_id | path UUID | 更新する選択済みストア決済資産。 |
ストア承認ポリシー本文
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| strategy | inherit | custom | 必須 | タグ付きstrategy。inheritは上書き解除、customはrequired_confirmations必須です。 |
| required_confirmations | integer | customのみ | 資産に返された最小・最大範囲内の整数。未知・余分なフィールドは拒否します。 |
PaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | プロジェクト・ストアのポリシールートで使う永続的な決済資産ID。 |
| asset_key | string | 常に | 正規CAIP形式のネイティブ/コントラクト資産ID。 |
| chain_slug / network | string | 常に | Wholly Cryptoのチェーン識別子と設定ネットワーク。 |
| caip_network_id / caip_asset_id | string / string|null | 常に | 正規のネットワーク・資産ID。 |
| asset_kind | native | token | 常に | チェーン通貨か検証済みコントラクト/mintで決済するか。 |
| payment_rail | string | 常に | 実行経路:utxo、evm-native、solana-native、account-native、privacy-native、token-transfer。 |
| symbol / name / decimals | string / string / integer | 常に | 表示情報と正確な最小単位精度。 |
| contract_address | string | null | 常に | トークンは正規ERC-20コントラクトまたはSPL mint、ネイティブはnull。 |
| coingecko_id | string | null | 常に | 検索・価格用ID。カスタムコントラクトはnullで、ティッカーから市場価格を推測しません。CoinGecko情報だけで選択可能にはなりません。 |
| custom_token | boolean | 常に | オンチェーン検証済みのカスタムコントラクト。プロジェクト単位の固定USD価格または選択DEXプールを使います。 |
| icon_path | path | null | 常に | 利用可能ならローカルキャッシュのトークンアイコン。 |
| token_standard | erc20 | spl-token | null | 常に | 検証済みの実行トークン規格。ネイティブはnull。 |
| metadata_verified_at | timestamp | null | 常に | 登録トークンのオンチェーン情報検証時刻。 |
| payment_supported / scanner_ready / balance_ready | boolean | 常に | ビルド時の登録条件。scanner_readyは決済スキャナー実装が導入済みという意味です。入金確定には正常で適切な役割のプロバイダーが設定数必要(標準2、任意1)。6.0.6以降は一時的なスキャナー不通で請求書作成を止めません。balance_readyは実装済み残高アダプターだけtrueです。 |
| default_finality_mode | confirmations | finalized | 常に | 新しいプロジェクトポリシーが継承する標準確定モデル。 |
| default_required_confirmations / default_monitoring_minutes | integer | 常に | 標準の承認・監視ポリシー。 |
StorePaymentAsset
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| asset | PaymentAsset | 常に | プロジェクトから見えるネイティブ/検証トークン資産。 |
| project_policy | ProjectAssetPolicy | null | 常に | 親プロジェクトのポリシー。 |
| selected | boolean | 常に | ストアに保存した希望設定に含むか。プロジェクト方針、ウォレット、導入アダプター、価格が有効なら提供します。一時スキャナー不通で新請求書から除外しません。 |
| display_order | integer | null | 常に | 選択時の決済表示順。 |
| confirmation_policy | StoreConfirmationPolicy | null | 常に | 設定済み資産の有効ストア方針。プロジェクト方針なしはnull。 |
| wallet | WalletSummary | null | 常に | ネイティブとトークンで共有するチェーンウォレット。 |
| wallet_readiness | readiness enum | 常に | ウォレット/ポリシー状態のみ。スキャナー要件はreceive_readinessを使います。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | 共通受取設定とストア受入。キャッシュ評価で、予約や保証ではありません。作成時に要件と実際の換算レートを再確認します。 |
StoreConfirmationPolicy
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| finality_mode | confirmations | finalized | 常に | 設定可能なブロック数かネットワーク確定性を使うか。 |
| project_required_confirmations | integer | 常に | ストア上書きなしで今後の請求書が使う現在のプロジェクト標準。 |
| override_required_confirmations | integer | null | 常に | ストア専用数、または継承するnull。 |
| effective_required_confirmations | integer | 常に | このストア/資産の新請求書に保存する数。 |
| editable | boolean | 常に | 確定方針を変更できないfinalizedネットワークではfalse。 |
| minimum_required_confirmations | integer | 常に | チェーン別の下限(含む)。検出時受理に対応する経路のみ0を提示します。 |
| maximum_required_confirmations | integer | 常に | チェーン別の上限(含む)。 |
ReceiveReadiness
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ready | boolean | 常に | 受取準備の確認に合格。送金準備、ガス、残高更新、将来の見積もり保証を意味しません。 |
| invoice_creatable | boolean | 6.0.6+ | 一時スキャナー警告があっても設定上は請求方法を作成可能です。通貨価格は作成時確認。入金検証とは異なり、ready=falseでもinvoice_creatable=trueになれます。ウォレット不足、無効方針、非対応アダプターは安全に拒否します。 |
| checked_at | timestamp | 常に | 評価時刻。一覧取得でネットワーク照会やアドレス割当は行いません。 |
| issues | PaymentMethodIssue[] | 常に | 準備済みなら空。それ以外は受取警告や設定上の障害。invoice_creatableで一時スキャナー警告と作成準備の失敗を区別します。 |
PaymentMethodIssue
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug / asset_id / asset_ticker | string / UUID / string | 判明している場合 | 対象チェーンと資産を示します。Lightningはasset_idを省く場合があります。 |
| reason_code | string | 常に | scanner_provider_quorum、scanner_not_checked、scanner_unavailable、wallet_missing、wallet_disabled、wallet_backup_required、wallet_key_unavailable、wallet_activation_required、monero_binding_unavailable、rate_unavailable、custom_rate_unavailable、lightning_unavailable、project_disabled、store_disabled、chain_disabled、asset_disabled、asset_not_accepted。 |
| message / action | string | 利用可能な場合 | 加盟店向け説明と操作ID:chain_connections、wallets、rates、payment_methods、project_settings、store_settings。認証情報や非公開プロバイダーURLは含みません。 |
| required_endpoint_role | string | null | オンチェーン | 優先スキャナーAPI役割(旧フィールド)。全互換リストはaccepted_endpoint_rolesを使います。基本稼働確認は支払履歴対応を証明しません。 |
| accepted_endpoint_roles | string[] | null | オンチェーン | 互換APIの種類で、履歴や処理能力の証明ではありません。raw node-rpcはBTC/BCH/LTC/DOGE/DASHと透明ZEC(完全復号ブロック、1〜48承認)、solidifiedネイティブTRX、algodのALGO、OctezのXTZ、SCALEメタデータの確定Asset Hub DOT、請求memo ID付きStellar RPCのXLMに対応。pruned・不完全履歴は対象外で、トークン経路は追加しません。インデックスAPIも選べます。raw/インデックス混合ソースは範囲を独立検証し、標準は同じ運営者の別名でなく独立2プロバイダーです。基本ノード高さ、ORDnet情報、非EVM経路へのEVM relayは入金証明になりません。Moneroには専用閲覧wallet-RPCが必要です。 |
| healthy_endpoints | integer | オンチェーン | 正常で一致するエンドポイント数。独立プロバイダー数ではありません。 |
| usable_independent_providers / required_independent_providers | integer | オンチェーン | 利用できる検証枠、最大2。required_independent_providersはチェーン設定で標準2、管理者の明示選択後は1。2の場合はプロバイダーキーとホストの両方が異なる必要があります。無効、10分超古い、クールダウン中は枠に入りません。Lightningは別ルールです。 |
| last_checked_at | timestamp | null | オンチェーン | 一致するエンドポイントの最新稼働確認。評価時刻とは別です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request PUT \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"strategy": "custom",
"required_confirmations": 0
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"strategy": "custom",
"required_confirmations": 0
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy", {
method: "PUT",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"strategy": "custom",
"required_confirmations": 0
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"strategy": "custom",
"required_confirmations": 0
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy",
method="PUT", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{
"asset": { "id": "YOUR_ASSET_ID", "chain_slug": "bitcoin", "symbol": "BTC" },
"selected": true,
"display_order": 0,
"confirmation_policy": {
"finality_mode": "confirmations",
"project_required_confirmations": 2,
"override_required_confirmations": 0,
"effective_required_confirmations": 0,
"editable": true,
"minimum_required_confirmations": 0,
"maximum_required_confirmations": 10000
},
"wallet_readiness": "ready"
}
]
}GETプロジェクトのウォレットと残高一覧/v1/projects/{project_id}/wallets読み取り専用
公開ウォレット情報と、同じ正確なチェーン/ネットワークの登録済み残高対応資産を返します。30ネイティブ経路と検証済みERC-20/SPLを追跡します。初回スキャン前や決済未許可でも資産はすぐ表示。project_enabledは支払受入、tracking_activeは独立した読み取り更新対象を示します。Moneroは専用外部閲覧wallet-RPCが必要です。コンソールの残高スキャンは上限付き読取を優先し資産別進捗/エラーを表示、完全な一巡だけが最新合計を更新します。請求確定はキャッシュ残高でなくトランザクション監視と承認方針で決まります。
- このBearerルートは復元フレーズ、秘密鍵、暗号化秘密情報、送金方法を返しません。
- 同チェーンの新規登録資産は、初回完了まで残高nullとpendingを返します。仮の0は返しません。
- プロジェクト、支払受入ウォレット、ネイティブ経路、個別資産を無効にしても読取専用追跡は止まりません。基本アドレスのあるactive/disabledウォレットは登録済み対応資産を更新し続けます。pending/errorウォレットはスキャンしません。
- project_enabledは受入方針だけです。falseでもtracking_activeはtrueになれます。
- balanceとbalance_atomicは正確な文字列。price_usd、value_usd、total_value_usdは参考値でnullの場合があります。残高が新しくても価格が新しいとは限りません。
- 評価は2時間以内のCoinGecko価格を優先します。ネイティブと検証済み正規USDC/USDTは、5分以内の有効Kraken/Binance USD価格へ優先プロバイダー順に代替できます。ドル連動の仮定やティッカーだけのカスタム価格は使わず、固定/DEX価格は別です。請求見積もりは不変です。
- pendingは完全なスナップショットなし。refreshingは前回完了額とchecked_atを保ち、送金の保留ではありません。stale/errorでも旧額を残す場合があります。取得不可を0や未入金と考えないでください。通常EVM/Solana更新は確認済み空アドレスを監査の間最大30分再利用し、残高あり・新規・変更アドレスを再確認します。明示的な残高スキャンは全件を要求します。
- recent_paymentsはウォレットあたり3記録までで、無効化履歴を除きます。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てた有効なプロジェクト。 |
WalletSummary
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id / project_id / native_asset_id | UUID | 常に | ウォレット、所有プロジェクト、チェーンネイティブ資産のID。 |
| chain_slug / network | string | 常に | ウォレットのチェーンとネットワーク。 |
| asset_symbol / asset_name | string | 常に | ネイティブ資産の表示情報。 |
| status | pending | active | disabled | error | 常に | ウォレットの運用状態。 |
| label | string | 常に | 運用者が付けたラベル。 |
| public_key / primary_address | string | null | 常に | 公開ウォレット情報。seedフレーズや秘密鍵は公開しません。 |
| derivation_scheme / address_format | string | null | 常に | アドレス方針と形式。 |
| backup_confirmed_at | timestamp | null | 常に | 運用者が復元用バックアップを確認すると非nullになります。 |
| activation_required / activation_verified_at | boolean / timestamp|null | 常に | XRPとStellarの共有アカウントは、表示アドレスに入金し、設定スキャナープロバイダーがその正確なアカウントを検証するまで利用できません。保存済み証明は失効しません。ライブのスキャナー状態は請求書作成ではなく入金検証時に別途確認します。 |
| receive_readiness | ReceiveReadiness | null | 5.5.0+ | ウォレット一覧に含むプロジェクト受取準備とスキャナー要件。残高、トークンガス、送金準備とは別です。他のウォレット応答ではnullの場合があります。 |
| monero_wallet_rpc | MoneroWalletRpcBinding | null | 常に | Moneroの外部閲覧専用wallet-RPC紐付け状態から秘密情報を除いたもの。endpoint、認証方式、account-0基本アドレス、技術証明フラグ/高さ、運用者確認時刻を含みます。認証情報、ウォレットキー、ファイルは出力しません。 |
| last_secret_revealed_at / secret_reveal_count | timestamp|null / integer | 常に | コンソールで秘密情報を表示した監査メタデータ。 |
| next_receive_index | integer | 常に | 次に予約する子アドレスのインデックス。 |
| last_scanned_height / last_scanned_at / last_error | integer|null / timestamp|null / string|null | 常に | ウォレットスキャナーの状態。 |
| balances | WalletAssetBalance[] | 常に | 30ネイティブチェーンすべてと検証済みERC-20/SPLのキャッシュ残高。Moneroは外部閲覧専用wallet-RPC設定が必要です。 |
| total_value_usd | decimal string | null | 常に | 現在のUSD価格がある残高の参考合計。 |
| balance_status | pending | refreshing | fresh | stale | error | unknown | 常に | 集計キャッシュの鮮度。unknownは安全側の代替値で、どの状態も請求書の決済確定を証明しません。 |
| balance_checked_at | timestamp | null | 常に | 集計に含まれる関連する成功残高確認の最古時刻。 |
| recent_payments | WalletRecentPayment[] | 常に | このウォレットに対応する、有効なdetected/confirming/finalの直近最大3件。 |
| created_at / updated_at | RFC 3339 timestamp | 常に | 作成時刻と最終ウォレット更新時刻。 |
WalletAssetBalance
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| wallet_id / asset_id | UUID | 常に | ウォレットと永続資産のID。 |
| project_enabled | boolean | 常に | 現在プロジェクトの資産方針で有効か。 |
| active_store_count | integer | 常に | この資産を選択する有効ストア数。受入状況であり、読取専用残高追跡とは独立です。 |
| active_store_ids | UUID[] | 常に | 現在資産を受け付ける同プロジェクトの有効ストア。追加APIなしで正確にローカル絞り込みできます。 |
| tracking_active | boolean | 常に | 読取可能ウォレットと登録済み同チェーン資産が背景更新対象か。プロジェクト/決済受入スイッチは読取追跡を止めません。 |
| asset_kind | native | token | 常に | ネイティブ通貨または検証済みコントラクト/mint資産。 |
| contract_address | string | null | 常に | トークン契約/mint。ネイティブ通貨はnull。 |
| symbol / name / decimals | string / string / integer | 常に | 表示情報と最小単位精度。 |
| coingecko_id | string | null | 常に | 対応付けがある場合の価格ID。 |
| balance / balance_atomic | decimal string|null / integer string|null | 常に | 基本アドレスと発行済み請求アドレス全体の正確な表示・最小単位残高。完全な値がなければnull。 |
| price_usd | decimal string | null | 常に | 評価に使う参考キャッシュUSD単価。 |
| value_usd | decimal string | null | 常に | 現在レートがある場合の参考法定通貨評価。 |
| status | pending | refreshing | fresh | stale | error | 常に | キャッシュのスキャン状態。refreshingは完了済み残高を保持でき、古さはchecked_atで判断。pendingは完了スナップショットなし。どれも送金保留や請求書確定の証明ではありません。 |
| checked_at | timestamp | null | 常に | 完了した残高スキャンが表す時刻。 |
| last_error | string | null | 常に | 安全な運用者向け診断。 |
WalletRecentPayment
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| invoice_public_id | UUID | 常に | 観測に対応する顧客向け請求書ID。 |
| chain_slug / symbol | string | 常に | チェーンとネイティブ/検証済みトークンの表示シンボル。 |
| transaction_id / event_index | string / integer | 常に | 正規トランザクションと送金イベントID。 |
| amount | decimal string | 常に | 浮動小数点変換なしの正確な検出資産額。 |
| status | detected | confirming | final | 常に | 現在の有効な観測状態。reorged、replaced、invalidは除外。 |
| confirmations | integer | 常に | 直近の検出承認数。 |
| observed_at | RFC 3339 timestamp | 常に | Wholly Cryptoが最初に入金を検出した時刻。 |
ReceiveReadiness
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ready | boolean | 常に | 受取準備の確認に合格。送金準備、ガス、残高更新、将来の見積もり保証を意味しません。 |
| invoice_creatable | boolean | 6.0.6+ | 一時スキャナー警告があっても設定上は請求方法を作成可能です。通貨価格は作成時確認。入金検証とは異なり、ready=falseでもinvoice_creatable=trueになれます。ウォレット不足、無効方針、非対応アダプターは安全に拒否します。 |
| checked_at | timestamp | 常に | 評価時刻。一覧取得でネットワーク照会やアドレス割当は行いません。 |
| issues | PaymentMethodIssue[] | 常に | 準備済みなら空。それ以外は受取警告や設定上の障害。invoice_creatableで一時スキャナー警告と作成準備の失敗を区別します。 |
PaymentMethodIssue
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug / asset_id / asset_ticker | string / UUID / string | 判明している場合 | 対象チェーンと資産を示します。Lightningはasset_idを省く場合があります。 |
| reason_code | string | 常に | scanner_provider_quorum、scanner_not_checked、scanner_unavailable、wallet_missing、wallet_disabled、wallet_backup_required、wallet_key_unavailable、wallet_activation_required、monero_binding_unavailable、rate_unavailable、custom_rate_unavailable、lightning_unavailable、project_disabled、store_disabled、chain_disabled、asset_disabled、asset_not_accepted。 |
| message / action | string | 利用可能な場合 | 加盟店向け説明と操作ID:chain_connections、wallets、rates、payment_methods、project_settings、store_settings。認証情報や非公開プロバイダーURLは含みません。 |
| required_endpoint_role | string | null | オンチェーン | 優先スキャナーAPI役割(旧フィールド)。全互換リストはaccepted_endpoint_rolesを使います。基本稼働確認は支払履歴対応を証明しません。 |
| accepted_endpoint_roles | string[] | null | オンチェーン | 互換APIの種類で、履歴や処理能力の証明ではありません。raw node-rpcはBTC/BCH/LTC/DOGE/DASHと透明ZEC(完全復号ブロック、1〜48承認)、solidifiedネイティブTRX、algodのALGO、OctezのXTZ、SCALEメタデータの確定Asset Hub DOT、請求memo ID付きStellar RPCのXLMに対応。pruned・不完全履歴は対象外で、トークン経路は追加しません。インデックスAPIも選べます。raw/インデックス混合ソースは範囲を独立検証し、標準は同じ運営者の別名でなく独立2プロバイダーです。基本ノード高さ、ORDnet情報、非EVM経路へのEVM relayは入金証明になりません。Moneroには専用閲覧wallet-RPCが必要です。 |
| healthy_endpoints | integer | オンチェーン | 正常で一致するエンドポイント数。独立プロバイダー数ではありません。 |
| usable_independent_providers / required_independent_providers | integer | オンチェーン | 利用できる検証枠、最大2。required_independent_providersはチェーン設定で標準2、管理者の明示選択後は1。2の場合はプロバイダーキーとホストの両方が異なる必要があります。無効、10分超古い、クールダウン中は枠に入りません。Lightningは別ルールです。 |
| last_checked_at | timestamp | null | オンチェーン | 一致するエンドポイントの最新稼働確認。評価時刻とは別です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{
"id": "55555555-5555-4555-8555-555555555555",
"project_id": "11111111-1111-4111-8111-111111111111",
"native_asset_id": "10000000-0000-4000-8000-000000000003",
"chain_slug": "ethereum",
"network": "mainnet",
"asset_symbol": "ETH",
"asset_name": "Ethereum",
"status": "active",
"label": "Primary Ethereum wallet",
"public_key": "0x…",
"primary_address": "0x…",
"derivation_scheme": "bip44",
"address_format": "eip55",
"backup_confirmed_at": "2026-08-31T17:00:00Z",
"last_secret_revealed_at": null,
"secret_reveal_count": 0,
"next_receive_index": 43,
"last_scanned_height": 23123456,
"last_scanned_at": "2026-08-31T18:05:00Z",
"last_error": null,
"balances": [
{ "wallet_id": "55555555-5555-4555-8555-555555555555", "asset_id": "10000000-0000-4000-8000-000000000003", "project_enabled": true, "tracking_active": true, "asset_kind": "native", "contract_address": null, "symbol": "ETH", "name": "Ethereum", "decimals": 18, "coingecko_id": "ethereum", "balance": "0.125", "balance_atomic": "125000000000000000", "price_usd": "4500", "value_usd": "562.50", "status": "fresh", "checked_at": "2026-08-31T18:05:00Z", "last_error": null },
{ "wallet_id": "55555555-5555-4555-8555-555555555555", "asset_id": "10000000-0000-4000-8000-000000000099", "project_enabled": false, "tracking_active": true, "asset_kind": "token", "contract_address": "0xA0b86991c6218b36c1d19d4a2e9eb0cE3606eB48", "symbol": "USDC", "name": "USDC", "decimals": 6, "coingecko_id": "usd-coin", "balance": null, "balance_atomic": null, "price_usd": "1", "value_usd": null, "status": "pending", "checked_at": null, "last_error": null }
],
"total_value_usd": "562.50",
"balance_status": "fresh",
"balance_checked_at": "2026-08-31T18:05:00Z",
"recent_payments": [
{ "invoice_public_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50", "chain_slug": "ethereum", "symbol": "USDC", "transaction_id": "0x…", "event_index": 0, "amount": "25", "status": "final", "confirmations": 12, "observed_at": "2026-08-31T18:04:00Z" }
],
"created_at": "2026-08-31T16:00:00Z",
"updated_at": "2026-08-31T18:05:00Z"
}
]
}POST請求書を作成/v1/projects/{project_id}/stores/{store_id}/invoices読み取り+書き込み
ウォレット受取先、新しい正確な見積もり、監査、通知outboxを原子的に作成します。同じ認証情報とIdempotency-Key、同じ本文バイトの再送は元の請求書を返します。
- payment_methodsはこの請求書だけのストア有効方法を絞ります。省略/nullは全方法、[]は無効です。Project → Stores → Payment methodsに小さなchain_slug表示と資産ティッカーがあります。APIのpayment-assets一覧はchain_slug、asset.symbol、asset.idを返します。Ethereumなら{chain_slug: ethereum, asset_tickers: [USDC, USDT]}。BTCやPEPEも選んだチェーンで同様です。ティッカーは大文字小文字を区別せず、チェーンとストア内だけで解決。同じティッカーの許可契約が2つあれば片方が未準備でも400となるのでasset_idsを使います。ネイティブ・カタログ・カスタムで同じルールです。チェーン/経路は1回ずつ、最終方法は最大64。Merchant 5.4.0以降は未知、無効、別チェーン、未許可を無視し、有効な一致が全くなければストア標準、あれば一致だけを使います。チェーンのみは有効な許可済みオンチェーン資産すべてを含みます。有効選択にはウォレット、導入スキャナー、信頼できる価格が必要。6.0.6以降はスキャナー不通、クールダウン、未確認/古い稼働確認で作成を止めたり方法を外したりしません。検出は自動再試行し、確定には定足数と承認が必要です。receive_readinessを監視しプロバイダーを確保してください。復旧まで未検証になる場合があります。MoneroサブアドレスとLightning BOLT11生成には外部サービスが必要です。失敗はerror.messageとerror.details.payment_methodsにchain_slug、asset_ticker、reason_codeを返し、診断にはrequired_endpoint_role、healthy_endpoints、required_independent_providersを含みます。TRONは索引履歴か対応raw solidifiedネイティブブロックAPIを使い、基本稼働だけでは互換性を証明しません。価格失敗は資産/通貨を特定します。未許可資産を有効にしたりストア方針を変えたりしません。5.4.0より前は未知/無効の明示選択で失敗します。既存請求方法は設定変更で増えず、Lightningは別指定です。再試行は元の方法を保持し、同じIdempotency-Keyで選択変更すると409です。
- checkout_appearanceは上記の全表示設定に対応。省略は継承、配列は置換、入れ子メッセージはマージ、空メッセージオブジェクトは対象範囲を消去します。解決済みデザインと画像はストアを変えず請求書に保存。公開決済JSONのappearanceで結果を確認できます。全リクエスト32 KiB、解決済み設定20 KiBまでです。
- 同じIdempotency-Keyでcheckout_appearanceを変えると409。同じ生バイトで再試行します。デザインは金額、レート、許可資産、承認、実際の状態、埋め込み権限を変えません。HTML、CSS、スクリプト、外部画像取得は禁止です。
- exchange_rate_spread_percentはこの請求書のストア標準を上書き。省略/nullで継承、"0"で無効。既存見積もりは変わりません。
- 切り上げ前にスプレッドを適用。処理手数料はスプレッドを除く元の法定請求額が基準です。
- 返されたexpected_amountまたはexpected_amount_atomicを送ってください。丸めは上方向で、資産精度、金額の0.1%、法定通貨の最小補助単位1つに制限されます。
- 再試行は同じ認証情報、Idempotency-Key、正確な本文を維持。同じキーでスプレッド変更は409 idempotency_conflictです。
- 完全一致の再試行は新見積もり、通知DNS、アドレス準備より前に確認します。権限とプロジェクト/ストア認可は毎回確認します。
- 有効なipn_urlにはストアIPN署名シークレットが必要。未知の本文フィールドは拒否します。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Idempotency-Key | 必須 | 空白なしの一意な表示可能ASCII、1〜128文字。 |
| Content-Type | 推奨 | application/json。現在の生本文ハンドラーはメディア型を強制せずJSONを解析します。 |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | Project → Settings → API IDsからProject API IDをコピー。認証情報への割当が必要で、読みやすい識別子は不可です。 |
| store_id | path UUID | Project → Stores → ストア選択 → Basic → API IDsからStore API IDをコピー。デフォルトでも必須で、有効かつproject_idに属する必要があります。 |
請求書作成本文
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| amount | string | 必須 | 符号・指数なしの小数文字列、整数48桁・小数30桁まで。標準は正数必須。Stores → Invoiceで0を許可でき、0総額は入金、アドレス割当、処理手数料なしで確定します。 |
| currency | string | null | 任意 | 対応する3文字法定通貨を大文字に正規化。省略/nullはストア通貨を継承。作成には独立して利用可能な請求換算レートも必要です。 |
| payment_methods | InvoicePaymentSelection[] | null | 任意 | この請求書のストア有効方法を選択。5.4.0以降は未知/無効/未許可を無視し、一致なしは標準。省略/nullも標準、[]は無効。方法有効化やストア変更はしません。下の選択仕様を参照。 |
| order_id | string | null | 任意 | 加盟店注文参照値。前後空白除去後1〜128文字、制御文字は拒否。 |
| string | null | 任意 | 加盟店専用顧客メール。実用的なASCII形式へ正規化し最大254文字。省略/nullなら保存しません。 | |
| description | string | null | 任意 | 顧客向け説明1〜500文字。改行・タブ可。 |
| expires_in_seconds | integer | null | 任意 | 見積もり寿命300〜86,400秒。省略/nullはストア方針を継承。 |
| exchange_rate_spread_percent | decimal string | null | 任意 | 見積もり上乗せ率0〜100、小数2桁まで。省略/nullは標準、"0"でこの請求書だけ無効。切り上げ前に適用して固定し、法定請求額や手数料基準は変えません。 |
| underpayment_tolerance_percent | decimal string | null | 任意 | 許容不足率0〜99.99、小数2桁まで。省略/nullはストア標準。 |
| ipn_url | string | null | 任意 | 公開HTTPS通知先、最大2,048バイト、認証情報やフラグメントなし。指定で上書き、省略/nullは標準を継承。 |
| redirect_url | string | null | 任意 | 確定後のHTTPS成功URL、最大2,048バイト、埋込認証情報なし。省略/nullは標準継承で、消去はできません。 |
| cancel_url | string | null | 任意 | 成功せず決済を終える場合のHTTPS戻り先。省略/nullは標準を継承し、消去できません。 |
| redirect_automatically | boolean | null | 任意 | 省略/nullはストア方針。trueには有効なredirect_urlが必要です。 |
| language | string | null | 任意 | en、de、de-DEなど英語/ドイツ語のBCP 47タグ。省略/nullはストア方針。 |
| checkout_appearance | CheckoutAppearanceOverride | null | 任意 | この請求書の部分表示設定。省略/nullは現在ストアを継承。{}を含むオブジェクトは作成時デザイン/画像を固定します。下の仕様を参照。金融設定、HTML、CSS、JavaScript、外部画像URLは不可。 |
| metadata | object | null | 任意 | 加盟店専用JSONオブジェクト。省略/nullは{}、符号化後4,096バイト・5階層まで。firstname、lastname、street、street2、zip、city、country、countryiso2、company、vatidを検証・正規化し顧客概要へ反映します。 |
InvoicePaymentSelection · ストアのチェーンと資産を選ぶ
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug | string | 必須 | Project → Stores → Payment methodsからchain_slugをコピーするか、GET /v1/projects/{project_id}/stores/{store_id}/payment-assetsで取得します。例ethereum、base、bitcoin。同じチェーン/経路は1回だけです。 |
| asset_ids | UUID[] | null | 任意 | オンチェーンasset.id UUID。コントラクトや決済方法IDではありません。これとasset_tickersはどちらか一方。両方省略でチェーンの全有効許可資産。[]、重複/nil IDは無効です。5.4.0以降はこのストア/チェーンで未許可・無効IDを無視し、全く一致なしならストア標準を使います。 |
| asset_tickers | string[] | null | 任意 | Merchant 5.3.0以降。BTC、USDC、PEPEなどをchain_slugとストアの範囲で指定。1〜64個の一意なティッカー、前後空白除去・大小文字無視、ASCII英数字/ドット/アンダースコア/ハイフン1〜40文字。これかasset_idsの一方。5.4.0以降は未知/無効/未許可を無視。曖昧な許可シンボルは失敗するのでasset_idsを使います。ウォレットと価格は有効である必要があり、6.0.6以降の一時スキャナー障害は作成を止めません。Lightningは任意指定ならBTCだけです。 |
| payment_rail | onchain | lightning | 任意 | 標準onchain。Lightningは{chain_slug: bitcoin, payment_rail: lightning}としasset_idsなし、asset_tickersは任意で[BTC]。オンチェーンBitcoin指定はLightningを含みません。ストアのLightning接続が有効・準備済みである必要があります。 |
CheckoutAppearanceOverride · 全項目任意
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| inherit_default_store | boolean | 任意 | trueはプロジェクトのデフォルトストアを基準にし、それ以外は対象ストアの有効デザインを使います。上書きを適用して独立保存し、請求書の解決済みフラグはfalseです。 |
| title | string | 任意 | 決済見出し、120文字まで。空なら標準見出し。 |
| intro / outro | string | 任意 | 各2,000文字までのプレーンテキスト。Introは上、Outroは下に全状態で表示。改行を保ち安全なURLをリンク化。空文字で消去。旧customer_messageはintroの別名として対応しますが、両方送らないでください。 |
| intro_font_size / outro_font_size | integer | 任意 | ピクセル:12、14、16、18、20、24。別途継承しなければ標準16。 |
| theme | system | light | dim | dark | 任意 | 顧客端末に合わせるか固定テーマを使います。 |
| accent_color / background_color / card_color / button_color | string | 任意 | #RRGGBB。背景・カード・ボタンは空で自動色。文字コントラストは自動です。 |
| logo_size / logo_alignment | string | 任意 | small、medium、large、およびleftかcenter。 |
| images | object | 任意 | キーはlogo_light、logo_dark、favicon。省略は基準画像保持、nullで削除。{store_id: UUID, kind?: logo_light|logo_dark|favicon}で同じプロジェクトのストアの有効アップロード画像を再利用。kind標準は対象キー。先にStore → Checkoutでアップロードし、Basic → API IDsからStore API IDをコピー。画像なしや別プロジェクトは400。外部URLや画像データは不可です。 |
| show_order_id / show_description / details_expanded | boolean | 任意 | 注文ID詳細とタイトル下のプレーンな説明を表示。details_expandedで注文ID詳細を初期展開します。表示制御でありデータ秘匿ではありません。 |
| show_project_name / show_store_name | boolean | 任意 | Merchant 5.6.0以降:顧客向けヘッダーの各名前を表示/非表示。両方標準true。Store → Checkoutでも設定でき、他の外観同様に継承・請求書保存されます。表示だけでデータ秘匿ではありません。 |
| featured_chains | string[] | 任意 | 順序付きチェーンslug、一意最大60件(小文字英字・数字・ハイフン、64文字まで)。[]で消去。利用可能な請求方法だけ並べ替えます。 |
| featured_asset_ids / default_asset_id | UUID[] / UUID|null | 任意 | 一意で順序付き資産IDを最大100件。[]で消去。標準資産はnull可。IDはpayment-assetsで、payment-intentではありません。方法を有効にせず、入金済みと有効な顧客選択が優先します。 |
| messages | object | 任意 | en/deオブジェクトにwaiting、confirming、paid、underpaid、expiredの文字列(各500文字)。指定言語/状態だけ変更。{}は全メッセージ、{en:{}}は英語、空文字はその状態を消去。英語が代替言語です。実際の状態は変更しません。 |
| support_email | string | 任意 | ASCIIメール、最大254文字。空で消去。 |
| support_url / terms_url / privacy_url | string | 任意 | 認証情報なしHTTPS URL、最大2,048文字。空で消去。新しいウィンドウで開きます。 |
| return_button_text | string | 任意 | ラベル最大60文字。請求書動作は上位redirect_url/cancel_url/redirect_automatically/languageを使います。 |
請求書サマリー
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | 内部請求書UUID。加盟店詳細や決済パスに使わないでください。 |
| invoice_id | UUID | 常に | 加盟店詳細・決済パスで使う公開請求書UUID。 |
| project_id | UUID | 常に | 所有プロジェクト。 |
| store_id | UUID | 常に | 所有ストア。 |
| source | manual | api | 常に | 請求書の作成経路。 |
| order_id | string | null | 常に | 加盟店の注文参照値。 |
| string | null | 常に | 加盟店専用の顧客メール。公開決済には返しません。 | |
| customer_name | string | null | 常に | 非公開firstname、lastname、companyメタデータから作る表示名。 |
| customer_address | string | null | 常に | 非公開company、street、street2、zip、city、country、countryiso2、vatidから作る1行住所。 |
| description | string | null | 常に | 顧客向け説明。 |
| amount | decimal string | 常に | 正規化した請求額。 |
| currency | string | 常に | 正規化した請求通貨/資産コード。 |
| exchange_rate_spread_percent | decimal string | 常に | 固定スプレッド:作成時の上書き、なければストア標準。切り上げ前に適用し、この請求書では変わりません。 |
| underpayment_tolerance_percent | decimal string | 常に | 作成時に保存した不変の不足許容率。 |
| status | invoice status | 常に | new、processing、settled、expired、invalid、cancelled。 |
| amount_status | amount status | 常に | none、partial、paid、overpaid。明示許可した金額0はnoneで確定し、決済方法はありません。 |
| timing_status | timing status | 常に | on_timeまたはlate。 |
| resolution | resolution | 常に | automatic、manually_settled、manually_invalidated。 |
| sequence | integer | 常に | 1から単調増加する請求書状態シーケンス。 |
| winning_payment_intent_id | UUID | null | 常に | 選択された場合の、請求書を確定させた決済方法。 |
| expires_at | RFC 3339 timestamp | 常に | 見積もり/支払期限。 |
| monitoring_expires_at | RFC 3339 timestamp | 常に | 各方法の設定済み遅延監視期限のうち最も遅い時刻。 |
| settled_at | timestamp | null | 常に | settledになった時刻。 |
| cancelled_at | timestamp | null | 常に | キャンセル時刻。 |
| archived_at | timestamp | null | 常に | アーカイブ時刻。 |
| created_at | RFC 3339 timestamp | 常に | 作成時刻。 |
| updated_at | RFC 3339 timestamp | 常に | 最終状態更新時刻。 |
請求書詳細の追加項目
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ipn_url | string | null | 常に | 請求書ごとの有効IPN送信先。加盟店応答のみで公開決済からは省きます。 |
| redirect_url | string | null | 常に | 確定後に使う有効な成功URL。 |
| cancel_url | string | null | 常に | 支払い成功せず終了する場合の有効な戻り先URL。 |
| redirect_automatically | boolean | 常に | 成功後に自動リダイレクトするか。 |
| checkout_language | string | 常に | 有効な決済画面の言語タグ。 |
| metadata | object | 常に | 加盟店メタデータ。公開決済には返しません。 |
| payment_intents | PaymentIntent[] | 常に | 見積もり済みの決済方法と監視状態。 |
PaymentIntent
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | 決済intent ID。QRのintent_idにも使います。 |
| payment_rail | onchain | lightning | 常に | 請求書の経路。BitcoinオンチェーンとLightningはasset_idを共有できるので、symbolだけでなくintent idとこのフィールドを使います。資産カタログのスキャナーpayment_railとは異なります。 |
| bolt11 | string | null | 常に | Lightning支払要求、それ以外null。Lightningウォレットで支払い、payment hashへオンチェーン送金しないでください。 |
| asset_id | UUID | 常に | 設定済み決済資産ID。 |
| asset_key | string | 常に | 正規CAIP形式の資産キー。 |
| chain_slug | string | 常に | Wholly CryptoチェーンID。 |
| network | string | 常に | 設定ネットワーク。対応決済資産は現在mainnet。 |
| caip_network_id | string | 常に | 正規CAIP-2ネットワークID。 |
| caip_asset_id | string | null | 常に | 登録されている場合の正規CAIP-19 ID。 |
| symbol | string | 常に | 資産シンボル。 |
| asset_decimals | integer | 常に | 最小単位精度。Lightning BTCは11(ミリサトシ)で、オンチェーンの8とは違います。見積もりは整数サトシ、受取はミリサトシ精度を保ちます。 |
| status | intent status | 常に | pending、partial、paid、overpaid、expired、invalid。 |
| finality_mode | confirmations | finalized | 常に | 確定ポリシー。 |
| required_confirmations | integer | 常に | 該当する場合の必要承認数。 |
| quote_rate | decimal string | 常に | 固定スプレッド込みの請求通貨1単位あたり資産量。例1 USDあたり1.02 USDC。逆レートではありません。 |
| quote_details | object | null | 常に | 固定見積もりの出所:スプレッド前reference_rate、unrounded_payment_amount、rounding_adjustment、pricing_provider、asset_provider、pricing_fetched_at、asset_fetched_at。古い請求書はnullで、過去値を推測しません。 |
| expected_amount | decimal string | 常に | スプレッド・切り上げ後の正確な固定支払額。4.1.1以降、認識済み検証フィアットステーブルコイン(USDC、USDT、DAI、USDS、EURCなど)は最大小数2桁に切り上げ。1.321は1.33で、1.32にはしません。許容差0でもこれが要求額です。他の資産は適応精度を維持。既存請求書は再価格設定しません。 |
| expected_amount_atomic | integer string | 常に | 資産最小単位の正確な金額。 |
| minimum_payment_amount | decimal string | 常に | 許容差後に支払済みと認める最小額。 |
| minimum_payment_amount_atomic | integer string | 常に | 資産最小単位の正確な受入基準。 |
| received_amount | decimal string | 常に | 検出金額。 |
| received_amount_atomic | integer string | 常に | 検出した最小単位金額。 |
| confirmed_amount | decimal string | 常に | 承認/確定金額。 |
| confirmed_amount_atomic | integer string | 常に | 承認/確定の最小単位金額。 |
| destination_address | string | 常に | オンチェーン受取アドレス、またはLightningの64文字ハッシュ。Lightningの支払いはbolt11を使います。ハッシュはBitcoinアドレスではありません。 |
| destination_tag | string | null | 常に | 経路が要求する公開参照値:XRP destination tag、Stellar memo ID、TONコメント。専用アドレス経路はnull。 |
| derivation_index | integer | 常に | 予約した子アドレスのインデックス。加盟店詳細のみ。 |
| quote_expires_at | RFC 3339 timestamp | 常に | 見積もり期限。 |
| monitoring_expires_at | RFC 3339 timestamp | 常に | この方法の遅延監視期限。 |
| next_check_at | timestamp | null | 常に | 次のチェーン確認予定。 |
| last_checked_at | timestamp | null | 常に | 最後のチェーン確認。 |
| last_chain_height | integer | null | 常に | 監視が観測した最新の信頼できる高さ。 |
| last_anchor_hash | string | null | 常に | 最新監視アンカー/ブロックハッシュ。 |
| last_monitor_error | string | null | 常に | 運用者向けの安全な監視診断。 |
| first_payment_at | timestamp | null | 常に | 最初の入金検出時刻。 |
| fully_paid_at | timestamp | null | 常に | 受入最低額へ最初に達した時刻。 |
| finalized_at | timestamp | null | 常に | 入金が確定ルールを満たした時刻。 |
PaymentMethodIssue
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| chain_slug / asset_id / asset_ticker | string / UUID / string | 判明している場合 | 対象チェーンと資産を示します。Lightningはasset_idを省く場合があります。 |
| reason_code | string | 常に | scanner_provider_quorum、scanner_not_checked、scanner_unavailable、wallet_missing、wallet_disabled、wallet_backup_required、wallet_key_unavailable、wallet_activation_required、monero_binding_unavailable、rate_unavailable、custom_rate_unavailable、lightning_unavailable、project_disabled、store_disabled、chain_disabled、asset_disabled、asset_not_accepted。 |
| message / action | string | 利用可能な場合 | 加盟店向け説明と操作ID:chain_connections、wallets、rates、payment_methods、project_settings、store_settings。認証情報や非公開プロバイダーURLは含みません。 |
| required_endpoint_role | string | null | オンチェーン | 優先スキャナーAPI役割(旧フィールド)。全互換リストはaccepted_endpoint_rolesを使います。基本稼働確認は支払履歴対応を証明しません。 |
| accepted_endpoint_roles | string[] | null | オンチェーン | 互換APIの種類で、履歴や処理能力の証明ではありません。raw node-rpcはBTC/BCH/LTC/DOGE/DASHと透明ZEC(完全復号ブロック、1〜48承認)、solidifiedネイティブTRX、algodのALGO、OctezのXTZ、SCALEメタデータの確定Asset Hub DOT、請求memo ID付きStellar RPCのXLMに対応。pruned・不完全履歴は対象外で、トークン経路は追加しません。インデックスAPIも選べます。raw/インデックス混合ソースは範囲を独立検証し、標準は同じ運営者の別名でなく独立2プロバイダーです。基本ノード高さ、ORDnet情報、非EVM経路へのEVM relayは入金証明になりません。Moneroには専用閲覧wallet-RPCが必要です。 |
| healthy_endpoints | integer | オンチェーン | 正常で一致するエンドポイント数。独立プロバイダー数ではありません。 |
| usable_independent_providers / required_independent_providers | integer | オンチェーン | 利用できる検証枠、最大2。required_independent_providersはチェーン設定で標準2、管理者の明示選択後は1。2の場合はプロバイダーキーとホストの両方が異なる必要があります。無効、10分超古い、クールダウン中は枠に入りません。Lightningは別ルールです。 |
| last_checked_at | timestamp | null | オンチェーン | 一致するエンドポイントの最新稼働確認。評価時刻とは別です。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new invoice.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: order-1042-attempt-1' \
--header 'Content-Type: application/json' \
--data-raw '{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new invoice.
const body = `{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new invoice.
$body = <<<'JSON'
{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: order-1042-attempt-1", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new invoice.
headers = {
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 新規請求書201、完全一致の冪等再送200
{
"data": {
"id": "2f798f9f-01f2-42f0-9d10-5581d6116b4c",
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"source": "api",
"order_id": "order-1042",
"email": "ada@example.com",
"customer_name": "Ada Lovelace · Example GmbH",
"customer_address": "Example GmbH · 12 Example Street · Suite 2 · 10115 Berlin · Germany (DE) · VAT DE123456789",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "new",
"amount_status": "none",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 1,
"winning_payment_intent_id": null,
"expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"settled_at": null,
"cancelled_at": null,
"archived_at": null,
"created_at": "2026-08-31T18:00:00Z",
"updated_at": "2026-08-31T18:00:00Z",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"checkout_language": "en",
"metadata": { "cart_id": "cart-681", "firstname": "Ada", "lastname": "Lovelace", "street": "12 Example Street", "street2": "Suite 2", "zip": "10115", "city": "Berlin", "country": "Germany", "countryiso2": "DE", "company": "Example GmbH", "vatid": "DE123456789" },
"payment_intents": [
{
"id": "33333333-3333-4333-8333-333333333333",
"asset_id": "10000000-0000-4000-8000-000000000001",
"asset_key": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"chain_slug": "bitcoin",
"network": "mainnet",
"caip_network_id": "bip122:000000000019d6689c085ae165831e93",
"caip_asset_id": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"symbol": "BTC",
"asset_decimals": 8,
"status": "pending",
"finality_mode": "confirmations",
"required_confirmations": 1,
"quote_rate": "0.000009218",
"quote_details": null,
"expected_amount": "0.00046",
"expected_amount_atomic": "46000",
"minimum_payment_amount": "0.0004554",
"minimum_payment_amount_atomic": "45540",
"received_amount": "0",
"received_amount_atomic": "0",
"confirmed_amount": "0",
"confirmed_amount_atomic": "0",
"destination_address": "bc1q…example",
"destination_tag": null,
"derivation_index": 42,
"quote_expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"next_check_at": "2026-08-31T18:00:00Z",
"last_checked_at": null,
"last_chain_height": null,
"last_anchor_hash": null,
"last_monitor_error": null,
"first_payment_at": null,
"fully_paid_at": null,
"finalized_at": null
}
]
},
"links": {
"checkout": "https://pay.example.com/invoice/0a6a98db-d93d-48ee-8c3c-fd45f90c4a50"
}
}GET請求書一覧/v1/projects/{project_id}/invoices読み取り専用
範囲内のコンパクトな請求書概要を新しい順で返します。加盟店専用emailと認識metadata由来の顧客情報を含みます。検索・状態・ストアはサーバー側で絞り、totalとhas_moreで確実にページ送りできます。
- created_at降順、次に内部id降順。
- 項目はInvoiceSummary。email、customer_name、customer_addressは加盟店専用。生metadataとpayment intentsは詳細を取得します。
- has_more=trueの場合だけ、次ページoffsetをpagination.offset + pagination.limitにします。
- 件数とページは1つのrepeatable-read DBスナップショットで読み、同時更新は次のリクエストに現れます。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てた有効なプロジェクト。 |
| store_id | query UUID | 任意の正確なストアフィルター。 |
| status | query enum | 任意でnew、processing、settled、expired、invalid、cancelled。 |
| search | query string | 任意の大文字小文字を区別しないinvoice-id/order-id/email前方一致、正確なUUID、説明・認識顧客欄の部分一致。全metadataキーと文字列・数値・真偽値(入れ子/配列含む)はインデックス付き単語前方検索に対応し、全検索語が一致する必要があります。記号は区切り。前後空白除去後100文字まで、制御文字なし。metadata検索でも一覧に生データは追加せず、詳細で読みます。 |
| limit | query integer | 任意で1〜100。標準50。 |
| offset | query integer | 任意で0〜1,000,000。標準0。 |
請求書サマリー
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | 内部請求書UUID。加盟店詳細や決済パスに使わないでください。 |
| invoice_id | UUID | 常に | 加盟店詳細・決済パスで使う公開請求書UUID。 |
| project_id | UUID | 常に | 所有プロジェクト。 |
| store_id | UUID | 常に | 所有ストア。 |
| source | manual | api | 常に | 請求書の作成経路。 |
| order_id | string | null | 常に | 加盟店の注文参照値。 |
| string | null | 常に | 加盟店専用の顧客メール。公開決済には返しません。 | |
| customer_name | string | null | 常に | 非公開firstname、lastname、companyメタデータから作る表示名。 |
| customer_address | string | null | 常に | 非公開company、street、street2、zip、city、country、countryiso2、vatidから作る1行住所。 |
| description | string | null | 常に | 顧客向け説明。 |
| amount | decimal string | 常に | 正規化した請求額。 |
| currency | string | 常に | 正規化した請求通貨/資産コード。 |
| exchange_rate_spread_percent | decimal string | 常に | 固定スプレッド:作成時の上書き、なければストア標準。切り上げ前に適用し、この請求書では変わりません。 |
| underpayment_tolerance_percent | decimal string | 常に | 作成時に保存した不変の不足許容率。 |
| status | invoice status | 常に | new、processing、settled、expired、invalid、cancelled。 |
| amount_status | amount status | 常に | none、partial、paid、overpaid。明示許可した金額0はnoneで確定し、決済方法はありません。 |
| timing_status | timing status | 常に | on_timeまたはlate。 |
| resolution | resolution | 常に | automatic、manually_settled、manually_invalidated。 |
| sequence | integer | 常に | 1から単調増加する請求書状態シーケンス。 |
| winning_payment_intent_id | UUID | null | 常に | 選択された場合の、請求書を確定させた決済方法。 |
| expires_at | RFC 3339 timestamp | 常に | 見積もり/支払期限。 |
| monitoring_expires_at | RFC 3339 timestamp | 常に | 各方法の設定済み遅延監視期限のうち最も遅い時刻。 |
| settled_at | timestamp | null | 常に | settledになった時刻。 |
| cancelled_at | timestamp | null | 常に | キャンセル時刻。 |
| archived_at | timestamp | null | 常に | アーカイブ時刻。 |
| created_at | RFC 3339 timestamp | 常に | 作成時刻。 |
| updated_at | RFC 3339 timestamp | 常に | 最終状態更新時刻。 |
請求書のページ分割
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| limit | integer | 常に | 実際のページサイズ、1〜100。 |
| offset | integer | 常に | 0基準の行offset、0〜1,000,000。 |
| total | integer | 常に | 同じページスナップショットで、プロジェクト・ストア・状態・検索に一致する総行数。 |
| has_more | boolean | 常に | offsetと返却件数の合計がtotal未満ならtrue。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": [
{
"id": "2f798f9f-01f2-42f0-9d10-5581d6116b4c",
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"source": "api",
"order_id": "order-1042",
"email": "ada@example.com",
"customer_name": "Ada Lovelace · Example GmbH",
"customer_address": "Example GmbH · 12 Example Street · Suite 2 · 10115 Berlin · Germany (DE) · VAT DE123456789",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "processing",
"amount_status": "paid",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 3,
"winning_payment_intent_id": "33333333-3333-4333-8333-333333333333",
"expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"settled_at": null,
"cancelled_at": null,
"archived_at": null,
"created_at": "2026-08-31T18:00:00Z",
"updated_at": "2026-08-31T18:04:10Z"
}
],
"pagination": {
"limit": 50,
"offset": 0,
"total": 143,
"has_more": true
}
}GET請求書を取得/v1/projects/{project_id}/invoices/{invoice_id}読み取り専用
完全な加盟店請求書詳細と現在有効な決済URLを返します。ポーリングと照合に使ってください。
- 公開IDが許可プロジェクト内になければ、範囲付き検索は意図的にinvoice_not_foundを返します。
- links.checkoutはStore → Basic → Store domainsを使い、このストアの有効payホスト、デフォルトストア、システム優先の順です。廃止/下書き/役割違いを無視。作成/MCPにも適用し、冪等再送を含め応答時に解決します。署名通知は作成時のリンクを固定し、再試行で書き換えません。これはリンク生成だけで、転送やIP制限変更はしません。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証情報に割り当てた有効なプロジェクト。 |
| invoice_id | path UUID | 作成/一覧で返るinvoice_id。内部idではありません。 |
請求書サマリー
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | 内部請求書UUID。加盟店詳細や決済パスに使わないでください。 |
| invoice_id | UUID | 常に | 加盟店詳細・決済パスで使う公開請求書UUID。 |
| project_id | UUID | 常に | 所有プロジェクト。 |
| store_id | UUID | 常に | 所有ストア。 |
| source | manual | api | 常に | 請求書の作成経路。 |
| order_id | string | null | 常に | 加盟店の注文参照値。 |
| string | null | 常に | 加盟店専用の顧客メール。公開決済には返しません。 | |
| customer_name | string | null | 常に | 非公開firstname、lastname、companyメタデータから作る表示名。 |
| customer_address | string | null | 常に | 非公開company、street、street2、zip、city、country、countryiso2、vatidから作る1行住所。 |
| description | string | null | 常に | 顧客向け説明。 |
| amount | decimal string | 常に | 正規化した請求額。 |
| currency | string | 常に | 正規化した請求通貨/資産コード。 |
| exchange_rate_spread_percent | decimal string | 常に | 固定スプレッド:作成時の上書き、なければストア標準。切り上げ前に適用し、この請求書では変わりません。 |
| underpayment_tolerance_percent | decimal string | 常に | 作成時に保存した不変の不足許容率。 |
| status | invoice status | 常に | new、processing、settled、expired、invalid、cancelled。 |
| amount_status | amount status | 常に | none、partial、paid、overpaid。明示許可した金額0はnoneで確定し、決済方法はありません。 |
| timing_status | timing status | 常に | on_timeまたはlate。 |
| resolution | resolution | 常に | automatic、manually_settled、manually_invalidated。 |
| sequence | integer | 常に | 1から単調増加する請求書状態シーケンス。 |
| winning_payment_intent_id | UUID | null | 常に | 選択された場合の、請求書を確定させた決済方法。 |
| expires_at | RFC 3339 timestamp | 常に | 見積もり/支払期限。 |
| monitoring_expires_at | RFC 3339 timestamp | 常に | 各方法の設定済み遅延監視期限のうち最も遅い時刻。 |
| settled_at | timestamp | null | 常に | settledになった時刻。 |
| cancelled_at | timestamp | null | 常に | キャンセル時刻。 |
| archived_at | timestamp | null | 常に | アーカイブ時刻。 |
| created_at | RFC 3339 timestamp | 常に | 作成時刻。 |
| updated_at | RFC 3339 timestamp | 常に | 最終状態更新時刻。 |
請求書詳細の追加項目
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| ipn_url | string | null | 常に | 請求書ごとの有効IPN送信先。加盟店応答のみで公開決済からは省きます。 |
| redirect_url | string | null | 常に | 確定後に使う有効な成功URL。 |
| cancel_url | string | null | 常に | 支払い成功せず終了する場合の有効な戻り先URL。 |
| redirect_automatically | boolean | 常に | 成功後に自動リダイレクトするか。 |
| checkout_language | string | 常に | 有効な決済画面の言語タグ。 |
| metadata | object | 常に | 加盟店メタデータ。公開決済には返しません。 |
| payment_intents | PaymentIntent[] | 常に | 見積もり済みの決済方法と監視状態。 |
PaymentIntent
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| id | UUID | 常に | 決済intent ID。QRのintent_idにも使います。 |
| payment_rail | onchain | lightning | 常に | 請求書の経路。BitcoinオンチェーンとLightningはasset_idを共有できるので、symbolだけでなくintent idとこのフィールドを使います。資産カタログのスキャナーpayment_railとは異なります。 |
| bolt11 | string | null | 常に | Lightning支払要求、それ以外null。Lightningウォレットで支払い、payment hashへオンチェーン送金しないでください。 |
| asset_id | UUID | 常に | 設定済み決済資産ID。 |
| asset_key | string | 常に | 正規CAIP形式の資産キー。 |
| chain_slug | string | 常に | Wholly CryptoチェーンID。 |
| network | string | 常に | 設定ネットワーク。対応決済資産は現在mainnet。 |
| caip_network_id | string | 常に | 正規CAIP-2ネットワークID。 |
| caip_asset_id | string | null | 常に | 登録されている場合の正規CAIP-19 ID。 |
| symbol | string | 常に | 資産シンボル。 |
| asset_decimals | integer | 常に | 最小単位精度。Lightning BTCは11(ミリサトシ)で、オンチェーンの8とは違います。見積もりは整数サトシ、受取はミリサトシ精度を保ちます。 |
| status | intent status | 常に | pending、partial、paid、overpaid、expired、invalid。 |
| finality_mode | confirmations | finalized | 常に | 確定ポリシー。 |
| required_confirmations | integer | 常に | 該当する場合の必要承認数。 |
| quote_rate | decimal string | 常に | 固定スプレッド込みの請求通貨1単位あたり資産量。例1 USDあたり1.02 USDC。逆レートではありません。 |
| quote_details | object | null | 常に | 固定見積もりの出所:スプレッド前reference_rate、unrounded_payment_amount、rounding_adjustment、pricing_provider、asset_provider、pricing_fetched_at、asset_fetched_at。古い請求書はnullで、過去値を推測しません。 |
| expected_amount | decimal string | 常に | スプレッド・切り上げ後の正確な固定支払額。4.1.1以降、認識済み検証フィアットステーブルコイン(USDC、USDT、DAI、USDS、EURCなど)は最大小数2桁に切り上げ。1.321は1.33で、1.32にはしません。許容差0でもこれが要求額です。他の資産は適応精度を維持。既存請求書は再価格設定しません。 |
| expected_amount_atomic | integer string | 常に | 資産最小単位の正確な金額。 |
| minimum_payment_amount | decimal string | 常に | 許容差後に支払済みと認める最小額。 |
| minimum_payment_amount_atomic | integer string | 常に | 資産最小単位の正確な受入基準。 |
| received_amount | decimal string | 常に | 検出金額。 |
| received_amount_atomic | integer string | 常に | 検出した最小単位金額。 |
| confirmed_amount | decimal string | 常に | 承認/確定金額。 |
| confirmed_amount_atomic | integer string | 常に | 承認/確定の最小単位金額。 |
| destination_address | string | 常に | オンチェーン受取アドレス、またはLightningの64文字ハッシュ。Lightningの支払いはbolt11を使います。ハッシュはBitcoinアドレスではありません。 |
| destination_tag | string | null | 常に | 経路が要求する公開参照値:XRP destination tag、Stellar memo ID、TONコメント。専用アドレス経路はnull。 |
| derivation_index | integer | 常に | 予約した子アドレスのインデックス。加盟店詳細のみ。 |
| quote_expires_at | RFC 3339 timestamp | 常に | 見積もり期限。 |
| monitoring_expires_at | RFC 3339 timestamp | 常に | この方法の遅延監視期限。 |
| next_check_at | timestamp | null | 常に | 次のチェーン確認予定。 |
| last_checked_at | timestamp | null | 常に | 最後のチェーン確認。 |
| last_chain_height | integer | null | 常に | 監視が観測した最新の信頼できる高さ。 |
| last_anchor_hash | string | null | 常に | 最新監視アンカー/ブロックハッシュ。 |
| last_monitor_error | string | null | 常に | 運用者向けの安全な監視診断。 |
| first_payment_at | timestamp | null | 常に | 最初の入金検出時刻。 |
| fully_paid_at | timestamp | null | 常に | 受入最低額へ最初に達した時刻。 |
| finalized_at | timestamp | null | 常に | 入金が確定ルールを満たした時刻。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": {
"id": "2f798f9f-01f2-42f0-9d10-5581d6116b4c",
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"source": "api",
"order_id": "order-1042",
"email": "ada@example.com",
"customer_name": "Ada Lovelace · Example GmbH",
"customer_address": "Example GmbH · 12 Example Street · Suite 2 · 10115 Berlin · Germany (DE) · VAT DE123456789",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "settled",
"amount_status": "paid",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 4,
"winning_payment_intent_id": "33333333-3333-4333-8333-333333333333",
"expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"settled_at": "2026-08-31T18:05:00Z",
"cancelled_at": null,
"archived_at": null,
"created_at": "2026-08-31T18:00:00Z",
"updated_at": "2026-08-31T18:05:00Z",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"checkout_language": "en",
"metadata": { "cart_id": "cart-681", "firstname": "Ada", "lastname": "Lovelace", "street": "12 Example Street", "street2": "Suite 2", "zip": "10115", "city": "Berlin", "country": "Germany", "countryiso2": "DE", "company": "Example GmbH", "vatid": "DE123456789" },
"payment_intents": [
{
"id": "33333333-3333-4333-8333-333333333333",
"asset_id": "10000000-0000-4000-8000-000000000001",
"asset_key": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"chain_slug": "bitcoin",
"network": "mainnet",
"caip_network_id": "bip122:000000000019d6689c085ae165831e93",
"caip_asset_id": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"symbol": "BTC",
"asset_decimals": 8,
"status": "paid",
"finality_mode": "confirmations",
"required_confirmations": 1,
"quote_rate": "0.000009218",
"quote_details": null,
"expected_amount": "0.00046",
"expected_amount_atomic": "46000",
"minimum_payment_amount": "0.0004554",
"minimum_payment_amount_atomic": "45540",
"received_amount": "0.0004554",
"received_amount_atomic": "45540",
"confirmed_amount": "0.0004554",
"confirmed_amount_atomic": "45540",
"destination_address": "bc1q…example",
"destination_tag": null,
"derivation_index": 42,
"quote_expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"next_check_at": null,
"last_checked_at": "2026-08-31T18:05:00Z",
"last_chain_height": 912345,
"last_anchor_hash": "000000000000000000example",
"last_monitor_error": null,
"first_payment_at": "2026-08-31T18:03:00Z",
"fully_paid_at": "2026-08-31T18:03:00Z",
"finalized_at": "2026-08-31T18:05:00Z"
}
]
},
"links": {
"checkout": "https://pay.example.com/invoice/0a6a98db-d93d-48ee-8c3c-fd45f90c4a50"
}
}GET請求書の入金一覧/v1/projects/{project_id}/invoices/{invoice_id}/payments読み取り専用
無効化記録を含む完全な現在送金履歴。通知がpayments_truncatedなら使います。現在状態であり過去イベントの復元ではありません。
- 1観測はトークンlog、UTXO出力、その他経路送金で、一意ハッシュとは限りません。payment_idで重複排除し、transaction_id + event_indexがチェーン送金を特定します。
- statusはdetected、confirming、final、reorged、replaced、invalid。counts_towards_receivedだけ受取額に算入します。異なる資産を合計しないでください。
- Lightningはpayment_hashを使いtransaction_id、confirmations、explorerリンクはnull。BTC精度は11(ミリサトシ)。preimage、BOLT11、秘密情報は出しません。
- observed_at降順、次にpayment_id降順。件数とページは同じrepeatable-readスナップショットですが、後続ページは新入金で変わりえます。ライブ請求書のページ送りではpayment_idで重複排除してください。
- 既存の読取専用プロジェクト範囲、IP制限、認証情報ごとの頻度制限が適用されます。通知リンクのoriginが設定APIホストと一致しない限り、トークン付きで開かないでください。
| ヘッダー | 必須条件 | ルール |
|---|---|---|
| Authorization | 必須 | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | 推奨 | application/json |
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | この認証情報に割り当てたプロジェクト。 |
| invoice_id | path UUID | 作成時に返された公開 invoice_id。 |
| payment_method_id | optional query UUID | 請求書の決済方法を1つに絞り込みます。 |
| limit | query integer | 1〜100。初期値は25。 |
| offset | query integer | 0〜1,000,000。初期値は0。 |
リクエスト
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"invoice_id": "11111111-2222-4333-8444-555555555555",
"data": [{
"payment_id": "44444444-4444-4444-8444-444444444444",
"payment_method_id": "33333333-3333-4333-8333-333333333333",
"transaction_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"payment_hash": null,
"event_index": 12,
"payment_rail": "onchain",
"chain_slug": "ethereum",
"network": "mainnet",
"asset_id": "55555555-5555-4555-8555-555555555555",
"asset_key": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"caip_asset_id": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"symbol": "USDC",
"asset_decimals": 6,
"amount": "58.17342",
"amount_atomic": "58173420",
"status": "final",
"counts_towards_received": true,
"confirmations": 2,
"block_height": 25975377,
"observed_at": "2026-09-14T12:03:00Z",
"chain_time": "2026-09-14T12:02:48Z",
"finalized_at": "2026-09-14T12:04:00Z",
"explorer_name": "Etherscan",
"explorer_url": "https://etherscan.io/tx/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}],
"pagination": {"limit": 25, "offset": 0, "total": 1, "has_more": false}
}GET決済ページの枠組み/公開
請求書を選択せずに決済アプリを表示する、管理対象の決済ホストのルートです。顧客向けの連携には通常 links.checkout を使ってください。
- Bearerトークンは不要です。
- 管理対象の決済エッジは GET/HEAD を許可し、それ以外のメソッドを拒否します。
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/" \
--output 'checkout.html'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout.html", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout.html", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout.html").write_bytes(response.read())レスポンス例 · 200 text/html
<!doctype html>
<!-- Hosted Wholly Crypto checkout shell -->GETホスト型決済ページ/invoice/{invoice_id}公開
顧客向けの HTML 決済ページです。同じ決済ホストから決済画面用の安全な JSON を取得します。ストアで埋め込みを有効にし、親ページの HTTPS オリジンを明示的に許可しない限り、埋め込みはできません。
- Bearer トークンは不要で、受け付けません。
- 請求書が存在しなくても HTML 自体は200を返します。その後、決済データの JSON リクエストが invoice_not_found を返します。
- レスポンスは no-store、noindex で、請求書ごとの frame-ancestors CSP を設定します。
- プロジェクトやストアが無効な場合、または請求書が不明な場合、決済データは公開されません。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invoice_id | path UUID | 加盟店 API が返した公開請求書 UUID。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID" \
--output 'checkout.html'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout.html", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout.html", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout.html").write_bytes(response.read())レスポンス例 · 200 text/html
<!doctype html>
<!-- Hosted Wholly Crypto checkout application -->GET決済ページ向けの安全な請求書データ/checkout-api/invoices/{invoice_id}公開
決済画面の描画に必要なフィールドのみを返します。内部 ID、顧客メールアドレス、派生住所フィールド、IPN URL、加盟店メタデータ、ウォレット ID、派生パス、監視診断情報は意図的に含めません。
- Bearerトークンは不要です。
- Cache-Control は no-store で、検索エンジンのインデックス登録も無効です。
- invoice_id は顧客向け情報へのアクセスを可能にするデータです。不要な公開は避けてください。
- asset_icon_url は同一オリジンのローカル画像です。顧客の決済画面が画像表示のために CoinGecko に接続する必要はありません。
- destination_tag が null でない場合はアドレスの横に表示し、コピーできるようにしてください。必須の XRP 宛先タグ、Stellar メモ ID、TON 請求書コメントのいずれかで、そのまま送信する必要があります。
- 検証済みトークンでは asset_kind が token、contract_address が正確な ERC-20 コントラクトまたは SPL ミント、token_standard が決済方式を示します。payment_uri にもそのトークン識別情報が含まれます。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invoice_id | path UUID | 公開請求書 UUID。 |
公開決済請求書
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| invoice_id | UUID | 常に | 公開請求書 UUID。 |
| order_id | string | null | 常に | 加盟店の注文参照値。 |
| description | string | null | 常に | 顧客向け説明。 |
| amount | decimal string | 常に | 請求金額。 |
| currency | string | 常に | 請求通貨。 |
| exchange_rate_spread_percent | decimal string | 常に | 作成時に固定された実効為替スプレッド。請求書ごとの上書き値も含みます。 |
| underpayment_tolerance_percent | decimal string | 常に | この請求書で許容する不足額の割合。 |
| status | invoice status | 常に | 現在の請求書ステータス。 |
| amount_status | amount status | 常に | none、partial、paid、overpaid。明示許可した金額0はnoneで確定し、決済方法はありません。 |
| timing_status | timing status | 常に | on_timeまたはlate。 |
| sequence | integer | 常に | 現在の状態シーケンス。 |
| active_payment_method_id | UUID | null | 常に | 入金を受け取った決済方法です。不足額を互換性のない別の資産で支払わないよう、決済画面はこの方法に固定されます。 |
| payment_method_locked | boolean | 常に | 有効な入金によって active_payment_method_id が選ばれた後は true。 |
| server_time | RFC 3339 timestamp | 常に | このレスポンス用に取得したサーバー時刻。expires_at と組み合わせ、顧客端末の時計のずれを避けてください。 |
| expires_at | RFC 3339 timestamp | 常に | 請求書の支払期限。 |
| expires_in_seconds | integer | 常に | server_time 時点の残り秒数。切り上げ、最小値は0です。 |
| payment_open | boolean | 常に | new または processing の請求書が期限内で、未払い額のある支払可能な方法が少なくとも1つある場合のみ true。 |
| redirect_url | string | null | 常に | 決済完了後に顧客が戻る先。 |
| cancel_url | string | null | 常に | 決済を完了せずに離れる場合に顧客が戻る先。 |
| redirect_automatically | boolean | 常に | 自動リダイレクトの設定。 |
| checkout_language | string | 常に | 決済画面の言語。 |
| project | object | 常に | name、checkout_title、checkout_description、theme、accent_color、logo_url。 |
| store | object | 常に | 公開ストア名。 |
| appearance | CheckoutAppearance | 常に | 実際に使う表示設定。請求書ごとの上書きがあれば固定した設定、それ以外はストアの現在のデザインです。金額に関するフィールドや安全上の警告は変えません。 |
| payment_methods | CheckoutPaymentMethod[] | 常に | 決済画面で安全に公開できる決済方法。 |
CheckoutAppearance
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| inherit_default_store | boolean | 常に | プロジェクトのデフォルトストアの表示設定を使う場合は true。独立した設定のストアや固定された請求書の上書き設定では false。 |
| invoice_override | boolean | 常に | 請求書作成時に checkout_appearance を指定した場合は true。省略または null の場合は false のままです。 |
| title / intro / outro | string | 常に | 加盟店の見出し、上部メッセージ、下部メッセージをプレーンテキストで指定します。intro は customer_message に代わる項目で、以前保存した文面は保持されます。マークアップとして解釈しないでください。 |
| intro_font_size / outro_font_size | integer | 常に | 文字サイズはピクセル単位で12、14、16、18、20、24。 |
| customer_message | string | 常に | intro の互換性維持用の旧エイリアスです。新しい連携では intro を使ってください。 |
| theme | system | light | dim | dark | 常に | 顧客端末の設定、または固定テーマ。 |
| accent_color / background_color / card_color / button_color | string | 常に | 色は厳密な #RRGGBB 形式。任意の色を空にすると自動設定になり、前景色のコントラストが計算されます。 |
| logo_size / logo_alignment | string | 常に | small、medium、large と left、center。画像は切り抜かず、枠内に収めます。 |
| images | object | 常に | 任意の logo_light、logo_dark、favicon URL。スコープが制限された、同一オリジンの正規化済み PNG 画像です。 |
| show_order_id / show_description / details_expanded | boolean | 常に | 注文 ID の表示、タイトル下の説明、注文 ID の初期展開状態。金額は常に表示されます。これらは表示制御であり、データを削除するものではありません。 |
| show_project_name / show_store_name | boolean | 常に | 加盟店版5.6.0以降:ヘッダーの名前表示。どちらも初期値は true。JSON 内のプロジェクトとストアの識別情報は残ります。 |
| featured_chains / featured_asset_ids | array | 常に | 優先順位付きの設定です。請求書にすでにある方法にのみ適用し、存在しない方法や無効な方法は無視します。 |
| default_asset_id | UUID | null | 常に | 最初に選ぶ方法の候補です。有効な顧客の前回選択や、すでに入金を受け取った方法が優先されます。 |
| messages | object | 常に | waiting、confirming、paid、underpaid、expired をキーにした en/de のプレーンテキスト。英語にフォールバックします。補足表示専用で、実際のステータスを置き換えません。 |
| support_email / support_url / terms_url / privacy_url | string | 常に | 任意の連絡先と HTTPS リンク。URL 内に認証情報は含められません。外部リンクは新しいウィンドウで開きます。 |
| return_button_text | string | 常に | 任意のラベルのみ。成功時・キャンセル時の URL とリダイレクト設定は、引き続き請求書側の項目です。 |
CheckoutPaymentMethod
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| payment_rail | onchain | lightning | 常に | Lightning は Bitcoin の決済方法ですが、オンチェーン BTC とは別です。asset_id だけでなく、インテント ID と決済方式で区別してください。 |
| bolt11 | string | null | 常に | 署名済み Lightning リクエスト。オンチェーン決済では null。payable が false になった後は支払わないでください。 |
| payment_hash | string | null | 常に | 照合用の Lightning 決済ハッシュで、受取アドレスではありません。オンチェーン決済では null。 |
| id | UUID | 常に | 決済インテントの識別子。 |
| asset_id | UUID | 常に | 表示設定の優先順位に使う資産 UUID。この請求書の決済インテント ID とは異なります。 |
| asset_key | string | 常に | 正規の資産キー。 |
| chain_slug / chain_name | string | 常に | チェーンの機械用名称と表示名。 |
| network | string | 常に | 決済ネットワーク。 |
| caip_network_id | string | 常に | 選択したチェーンを一意に識別する正規のネットワーク識別情報。 |
| caip_asset_id | string | null | 常に | 正確な資産を示す正規の識別情報。該当する場合は検証済みトークンコントラクトやミントも含みます。 |
| asset_name / symbol | string | 常に | 決済資産の表示用データ。 |
| asset_icon_url | string | null | 常に | 同一オリジンにローカルキャッシュした資産アイコン。検証済みの CoinGecko 対応付けがない場合は null。 |
| asset_kind | native | token | 常に | ネイティブ通貨とコントラクト/ミントによる決済を区別します。 |
| contract_address | string | null | 常に | トークンの正規 ERC-20 コントラクトまたは SPL ミント。ネイティブ通貨では null。 |
| token_standard | erc20 | spl-token | null | 常に | 検証済みのトークン実行方式。ネイティブ通貨では null。 |
| asset_decimals | integer | 常に | 最小単位の小数精度。Lightning BTC のミリサトシでは11、オンチェーン BTC のサトシでは8。 |
| status | intent status | 常に | 現在の決済方法ステータス。 |
| payable | boolean | 常に | この方法で現在支払える場合のみ true。別の資産で入金を受けた後の無効な方法では false。 |
| finality_mode / required_confirmations | string / integer | 常に | 確定ポリシー。 |
| expected_amount / expected_amount_atomic | decimal / integer string | 常に | 固定した見積額の全額を、表示単位と実際のオンチェーン単位で返します。認識済みの法定通貨連動ステーブルコインは見積額を小数点以下最大2桁とし、スプレッド適用後に必ず切り上げます。他の資産は適応的な精度を使います。トークン本来の小数精度、受取額、一部入金後の残額は正確に保持します。返された額を変更せず使ってください。 |
| minimum_payment_amount / minimum_payment_amount_atomic | decimal / integer string | 常に | 不足額の許容範囲を適用した後の決済完了基準額。 |
| received_amount / received_amount_atomic | decimal / integer string | 常に | 検出金額。 |
| remaining_amount | decimal string | 常に | 許容基準額に達するまでに必要な正確な表示額。最小値は0。 |
| remaining_amount_atomic | integer string | 常に | 許容基準額までの不足を最小単位で示します。支払いを求める金額ではありません。許容範囲は入金の受け入れ判定にのみ影響します。 |
| confirmed_amount / confirmed_amount_atomic | decimal / integer string | 常に | 承認/確定金額。 |
| destination_address / destination_tag | string / string|null | 常に | オンチェーンの宛先と任意の参照情報。Lightning ではタグなしの決済ハッシュです。支払いには bolt11/payment_uri を使ってください。 |
| quote_expires_at | RFC 3339 timestamp | 常に | 見積もり期限。 |
| payment_uri | string | null | 常に | チェーンに対応したリクエスト:ERC-681、Solana Pay、ネイティブ URI、または lightning:<bolt11>。金額付きリクエストは全見積額から受取済み額を差し引いた額を使い、許容基準額は使いません。payable が false の場合は null です。許容範囲内の不足を受け入れた後も同様です。Lightning QR は決済ハッシュではなく、Lightning リクエスト全体を含みます。 |
| qr_url | path | null | 常に | シーケンスと正確な残額に応じたリビジョン付きの、同一オリジンの SVG QR パス。payable が false なら null。SVG は no-store です。 |
| address_explorer_name / address_explorer_url | string|null | 常に | 対応している場合に使う、検証済みメインネットエクスプローラーの代替リンク。 |
| transaction_count | integer | 常に | この方法で観測した、公開可能で有効な重複のないトランザクションの総数。 |
| transactions_truncated | boolean | 常に | transaction_count が返却された直近のトランザクション一覧の件数を超える場合は true。 |
| transactions | CheckoutTransaction[] | 常に | 公開可能で有効な直近のトランザクションを最大10件。正確な受取総額は、この表示件数制限の影響を受けません。 |
CheckoutTransaction
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| transaction_id | string | 常に | 観測したトランザクション識別子。 |
| status | detected | confirming | final | 常に | 公開用の観測ステータス。 |
| confirmations | integer | 常に | 観測した承認数。 |
| block_height | integer | null | 常に | 観測したブロック/台帳の高さ。 |
| explorer_name | string | 返される場合 | 検証済みの固定エクスプローラー名。 |
| explorer_url | string | 返される場合 | 検証済みの固定メインネットエクスプローラー URL。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": {
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"order_id": "order-1042",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "processing",
"amount_status": "partial",
"timing_status": "on_time",
"sequence": 3,
"active_payment_method_id": "33333333-3333-4333-8333-333333333333",
"payment_method_locked": true,
"server_time": "2026-08-31T18:10:00Z",
"expires_at": "2026-08-31T18:15:00Z",
"expires_in_seconds": 300,
"payment_open": true,
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"checkout_language": "en",
"project": {
"name": "Example project",
"checkout_title": "Complete your payment",
"checkout_description": "Send the exact amount shown.",
"theme": "system",
"accent_color": "#42e39b",
"logo_url": "/checkout-api/invoices/…/logo/…/image.png"
},
"store": { "name": "Online shop" },
"payment_methods": [
{
"id": "33333333-3333-4333-8333-333333333333",
"asset_key": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"chain_slug": "bitcoin",
"chain_name": "Bitcoin",
"network": "mainnet",
"caip_network_id": "bip122:000000000019d6689c085ae165831e93",
"caip_asset_id": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"asset_name": "Bitcoin",
"symbol": "BTC",
"asset_icon_url": "/assets/coingecko/bitcoin.png",
"asset_kind": "native",
"contract_address": null,
"token_standard": null,
"asset_decimals": 8,
"status": "partial",
"payable": true,
"finality_mode": "confirmations",
"required_confirmations": 1,
"expected_amount": "0.00046",
"expected_amount_atomic": "46000",
"minimum_payment_amount": "0.0004554",
"minimum_payment_amount_atomic": "45540",
"received_amount": "0.0002",
"received_amount_atomic": "20000",
"remaining_amount": "0.0002554",
"remaining_amount_atomic": "25540",
"confirmed_amount": "0",
"confirmed_amount_atomic": "0",
"destination_address": "bc1q…example",
"destination_tag": null,
"quote_expires_at": "2026-08-31T18:15:00Z",
"payment_uri": "bitcoin:bc1q…example?amount=0.00026",
"qr_url": "/checkout-api/invoices/…/payment-methods/…/qr.svg?sequence=3&amount_atomic=26000",
"address_explorer_name": "mempool.space",
"address_explorer_url": "https://mempool.space/address/…",
"transaction_count": 0,
"transactions_truncated": false,
"transactions": []
}
]
}
}GETストアの決済プレビュー/invoice/preview/{project_id}公開
保存したストアの表示設定を、例の金額と実際に受け付ける資産のメタデータで表示します。決済を作成せず、待機中、承認中、支払い済み、不足、期限切れの例を切り替えられます。
- プレビューはデザイン確認専用です。支払いリクエストとして顧客に送らないでください。
- 受取アドレス、支払可能な QR、ウォレット操作、リダイレクト、決済ポーリングはありません。例を切り替えても実際の請求書ステータスは変わりません。
- レスポンスは no-store、noindex で、埋め込みはできません。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | 認証済みコンソールがプレビューリンクに含めるプロジェクト UUID。 |
| store_id | query UUID, optional | このプロジェクトに属するストア。省略すると最初のストアまたはデフォルトストアを使います。 |
| state | query string, optional | waiting、confirming、paid、underpaid、expired。ブラウザー上の表示例のみです。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming" \
--output 'checkout-preview.html'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout-preview.html", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout-preview.html", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout-preview.html").write_bytes(response.read())レスポンス例 · 200 text/html
<!doctype html>
<!-- Hosted branding preview; no invoice is created -->GET決済プレビューデータ/checkout-api/previews/{project_id}公開
適用されるストア表示設定と、安全に公開できる受付資産のメタデータを返します。payment_methods は空のままで、preview_methods に決済アドレス、見積額、ウォレットの秘密情報は含まれません。
- Bearer トークンは不要で、受け付けません。
- 請求書、宛先、ウォレット、トランザクション、IPN、Webhook、加盟店メタデータは返しません。
- 認証済みコンソールから、正しい決済ドメインのプレビューリンクを取得してください。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | コンソールのプレビューリンクにあるプロジェクト UUID。 |
| store_id | query UUID, optional | このプロジェクトに属する必要があります。ID が一致しない場合は404。不明なクエリフィールドは拒否します。 |
CheckoutAppearance
| フィールド | 型 | 必須条件 | 説明 |
|---|---|---|---|
| inherit_default_store | boolean | 常に | プロジェクトのデフォルトストアの表示設定を使う場合は true。独立した設定のストアや固定された請求書の上書き設定では false。 |
| invoice_override | boolean | 常に | 請求書作成時に checkout_appearance を指定した場合は true。省略または null の場合は false のままです。 |
| title / intro / outro | string | 常に | 加盟店の見出し、上部メッセージ、下部メッセージをプレーンテキストで指定します。intro は customer_message に代わる項目で、以前保存した文面は保持されます。マークアップとして解釈しないでください。 |
| intro_font_size / outro_font_size | integer | 常に | 文字サイズはピクセル単位で12、14、16、18、20、24。 |
| customer_message | string | 常に | intro の互換性維持用の旧エイリアスです。新しい連携では intro を使ってください。 |
| theme | system | light | dim | dark | 常に | 顧客端末の設定、または固定テーマ。 |
| accent_color / background_color / card_color / button_color | string | 常に | 色は厳密な #RRGGBB 形式。任意の色を空にすると自動設定になり、前景色のコントラストが計算されます。 |
| logo_size / logo_alignment | string | 常に | small、medium、large と left、center。画像は切り抜かず、枠内に収めます。 |
| images | object | 常に | 任意の logo_light、logo_dark、favicon URL。スコープが制限された、同一オリジンの正規化済み PNG 画像です。 |
| show_order_id / show_description / details_expanded | boolean | 常に | 注文 ID の表示、タイトル下の説明、注文 ID の初期展開状態。金額は常に表示されます。これらは表示制御であり、データを削除するものではありません。 |
| show_project_name / show_store_name | boolean | 常に | 加盟店版5.6.0以降:ヘッダーの名前表示。どちらも初期値は true。JSON 内のプロジェクトとストアの識別情報は残ります。 |
| featured_chains / featured_asset_ids | array | 常に | 優先順位付きの設定です。請求書にすでにある方法にのみ適用し、存在しない方法や無効な方法は無視します。 |
| default_asset_id | UUID | null | 常に | 最初に選ぶ方法の候補です。有効な顧客の前回選択や、すでに入金を受け取った方法が優先されます。 |
| messages | object | 常に | waiting、confirming、paid、underpaid、expired をキーにした en/de のプレーンテキスト。英語にフォールバックします。補足表示専用で、実際のステータスを置き換えません。 |
| support_email / support_url / terms_url / privacy_url | string | 常に | 任意の連絡先と HTTPS リンク。URL 内に認証情報は含められません。外部リンクは新しいウィンドウで開きます。 |
| return_button_text | string | 常に | 任意のラベルのみ。成功時・キャンセル時の URL とリダイレクト設定は、引き続き請求書側の項目です。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID", {
method: "GET",
headers: {
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
request = Request("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))応答例 · 200 application/json
{
"data": {
"preview": true,
"invoice_id": "YOUR_PROJECT_ID",
"amount": "100.00",
"currency": "USD",
"project": {
"name": "Example project",
"checkout_title": "Complete your payment",
"checkout_description": "Choose a network and send the exact amount shown.",
"theme": "system",
"accent_color": "#42e39b",
"logo_url": "/checkout-api/previews/…/logo/…/image.png"
},
"appearance": {"inherit_default_store": true, "theme": "system", "accent_color": "#42E39B", "images": {}},
"preview_methods": [],
"payment_methods": []
}
}GETストアの決済画像/checkout-api/invoices/{invoice_id}/appearance-images/{kind}/{revision}/image.png公開
この請求書に属する正規化済みストアロゴまたはファビコンを返します。決済データ内の appearance.images URL を使ってください。
- 決済 JSON の appearance.images を使ってください。請求書に固定された画像は、元のストアで画像を交換・削除しても利用できます。明示的に削除された画像、別の請求書・種類の画像、不明なリビジョンは404になります。スナップショットが現在のストア画像にフォールバックすることはありません。
- 請求書ごとの上書きがない場合は、現在適用されるストア画像を使います。交換・削除済みのリビジョンは404です。PNG のみ、nosniff とプライベートキャッシュを使用します。
- 認証済みコンソールでは、制限内の PNG、JPEG、WebP をストア画像としてアップロードできます。SVG、HTML、リモート画像 URL は受け付けません。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invoice_id | path UUID | 公開請求書 UUID。 |
| kind | path enum | logo_light、logo_dark、favicon。 |
| revision | path UUID | 現在の画像リビジョン。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png" \
--output 'store-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("store-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("store-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("store-logo.png").write_bytes(response.read())レスポンス例 · 200 image/png
(binary PNG response)GETストアのプレビュー画像/checkout-api/previews/{project_id}/stores/{store_id}/appearance-images/{kind}/{revision}/image.png公開
一致するプロジェクト、ストア、画像種別、現在のリビジョンに対してのみ、正規化済みプレビュー画像を返します。
- プレビューデータの appearance.images を使ってください。不明または不一致の ID は404です。ウォレットや決済の情報は公開されません。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | プロジェクト UUID。 |
| store_id | path UUID | プロジェクトに属するストア。 |
| kind | path enum | logo_light、logo_dark、favicon。 |
| revision | path UUID | 現在の画像リビジョン。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png" \
--output 'store-preview-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("store-preview-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("store-preview-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("store-preview-logo.png").write_bytes(response.read())レスポンス例 · 200 image/png
(binary PNG response)GETリビジョン付きプレビューロゴ/checkout-api/previews/{project_id}/logo/{revision}/image.png公開
プロジェクトとキャッシュ安全なロゴリビジョンが一致する場合にのみ、正規化済みのプロジェクトロゴを返します。URL を組み立てず、プレビューデータの project.logo_url を使ってください。
- 不明なプロジェクトや古いロゴリビジョンは、どの項目が存在しなかったかを明かさず invoice_not_found を返します。
- 正常に返されたリビジョン付き画像は不変なので、キャッシュできます。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| project_id | path UUID | プロジェクト UUID。 |
| revision | path UUID | project.logo_url に含まれる現在の決済ロゴリビジョン。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png" \
--output 'checkout-preview-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout-preview-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout-preview-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout-preview-logo.png").write_bytes(response.read())レスポンス例 · 200 image/png
(binary PNG response)GET決済QR画像/checkout-api/invoices/{invoice_id}/payment-methods/{intent_id}/qr.svg公開
請求書の決済方法に対応した正確なチェーン別決済データから、512×512の SVG QR を生成します。
- Bearerトークンは不要です。
- 決済 JSON が返す、シーケンスと残額に応じたリビジョン付き qr_url を使ってください。SVG は private、no-store です。
- 一部入金後は正確な残額をリクエストし、その資産に固定されたままになります。
- 期限切れ、完了後、または別の方法が有効な場合は409。リクエストが大きすぎてエンコードできない場合は payment_qr_unavailable(422)を返します。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invoice_id | path UUID | 公開請求書 UUID。 |
| intent_id | path UUID | 決済 JSON の決済方法 ID。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg" \
--output 'payment-qr.svg'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("payment-qr.svg", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("payment-qr.svg", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("payment-qr.svg").write_bytes(response.read())レスポンス例 · 200 image/svg+xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">…</svg>GETリビジョン付き決済ロゴ/checkout-api/invoices/{invoice_id}/logo/{revision}/image.png公開
請求書と現在のロゴリビジョンが一致する場合のみ、正規化済みプロジェクト決済ロゴを返します。ルートを組み立てるより、決済 JSON の project.logo_url を使ってください。
- Bearerトークンは不要です。
- リビジョンが内容に対応する状態なので、公開キャッシュ期間は1年で immutable を設定します。
- 不明または不一致のリビジョンは invoice_not_found を返します。
| パラメーター | 型 / 場所 | ルール |
|---|---|---|
| invoice_id | path UUID | 公開請求書 UUID。 |
| revision | path UUID | project.logo_url に含まれる現在の決済ロゴリビジョン。 |
リクエスト
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png" \
--output 'checkout-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout-logo.png").write_bytes(response.read())レスポンス例 · 200 image/png
(binary PNG response)Wholly Crypto 7.5.5 のリファレンスです。インストール済みバージョンの資料は、コンソールの「設定 → API アクセス → ドキュメント」で確認できます。 リリースを見る.