SWAPay API リファレンス
自社のサイト・システムから、支払いの作成・状態の確認・取消返金・請求書・サブスクリプション・精算の確認ができます。カード番号は、あなたのサーバーも SWAPay のサーバーも通りません(お客様は SWAPay の決済画面で、決済代行会社の入力欄に直接入力します)。
- ベース URL
- https://www.swapay-app.com/api/v1
- 認証
- Bearer sk_live_…
- 形式
- HTTPS ・ JSON(UTF-8)
- いまの版
- 2026-11-07
はじめに
- ベース URL:https://www.swapay-app.com/api/v1
- 認証:加盟店画面の API管理 で発行したシークレットキーを Authorization: Bearer sk_live_… に付けます。キーはサーバーだけで使い、ブラウザ・アプリに入れないでください。権限を絞った制限付きキー(rk_…)・IP 制限・有効期限・リクエストの署名も使えます。
- 形式:HTTPS・JSON(UTF-8)。金額は整数(円)、currency は jpy、日時は RFC 3339 の UTC です。
- ID は種類の接頭辞が付きます(pi_・ch_・re_・plink_・qr_・in_・price_・sub_・stl_・evt_・cus_・seti_・pm_)。
- すべての応答に Request-Id ヘッダーが付きます。お問い合わせのときにお知らせください。
版
URL は /v1 のまま、応答の形の版を日付で決めます。APIキーは作った日の版に固定されるので、SWAPay が新しい版を出しても、あなたのシステムの動きは変わりません。リクエストに SWAPay-Version: 2026-11-07 を付けると、その版で答えます(ない版は 400 の invalid_version)。応答の SWAPay-Version ヘッダーに、使った版が入ります。項目を足すだけの変更では版を上げません(知らない項目は読み飛ばしてください)。版ごとの違いは変更履歴にあります。
リクエストの署名
キーごとに「署名を必須にする」を選べます(加盟店画面 > API管理 > 署名)。必須にしたキーは、署名のないリクエストを受け付けません。キーが漏れても署名用の鍵(ssk_…)がなければ使えず、送った中身の書き換えも見つかります。署名は次のヘッダーに入れます。
SWAPay-Request-Signature: t=<UNIX秒>,n=<一度きりの値(16〜64文字の英数字)>,v1=<署名(16進)> 署名する文字列(改行でつなぐ): メソッド(大文字) パス(例 /v1/payment_intents) クエリ文字列(なければ空) t n 本文の SHA-256(16進。本文がなければ空文字の SHA-256) v1 = HMAC-SHA256(署名用の鍵, 署名する文字列)
t がいまから 300 秒以上ずれている・同じ n をもう一度使った・中身が違う、のどれかなら 401(signature_expired・signature_replayed・signature_invalid)です。署名する本文は、送る本文の文字列そのものです(JSON にし直さないでください)。
$body = json_encode(['amount' => 3960, 'currency' => 'jpy'], JSON_UNESCAPED_UNICODE);
$t = time();
$n = bin2hex(random_bytes(12));
$payload = implode("\n", ['POST', '/v1/payment_intents', '', $t, $n, hash('sha256', $body)]);
$sig = 't='.$t.',n='.$n.',v1='.hash_hmac('sha256', $payload, getenv('SWAPAY_SIGNING_SECRET'));
$ch = curl_init('https://api.swapay-app.com/v1/payment_intents');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Content-Type: application/json',
'Idempotency-Key: order-1029', 'SWAPay-Request-Signature: '.$sig,
]]);
$res = json_decode(curl_exec($ch), true);
import crypto from 'node:crypto';
const body = JSON.stringify({ amount: 3960, currency: 'jpy' });
const t = Math.floor(Date.now() / 1000);
const n = crypto.randomBytes(12).toString('hex');
const payload = ['POST', '/v1/payment_intents', '', t, n, crypto.createHash('sha256').update(body).digest('hex')].join('\n');
const v1 = crypto.createHmac('sha256', process.env.SWAPAY_SIGNING_SECRET).update(payload).digest('hex');
const res = await fetch('https://api.swapay-app.com/v1/payment_intents', {
method: 'POST', body,
headers: { Authorization: `Bearer ${process.env.SWAPAY_SECRET_KEY}`, 'Content-Type': 'application/json',
'Idempotency-Key': 'order-1029', 'SWAPay-Request-Signature': `t=${t},n=${n},v1=${v1}` },
});
キーの入れ替え
加盟店画面 > API管理 の「入れ替え」で、同じ設定(権限・IP 制限・署名・版)の新しいキーを作れます。古いキーは、すぐ止めるか、1・24・72 時間後に止めるかを選べます。止めずに入れ替えられるので、新しいキーに替えてから古いキーが止まります。キーがはじめての IP アドレスから使われたときは、オーナーにメールで知らせます。
カードを登録して、あとで決済する
予約のキャンセル料のように、あとで金額が決まる料金は、先にカードを登録してもらい、必要になったときにお客様がいないところで決済できます。
- POST /v1/setup_sessions で、使い道(description)と1回の上限(max_amount)を決めて登録ページを作り、url をお客様に送ります。
- お客様は、電話番号を確かめ、使い道と上限に同意して、決済代行会社の入力欄にカードを入れます。SWAPay は上限の金額の利用枠を 3D セキュアつきで一時的に確保してカードを確かめ、すぐに取り消します(請求されません)。
- 登録できると、ウェブフック setup_session.completed が届き、登録カード(pm_)が使えるようになります。
- 料金が決まったら、POST /v1/payment_intents に payment_method と amount(上限まで)と Idempotency-Key を付けて決済します。断られたときは checkout_url をお客様に送れば、別のカードで払ってもらえます。
お客様は SWAPay のマイページから、登録カードをいつでも削除できます(payment_method.detached が届きます)。登録カードは、そのお店でだけ使えます。決済代行会社の継続課金の利用が必要です。
エラー
HTTP ステータスで種類が分かり、本文で理由を返します。カードが通らなかった理由は SWAPay の決まったコード(declined など)だけを返し、細かい理由は返しません。
{
"error": {
"type": "invalid_request", // invalid_request / authentication_error / permission_error / rate_limit_error / idempotency_error / api_error
"code": "parameter_invalid",
"message": "amount は 1 以上にしてください。",
"param": "amount",
"retryable": false, // true のときは、同じ Idempotency-Key で再試行してよい
"request_id": "req_01jbx…"
}
}
400 パラメーターの誤り・401 キー・署名の誤り・403 権限・IP・404 見つからない・409 状態が合わない(取り消せない など)・429 多すぎる・500 SWAPay 側のエラー。
parameter_invalid値の形・範囲が正しくない(param に項目名)
parameter_missing必要な項目・ヘッダーがない
invalid_versionSWAPay-Version の版がない
card_data_not_allowedカード番号と思われる値が入っている(値は記録しません)
idempotency_key_too_longIdempotency-Key が255文字を超えている
resource_missing見つからない(ほかの加盟店のデータも含む)
method_not_allowedこのパスでは使えないメソッド
request_failedリクエストを受け付けられなかった
amount_too_large登録カードの上限(max_amount)を超えている
invalid_api_keyキーが正しくない・止めた・期限切れ
wrong_environment本番と検証環境のキーが違う
signature_missing署名のヘッダーがない・形が正しくない
signature_expired署名の時刻が300秒以上ずれている
signature_invalid署名が合わない
signature_replayed同じ署名(n)をもう一度使った
signature_not_configured署名用の鍵を作っていない
insufficient_scopeキーに権限がない
ip_not_allowed許可していない IP アドレス
account_inactive加盟店が API を使えない状態
plan_requiredいまのプランでは使えない
account_not_ready決済・カードの登録をまだ受け付けられない(審査・接続・継続課金)
payment_intent_unexpected_statePaymentIntent の状態が合わない(支払い後の取消 など)
setup_session_unexpected_stateSetupSession の状態が合わない(登録済み など)
payment_method_unusable登録カードが使えない(削除・接続の変更)
payment_method_expired登録カードの有効期限が過ぎている
customer_exists同じメール・電話のお客様がいる
refund_not_allowed取消返金できない(金額・設定・状態)
invoice_unexpected_state請求書の状態が合わない
price_inactive公開していないプラン
subscription_unexpected_stateサブスクリプションの状態が合わない
idempotency_key_reused同じ Idempotency-Key を違う内容で使った(登録カードでの決済では、違う金額・違う登録カード)
idempotency_key_in_use同じ Idempotency-Key のリクエストを処理中(少し待って再試行。処理中のまま5分を過ぎたものは、やり直せる)
rate_limited1分あたりの回数を超えた(Retry-After のあとに再試行)
too_many_auth_failures正しくないキー・署名が続いたため、この IP をしばらく断っている
processing_error決済の結果を確かめられなかった(同じ Idempotency-Key で送り直す)
internal_errorSWAPay 側のエラー(同じ Idempotency-Key で再試行できる)
not_installedSWAPay の準備が終わっていない
カード番号を送らない
SWAPay の API はカード番号を受け取りません(PCI DSS の非保持・非通過)。どの項目でも、カード番号と思われる値(ブランドの番号の始まり・桁数・チェックディジットがすべて合うもの)があれば、処理せずに 400(card_data_not_allowed)を返し、値は記録しません。お客様のカードは、SWAPay の決済画面(checkout_url)で入力してもらいます。
冪等キー
POST と DELETE には Idempotency-Key(255文字まで。注文番号など)を付けてください。通信が切れて再送しても、2回目以降は最初の結果をそのまま返し(Idempotent-Replayed: true)、二重に作られません。保持は 7 日。同じキーで内容が違うと 409(idempotency_key_reused)です。SWAPay 側のエラー(500)のときは記録しないので、同じキーで再試行できます。
回数の制限
1つのキーで1分あたり 600 リクエスト。応答の RateLimit-Limit・RateLimit-Remaining(残り)・RateLimit-Reset(数え直すまでの秒)で残りが分かります。超えると 429 と Retry-After を返します。正しくないキー・署名が同じ IP から続くと、その IP をしばらく断ります(too_many_auth_failures)。
一覧・ページ
一覧は新しい順です。limit(1〜100)と、次のページは前のページの最後の ID を starting_after に入れます。has_more が false なら最後です。
ウェブフックの署名の確かめ方
ウェブフックには SWAPay-Signature: t=<UNIX秒>,v1=<署名> が付きます。v1 = HMAC-SHA256(署名シークレット, "t.本文")。署名シークレットを作り直したあとの24時間は、新旧2つの v1= が付きます(どちらかが合えば正しい)。t が 300 秒より古いものは捨ててください(同じ通知の使い回しを防ぐため)。同じ通知が2回届くことがあり(イベントの id で見分ける)、届く順番は保証しません(created で判断する)。10 秒以内に 2xx を返してください。返らないときは最大16回・約2日、間隔をあけて送り直します。
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_SWAPAY_SIGNATURE'] ?? '';
preg_match('/t=(\d+)/', $header, $t);
preg_match_all('/v1=([0-9a-f]{64})/', $header, $v1);
$expected = hash_hmac('sha256', ($t[1] ?? '').'.'.$body, getenv('SWAPAY_WEBHOOK_SECRET'));
$ok = isset($t[1]) && abs(time() - (int) $t[1]) <= 300 && in_array(true, array_map(fn ($s) => hash_equals($expected, $s), $v1[1]), true);
if (! $ok) { http_response_code(400); exit; }
検証環境
検証環境(staging)のキーは sk_test_…、本番は sk_live_… です。環境ごとにデータベースが分かれ、キーも別です。検証環境の決済はテストモードで、実際のお金は動きません(テスト用のカード番号は SWAPay にお問い合わせください)。
変更履歴
- 2026-11-07 最初の公開版。リクエストの署名(SWAPay-Request-Signature)、キーとウェブフックの鍵の入れ替え、冪等キー 7 日・DELETE も対象、回数の残りのヘッダー、カードが通らない理由のコードを declined などに統一
PaymentIntent オブジェクト
API で作る1回の支払いです。支払いは SWAPay の決済画面で行い、カード番号はあなたのサーバーも SWAPay も通りません(決済代行会社の入力欄が直接受け取ります)。
idstringpi_ で始まる ID
statusenumrequires_payment_method(支払い待ち)/ requires_action(3D セキュアの認証中)/ processing(スマホ決済などの結果待ち)/ succeeded / canceled
checkout_urlstringお客様を案内する決済画面の URL(支払い待ちのときだけ)
latest_chargestring最新の決済(Charge)の ID
metadataobject作るときに付けたキーと値
{
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3960,
"amount_received": 0,
"amount_refunded": 0,
"currency": "jpy",
"status": "requires_payment_method",
"description": "ご注文 1029",
"metadata": {
"order_id": "1029"
},
"checkout_url": "https://www.swapay-app.com/pay/01jbx3q4w2k8m5n6p7r8s9t0va",
"next_action": {
"type": "redirect_to_url",
"redirect_to_url": {
"url": "https://www.swapay-app.com/pay/01jbx3q4w2k8m5n6p7r8s9t0va"
}
},
"return_url": "https://shop.example.co.jp/thanks",
"latest_charge": null,
"customer": null,
"payment_method": null,
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}PaymentIntent を作成
/v1/payment_intentspayment_intents:write支払いを作り、checkout_url を返します。お客様をその URL へ案内してください。支払いが終わると return_url に戻り、ウェブフック payment_intent.succeeded が届きます。1回だけ支払えます。
amountinteger必須金額(円・1〜9,999,999)
currencystring必須jpy
descriptionstring決済画面に表示する内容(500文字まで)
metadataobject任意のキーと値(50件・キー40文字・値500文字まで)。カード情報や個人情報は入れないでください
return_urlstring支払いのあと「お店に戻る」の戻り先(https)
expires_ininteger支払える時間(秒・300〜2,592,000。既定 86,400)
payment_methodstring登録カード(pm_)。付けると、お客様がいないところで、その場で決済します(下の「登録カードで決済」)
curl -X POST https://www.swapay-app.com/api/v1/payment_intents \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: d017dd76-3bea-47f7-99af-2e9159aefea8" \ -d 'amount=3960' \ -d 'currency=jpy' \ -d 'description= 1029' \ -d 'metadata[order_id]=1029' \ -d 'return_url=https://shop.example.co.jp/thanks'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/payment_intents', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'amount' => 3960,
'currency' => 'jpy',
'description' => 'ご注文 1029',
'metadata[order_id]' => '1029',
'return_url' => 'https://shop.example.co.jp/thanks',
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_intents', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"amount": 3960,
"currency": "jpy",
"description": "ご注文 1029",
"metadata[order_id]": "1029",
"return_url": "https://shop.example.co.jp/thanks"
}),
});
const data = await res.json();{
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3960,
"amount_received": 0,
"amount_refunded": 0,
"currency": "jpy",
"status": "requires_payment_method",
"description": "ご注文 1029",
"metadata": {
"order_id": "1029"
},
"checkout_url": "https://www.swapay-app.com/pay/01jbx3q4w2k8m5n6p7r8s9t0va",
"next_action": {
"type": "redirect_to_url",
"redirect_to_url": {
"url": "https://www.swapay-app.com/pay/01jbx3q4w2k8m5n6p7r8s9t0va"
}
},
"return_url": "https://shop.example.co.jp/thanks",
"latest_charge": null,
"customer": null,
"payment_method": null,
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}PaymentIntent を取得
/v1/payment_intents/{id}payment_intents:read今の状態を返します。
curl https://www.swapay-app.com/api/v1/payment_intents/pi_01jbx3q4w2k8m5n6p7r8s9t0va \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/payment_intents/pi_01jbx3q4w2k8m5n6p7r8s9t0va', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_intents/pi_01jbx3q4w2k8m5n6p7r8s9t0va', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3960,
"amount_received": 3960,
"amount_refunded": 0,
"currency": "jpy",
"status": "succeeded",
"description": "ご注文 1029",
"metadata": {
"order_id": "1029"
},
"checkout_url": null,
"next_action": null,
"return_url": "https://shop.example.co.jp/thanks",
"latest_charge": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"customer": null,
"payment_method": null,
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}PaymentIntent の一覧
/v1/payment_intentspayment_intents:read新しい順に返します。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
curl https://www.swapay-app.com/api/v1/payment_intents \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/payment_intents', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_intents', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/payment_intents",
"has_more": false,
"data": [
{
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3960,
"amount_received": 0,
"amount_refunded": 0,
"currency": "jpy",
"status": "requires_payment_method",
"description": "ご注文 1029",
"metadata": {
"order_id": "1029"
},
"checkout_url": "https://www.swapay-app.com/pay/01jbx3q4w2k8m5n6p7r8s9t0va",
"next_action": {
"type": "redirect_to_url",
"redirect_to_url": {
"url": "https://www.swapay-app.com/pay/01jbx3q4w2k8m5n6p7r8s9t0va"
}
},
"return_url": "https://shop.example.co.jp/thanks",
"latest_charge": null,
"customer": null,
"payment_method": null,
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
]
}PaymentIntent を取消
/v1/payment_intents/{id}/cancelpayment_intents:write支払い前の PaymentIntent を取り消します(決済画面で支払えなくなります)。支払い済みのものは取消返金を使ってください。
curl -X POST https://www.swapay-app.com/api/v1/payment_intents/pi_01jbx3q4w2k8m5n6p7r8s9t0va/cancel \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 1da389d2-fd82-4409-b14d-149290c2d624"
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/payment_intents/pi_01jbx3q4w2k8m5n6p7r8s9t0va/cancel', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_intents/pi_01jbx3q4w2k8m5n6p7r8s9t0va/cancel', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
});
const data = await res.json();{
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3960,
"amount_received": 0,
"amount_refunded": 0,
"currency": "jpy",
"status": "canceled",
"description": "ご注文 1029",
"metadata": {
"order_id": "1029"
},
"checkout_url": null,
"next_action": null,
"return_url": "https://shop.example.co.jp/thanks",
"latest_charge": null,
"customer": null,
"payment_method": null,
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}Charge オブジェクト
決済1件です。QRコード・リンク決済・請求書・サブスクリプション・API のすべての受付経路の決済が入ります。カード番号は持たず、ブランドと末尾4桁だけを返します。
statusenumpending / succeeded / refunded(全額を取消返金)/ failed / canceled
channelenumqr / link / invoice / subscription / api
referencestringお客様に見せるお問い合わせID(SP-…)
{
"id": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"object": "charge",
"amount": 3960,
"amount_refunded": 0,
"currency": "jpy",
"status": "succeeded",
"reference": "SP-C3D4E5F6G7",
"payment_method_type": "card",
"channel": "api",
"card": {
"brand": "visa",
"last4": "4242",
"issuer_country": "JP"
},
"payment_intent": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"paid_at": "2026-10-28T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}Charge の一覧
/v1/chargescharges:read新しい順に返します。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
channelstring受付経路で絞り込み
payment_intentstringPaymentIntent で絞り込み
curl https://www.swapay-app.com/api/v1/charges \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/charges', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/charges', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/charges",
"has_more": false,
"data": [
{
"id": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"object": "charge",
"amount": 3960,
"amount_refunded": 0,
"currency": "jpy",
"status": "succeeded",
"reference": "SP-C3D4E5F6G7",
"payment_method_type": "card",
"channel": "api",
"card": {
"brand": "visa",
"last4": "4242",
"issuer_country": "JP"
},
"payment_intent": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"paid_at": "2026-10-28T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
]
}Charge を取得
/v1/charges/{id}charges:readcurl https://www.swapay-app.com/api/v1/charges/ch_01jbx3t9a1b2c3d4e5f6g7h8j9 \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/charges/ch_01jbx3t9a1b2c3d4e5f6g7h8j9', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/charges/ch_01jbx3t9a1b2c3d4e5f6g7h8j9', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"object": "charge",
"amount": 3960,
"amount_refunded": 0,
"currency": "jpy",
"status": "succeeded",
"reference": "SP-C3D4E5F6G7",
"payment_method_type": "card",
"channel": "api",
"card": {
"brand": "visa",
"last4": "4242",
"issuer_country": "JP"
},
"payment_intent": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"paid_at": "2026-10-28T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}登録カードで決済
/v1/payment_intentspayment_intents:writepayment_method(pm_)を付けて PaymentIntent を作ると、お客様がいないところで、そのカードでその場で決済します(キャンセル料・追加料金など)。金額はお客様が同意した上限(max_amount)までです。payment_methods:write の権限と Idempotency-Key が必要です。カード会社に断られたときは status が requires_payment_method・last_payment_error が card_declined になり、checkout_url をお客様に送れば別のカードで払ってもらえます(7日間)。結果が分からない(500・retryable=true)ときは、同じ Idempotency-Key で送り直してください。二重に決済されることはありません。
payment_methodstring必須登録カード(pm_)
amountinteger必須金額(円・max_amount まで)
currencystring必須jpy
descriptionstring明細に出す内容(省略すると登録したときの使い道)
metadataobject任意のキーと値
curl -X POST https://www.swapay-app.com/api/v1/payment_intents \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 77df702c-ba91-436e-8390-64f07777ac0a" \ -d 'payment_method=pm_01jbxc1p2m3e4t5h6o7d8a9b0c' \ -d 'amount=3300' \ -d 'currency=jpy' \ -d 'description=11/30 50%'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/payment_intents', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'payment_method' => 'pm_01jbxc1p2m3e4t5h6o7d8a9b0c',
'amount' => 3300,
'currency' => 'jpy',
'description' => '11/30 カット 前日キャンセル(50%)',
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_intents', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"payment_method": "pm_01jbxc1p2m3e4t5h6o7d8a9b0c",
"amount": 3300,
"currency": "jpy",
"description": "11/30 カット 前日キャンセル(50%)"
}),
});
const data = await res.json();{
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3300,
"amount_received": 3300,
"amount_refunded": 0,
"currency": "jpy",
"status": "succeeded",
"description": "11/30 カット 前日キャンセル(50%)",
"metadata": [],
"checkout_url": null,
"next_action": null,
"return_url": null,
"latest_charge": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"payment_method": "pm_01jbxc1p2m3e4t5h6o7d8a9b0c",
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}取消返金を作成
/v1/refundsrefunds:write決済済みの支払いを取消返金します。合計は決済額を超えられません。決済代行会社での処理が終わるまで status は pending、終わると refund.succeeded が届きます。加盟店画面の設定で「○円以上はオーナーの承認」にしている場合は requires_approval になり、オーナーの承認後に処理します。
chargestring取消返金する決済(charge か payment_intent のどちらか)
payment_intentstring取消返金する PaymentIntent
amountinteger金額(省略時は取消返金できる残りすべて)
reasonenumrequested_by_customer(既定)/ duplicate / fraudulent
curl -X POST https://www.swapay-app.com/api/v1/refunds \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: faf8e67b-11d1-4cfa-8f5a-f7b2ff1dfb46" \ -d 'payment_intent=pi_01jbx3q4w2k8m5n6p7r8s9t0va' \ -d 'amount=1000'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/refunds', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'payment_intent' => 'pi_01jbx3q4w2k8m5n6p7r8s9t0va',
'amount' => 1000,
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/refunds', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"payment_intent": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"amount": 1000
}),
});
const data = await res.json();{
"id": "re_01jbx4a2b3c4d5e6f7g8h9j0k1",
"object": "refund",
"amount": 1000,
"currency": "jpy",
"status": "pending",
"reason": "customer_request",
"charge": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"payment_intent": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"failure_reason": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}取消返金を取得
/v1/refunds/{id}refunds:readstatus:pending / requires_approval / succeeded / failed / canceled(承認されなかった)
curl https://www.swapay-app.com/api/v1/refunds/re_01jbx4a2b3c4d5e6f7g8h9j0k1 \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/refunds/re_01jbx4a2b3c4d5e6f7g8h9j0k1', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/refunds/re_01jbx4a2b3c4d5e6f7g8h9j0k1', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "re_01jbx4a2b3c4d5e6f7g8h9j0k1",
"object": "refund",
"amount": 1000,
"currency": "jpy",
"status": "succeeded",
"reason": "customer_request",
"charge": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"payment_intent": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"failure_reason": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}取消返金の一覧
/v1/refundsrefunds:readlimitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
chargestring決済で絞り込み
curl https://www.swapay-app.com/api/v1/refunds \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/refunds', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/refunds', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/refunds",
"has_more": false,
"data": [
{
"id": "re_01jbx4a2b3c4d5e6f7g8h9j0k1",
"object": "refund",
"amount": 1000,
"currency": "jpy",
"status": "pending",
"reason": "customer_request",
"charge": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"payment_intent": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"failure_reason": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
]
}リンク決済を作成
/v1/payment_linkspayment_links:writeメールや SNS で送る決済ページを作ります。何人でも支払えます(max_uses で上限)。
titlestring必須決済ページに表示する件名
amountinteger必須金額(円)
descriptionstring説明
expires_atstring有効期限(RFC 3339)
max_usesinteger支払える回数の上限
curl -X POST https://www.swapay-app.com/api/v1/payment_links \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 666472ad-371d-4319-a6a5-412dbf2c8134" \ -d 'title=11 ' \ -d 'amount=5500' \ -d 'max_uses=100'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/payment_links', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'title' => '11月 セミナー参加費',
'amount' => 5500,
'max_uses' => 100,
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_links', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"title": "11月 セミナー参加費",
"amount": 5500,
"max_uses": 100
}),
});
const data = await res.json();{
"id": "plink_01jbx4m1n2p3q4r5s6t7v8w9x0",
"object": "payment_link",
"title": "11月 セミナー参加費",
"description": null,
"amount": 5500,
"customer_enters_amount": false,
"min_amount": null,
"max_amount": null,
"currency": "jpy",
"active": true,
"url": "https://www.swapay-app.com/pay/01jbx4m1n2p3q4r5s6t7v8w9x0",
"max_uses": 100,
"times_paid": 0,
"expires_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}リンク決済を取得・一覧
/v1/payment_links/{id}payment_links:read一覧は GET /payment_links(limit・starting_after)。
curl https://www.swapay-app.com/api/v1/payment_links/plink_01jbx4m1n2p3q4r5s6t7v8w9x0 \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/payment_links/plink_01jbx4m1n2p3q4r5s6t7v8w9x0', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_links/plink_01jbx4m1n2p3q4r5s6t7v8w9x0', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "plink_01jbx4m1n2p3q4r5s6t7v8w9x0",
"object": "payment_link",
"title": "11月 セミナー参加費",
"description": null,
"amount": 5500,
"customer_enters_amount": false,
"min_amount": null,
"max_amount": null,
"currency": "jpy",
"active": true,
"url": "https://www.swapay-app.com/pay/01jbx4m1n2p3q4r5s6t7v8w9x0",
"max_uses": 100,
"times_paid": 0,
"expires_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}リンク決済を更新
/v1/payment_links/{id}payment_links:write指定した項目だけ変えます。受付を止めるときは POST /payment_links/{id}/deactivate。
titlestringdescriptionstringexpires_atstringmax_usesintegeractivebooleantrue で受付を再開
curl -X POST https://www.swapay-app.com/api/v1/payment_links/plink_01jbx4m1n2p3q4r5s6t7v8w9x0 \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: c1141878-964d-4cb8-80df-f88a6d729e70" \ -d 'max_uses=150'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/payment_links/plink_01jbx4m1n2p3q4r5s6t7v8w9x0', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'max_uses' => 150,
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_links/plink_01jbx4m1n2p3q4r5s6t7v8w9x0', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"max_uses": 150
}),
});
const data = await res.json();{
"id": "plink_01jbx4m1n2p3q4r5s6t7v8w9x0",
"object": "payment_link",
"title": "11月 セミナー参加費",
"description": null,
"amount": 5500,
"customer_enters_amount": false,
"min_amount": null,
"max_amount": null,
"currency": "jpy",
"active": true,
"url": "https://www.swapay-app.com/pay/01jbx4m1n2p3q4r5s6t7v8w9x0",
"max_uses": 150,
"times_paid": 0,
"expires_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}QRコードを作成
/v1/qr_codespayment_links:write店頭に置く QR コードです。customer_enters_amount=true で、支払う人が金額を入れます。画像は image_url(SVG)。取得・一覧・更新・停止は /payment_links と同じ形です。
titlestring必須名前(例:レジ横)
amountinteger金額(固定のとき)
customer_enters_amountboolean支払う人が金額を入れる
min_amountinteger入れられる最小額(既定 100)
max_amountinteger入れられる最大額(既定 50,000)
curl -X POST https://www.swapay-app.com/api/v1/qr_codes \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: bd3bcf21-c324-4899-b31f-1227b393522d" \ -d 'title=' \ -d 'customer_enters_amount=true' \ -d 'max_amount=50000'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/qr_codes', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'title' => 'レジ横',
'customer_enters_amount' => true,
'max_amount' => 50000,
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/qr_codes', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"title": "レジ横",
"customer_enters_amount": true,
"max_amount": 50000
}),
});
const data = await res.json();{
"id": "qr_01jbx4q8r7s6t5v4w3x2y1z0a9",
"object": "qr_code",
"title": "レジ横",
"description": null,
"amount": null,
"customer_enters_amount": true,
"min_amount": 100,
"max_amount": 50000,
"currency": "jpy",
"active": true,
"url": "https://www.swapay-app.com/pay/01jbx4q8r7s6t5v4w3x2y1z0a9",
"max_uses": null,
"times_paid": 0,
"expires_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false,
"image_url": "https://www.swapay-app.com/api/v1/qr_codes/qr_01jbx4q8r7s6t5v4w3x2y1z0a9/image.svg"
}請求書を作成
/v1/invoicesinvoices:write適格請求書の形(税率ごとに消費税を1回だけ端数処理)で作ります。send=true ですぐ請求先へメールします。
customer[name]string必須宛名
customer[email]string必須送り先
customer[company]string会社名
titlestring必須件名
lines[][name]string必須品目
lines[][unit_amount]integer必須単価(税抜・円)
lines[][quantity]integer必須数量
lines[][tax_rate]enum必須10 / 8 / 0
due_datestring必須支払期限(YYYY-MM-DD)
issue_datestring発行日(既定は今日)
registration_numberstring適格請求書発行事業者の登録番号(T+13桁)
memostring請求書に載せる備考
sendbooleantrue ですぐ送る
curl -X POST https://www.swapay-app.com/api/v1/invoices \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 9ed4b195-9c0f-4a50-837b-a850f9ef7c15" \ -d 'customer[name]= ' \ -d 'customer[email]=billing@example.co.jp' \ -d 'title=10 ' \ -d 'lines[0][name]=' \ -d 'lines[0][unit_amount]=10000' \ -d 'lines[0][quantity]=1' \ -d 'lines[0][tax_rate]=10' \ -d 'due_date=2026-11-30' \ -d 'send=true'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/invoices', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'customer' =>
[
'name' => '山田 太郎',
'email' => 'billing@example.co.jp',
),
'title' => '10月分 ご利用料金',
'lines' =>
[
0 =>
[
'name' => '月額利用料',
'unit_amount' => 10000,
'quantity' => 1,
'tax_rate' => 10,
),
),
'due_date' => '2026-11-30',
'send' => true,
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/invoices', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"customer": {
"name": "山田 太郎",
"email": "billing@example.co.jp"
},
"title": "10月分 ご利用料金",
"lines": [
{
"name": "月額利用料",
"unit_amount": 10000,
"quantity": 1,
"tax_rate": 10
}
],
"due_date": "2026-11-30",
"send": true
}),
});
const data = await res.json();{
"id": "in_01jbx5a1s2d3f4g5h6j7k8l9m0",
"object": "invoice",
"number": "INV-2026-00012",
"title": "10月分 ご利用料金",
"status": "open",
"overdue": false,
"customer": {
"name": "山田 太郎",
"company": "株式会社サンプル",
"email": "billing@example.co.jp"
},
"lines": [
{
"name": "月額利用料",
"unit_amount": 10000,
"quantity": 1,
"tax_rate": 10
}
],
"subtotal": 10000,
"tax": {
"10": 1000,
"8": 0
},
"total": 11000,
"currency": "jpy",
"issue_date": "2026-10-28",
"due_date": "2026-11-30",
"hosted_url": "https://www.swapay-app.com/pay/01jbx5…/invoice",
"payment_url": "https://www.swapay-app.com/pay/01jbx5…",
"sent_at": "2026-10-28T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}請求書を送信・無効にする
/v1/invoices/{id}/sendinvoices:write下書きを送ります(送信済みならメールだけ送り直し)。無効にするときは POST /invoices/{id}/void。取得・一覧は GET /invoices/{id}・GET /invoices。status:draft / open / paid / void(期限切れは overdue=true)
curl -X POST https://www.swapay-app.com/api/v1/invoices/in_01jbx5a1s2d3f4g5h6j7k8l9m0/send \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 69134d81-15c7-4917-9232-e9b33a525383"
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/invoices/in_01jbx5a1s2d3f4g5h6j7k8l9m0/send', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/invoices/in_01jbx5a1s2d3f4g5h6j7k8l9m0/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
});
const data = await res.json();{
"id": "in_01jbx5a1s2d3f4g5h6j7k8l9m0",
"object": "invoice",
"number": "INV-2026-00012",
"title": "10月分 ご利用料金",
"status": "open",
"overdue": false,
"customer": {
"name": "山田 太郎",
"company": "株式会社サンプル",
"email": "billing@example.co.jp"
},
"lines": [
{
"name": "月額利用料",
"unit_amount": 10000,
"quantity": 1,
"tax_rate": 10
}
],
"subtotal": 10000,
"tax": {
"10": 1000,
"8": 0
},
"total": 11000,
"currency": "jpy",
"issue_date": "2026-10-28",
"due_date": "2026-11-30",
"hosted_url": "https://www.swapay-app.com/pay/01jbx5…/invoice",
"payment_url": "https://www.swapay-app.com/pay/01jbx5…",
"sent_at": "2026-10-28T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}料金プラン(Price)の一覧
/v1/pricessubscriptions:read加盟店画面で作ったプランです(作成・変更は加盟店画面で行います)。1件は GET /prices/{id}。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
curl https://www.swapay-app.com/api/v1/prices \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/prices', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/prices', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/prices",
"has_more": false,
"data": [
{
"id": "price_01jbx6p1r2i3c4e5x6y7z8a9b0",
"object": "price",
"code": "BEANS200",
"name": "コーヒー豆 定期便 200g",
"description": "焙煎したての豆を毎月お届けします。",
"unit_amount": 2980,
"tax_behavior": "inclusive",
"tax_rate": 10,
"currency": "jpy",
"recurring": {
"interval": "month",
"interval_count": 1,
"billing_anchor": "day:25"
},
"trial": null,
"setup_fee": 0,
"max_count": null,
"min_term_months": null,
"active": true,
"signup_url": "https://www.swapay-app.com/pay/01jbx6…",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
]
}申込ページの URL を作る
/v1/subscriptionssubscriptions:writeお客様をこの URL へ案内してください。お客様が SWAPay の申込ページで内容に同意し、カードを登録すると契約ができ、subscription.created が届きます(カードの登録と同意はお客様の操作が必要なため、API だけで契約は作れません)。
pricestring必須料金プランの ID
quantityinteger数量(プランで「数量を選べる」にしたとき)
customer_emailstring申込ページのメールアドレス欄に入れておく値
curl -X POST https://www.swapay-app.com/api/v1/subscriptions \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: c618785d-18d7-408d-b05a-c152484f72be" \ -d 'price=price_01jbx6p1r2i3c4e5x6y7z8a9b0' \ -d 'customer_email=user@example.com'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/subscriptions', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'price' => 'price_01jbx6p1r2i3c4e5x6y7z8a9b0',
'customer_email' => 'user@example.com',
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/subscriptions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"price": "price_01jbx6p1r2i3c4e5x6y7z8a9b0",
"customer_email": "user@example.com"
}),
});
const data = await res.json();{
"object": "subscription_checkout",
"price": "price_01jbx6p1r2i3c4e5x6y7z8a9b0",
"quantity": 1,
"url": "https://www.swapay-app.com/pay/01jbx6…?email=user%40example.com",
"livemode": false
}サブスクリプションを取得・一覧
/v1/subscriptions/{id}subscriptions:readstatus:trialing / active / past_due(支払い遅延)/ paused / canceling(解約予定)/ canceled。一覧は GET /subscriptions(status・price で絞り込み)。
curl https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0 \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "sub_01jbx7s1u2b3s4c5r6i7p8t9n0",
"object": "subscription",
"status": "active",
"price": "price_01jbx6p1r2i3c4e5x6y7z8a9b0",
"quantity": 1,
"customer": {
"email": "user@example.com",
"phone": "09012345678"
},
"card": {
"brand": "visa",
"last4": "4242"
},
"next_billing_date": "2026-11-25",
"cancel_at": null,
"canceled_at": null,
"paused_at": null,
"amount_overdue": 0,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}解約
/v1/subscriptions/{id}/cancelsubscriptions:writeat_period_end=true(既定)で、次回請求日の前日まで利用でき、以降は請求しません。false ですぐ解約(取消返金はしません)。
at_period_endboolean既定 true
curl -X POST https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0/cancel \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 003a7f04-55b8-4f8f-abb3-61888cd1f1ca" \ -d 'at_period_end=true'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0/cancel', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'at_period_end' => true,
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0/cancel', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"at_period_end": true
}),
});
const data = await res.json();{
"id": "sub_01jbx7s1u2b3s4c5r6i7p8t9n0",
"object": "subscription",
"status": "canceling",
"price": "price_01jbx6p1r2i3c4e5x6y7z8a9b0",
"quantity": 1,
"customer": {
"email": "user@example.com",
"phone": "09012345678"
},
"card": {
"brand": "visa",
"last4": "4242"
},
"next_billing_date": "2026-11-25",
"cancel_at": "2026-11-25",
"canceled_at": null,
"paused_at": null,
"amount_overdue": 0,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}一時停止・再開
/v1/subscriptions/{id}/pausesubscriptions:write一時停止中は請求しません(未払いの再決済・催促もしません)。再開は POST /subscriptions/{id}/resume(止めていた期間の日割りはしません)。
resume_onstring自動で再開する日(YYYY-MM-DD・日本時間の明日以降)
curl -X POST https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0/pause \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 9d45e11a-4948-4968-801c-733dd6075937" \ -d 'resume_on=2026-12-01'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0/pause', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'resume_on' => '2026-12-01',
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/subscriptions/sub_01jbx7s1u2b3s4c5r6i7p8t9n0/pause', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"resume_on": "2026-12-01"
}),
});
const data = await res.json();{
"id": "sub_01jbx7s1u2b3s4c5r6i7p8t9n0",
"object": "subscription",
"status": "paused",
"price": "price_01jbx6p1r2i3c4e5x6y7z8a9b0",
"quantity": 1,
"customer": {
"email": "user@example.com",
"phone": "09012345678"
},
"card": {
"brand": "visa",
"last4": "4242"
},
"next_billing_date": null,
"cancel_at": null,
"canceled_at": null,
"paused_at": "2026-10-28T03:15:42Z",
"amount_overdue": 0,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}カードの登録ページを作る(SetupSession)
/v1/setup_sessionspayment_methods:writeお客様にカードを登録してもらうページを作ります(予約のキャンセル料・あとで決まる料金のため)。お客様は url のページで電話番号を確認し、使い道(description)と1回の上限(max_amount)に同意して、決済代行会社の入力欄にカードを入れます(カード番号はあなたのサーバーも SWAPay も通りません)。確認のため max_amount の利用枠を 3D セキュアつきで一時的に確保し、すぐに取り消します。登録できると status=complete・payment_method に pm_ が入り、ウェブフック setup_session.completed が届きます。決済代行会社の継続課金の利用が必要です。
max_amountinteger必須お客様が同意する1回の上限(円・1〜1,000,000)
currencystring必須jpy
descriptionstring必須使い道(200文字まで)。お客様の同意の文に入ります。キャンセル料の決まりなどを具体的に
customerstring顧客(cus_)。顧客管理が使えるプランのとき
return_urlstring登録のあと「お店に戻る」の戻り先(https)
expires_ininteger登録できる時間(秒・300〜604,800。既定 86,400)
metadataobject任意のキーと値(登録カードにも引き継ぎます)
curl -X POST https://www.swapay-app.com/api/v1/setup_sessions \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 6c941729-fc95-49b9-9bdc-cad1e35fd84c" \ -d 'max_amount=6600' \ -d 'currency=jpy' \ -d 'description=11/30 50% 100%' \ -d 'customer=cus_01jbxa1c2u3s4t5o6m7e8r9a0b' \ -d 'return_url=https://salon.example.co.jp/reserve/done' \ -d 'metadata[reservation_id]=R-2041'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/setup_sessions', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'max_amount' => 6600,
'currency' => 'jpy',
'description' => '11/30 カット 予約のキャンセル料(前日 50%・当日 100%)',
'customer' => 'cus_01jbxa1c2u3s4t5o6m7e8r9a0b',
'return_url' => 'https://salon.example.co.jp/reserve/done',
'metadata[reservation_id]' => 'R-2041',
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/setup_sessions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"max_amount": 6600,
"currency": "jpy",
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"return_url": "https://salon.example.co.jp/reserve/done",
"metadata[reservation_id]": "R-2041"
}),
});
const data = await res.json();{
"id": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"object": "setup_session",
"status": "open",
"url": "https://www.swapay-app.com/pay/01jbxb1s2e3t4u5p6s7e8s9n0a",
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"max_amount": 6600,
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"payment_method": null,
"return_url": "https://salon.example.co.jp/reserve/done",
"metadata": {
"reservation_id": "R-2041"
},
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}SetupSession を取得・一覧・取消
/v1/setup_sessions/{id}payment_methods:readstatus:open(登録待ち)/ complete(登録済み)/ expired / canceled。一覧は GET /setup_sessions(customer で絞り込み)。登録前のページは POST /setup_sessions/{id}/cancel で取り消せます。
curl https://www.swapay-app.com/api/v1/setup_sessions/{id} \
-H "Authorization: Bearer $SWAPAY_SECRET_KEY"$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/setup_sessions/{id}', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/setup_sessions/{id}', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"object": "setup_session",
"status": "complete",
"url": null,
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"max_amount": 6600,
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"payment_method": "pm_01jbxc1p2m3e4t5h6o7d8a9b0c",
"return_url": "https://salon.example.co.jp/reserve/done",
"metadata": {
"reservation_id": "R-2041"
},
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}SetupSession の一覧
/v1/setup_sessionspayment_methods:read新しい順に返します。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
customerstring顧客で絞り込み
curl https://www.swapay-app.com/api/v1/setup_sessions \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/setup_sessions', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/setup_sessions', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/setup_sessions",
"has_more": false,
"data": [
{
"id": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"object": "setup_session",
"status": "open",
"url": "https://www.swapay-app.com/pay/01jbxb1s2e3t4u5p6s7e8s9n0a",
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"max_amount": 6600,
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"payment_method": null,
"return_url": "https://salon.example.co.jp/reserve/done",
"metadata": {
"reservation_id": "R-2041"
},
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
]
}SetupSession を取消
/v1/setup_sessions/{id}/cancelpayment_methods:write登録前のページを取り消します(登録済みなら 409。登録カードは detach で削除)。
curl -X POST https://www.swapay-app.com/api/v1/setup_sessions/{id}/cancel \
-H "Authorization: Bearer $SWAPAY_SECRET_KEY" \
-H "Idempotency-Key: 94c84710-5a85-4dae-91e3-b3e6c4f76d40"$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/setup_sessions/{id}/cancel', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/setup_sessions/{id}/cancel', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
});
const data = await res.json();{
"id": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"object": "setup_session",
"status": "canceled",
"url": null,
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"max_amount": 6600,
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"payment_method": null,
"return_url": "https://salon.example.co.jp/reserve/done",
"metadata": {
"reservation_id": "R-2041"
},
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}PaymentMethod オブジェクト(登録カード)
お客様が登録したカードです。カード番号は持たず、ブランド・末尾4桁・有効期限だけを返します。お客様が同意した使い道(description)と1回の上限(max_amount)の範囲で、POST /payment_intents(payment_method)で決済できます。お客様は SWAPay のマイページからいつでも削除でき、そのときはウェブフック payment_method.detached が届きます。
statusenumactive / expired(有効期限切れ)/ detached(削除)
max_amountinteger1回の上限(円)
setup_sessionstring登録したページ(seti_)
{
"id": "pm_01jbxc1p2m3e4t5h6o7d8a9b0c",
"object": "payment_method",
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029
},
"status": "active",
"max_amount": 6600,
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"setup_session": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"metadata": {
"reservation_id": "R-2041"
},
"last_used_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}PaymentMethod の一覧・取得
/v1/payment_methodspayment_methods:read新しい順に返します。1件は GET /payment_methods/{id}。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
customerstring顧客で絞り込み
setup_sessionstringSetupSession で絞り込み
curl https://www.swapay-app.com/api/v1/payment_methods \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/payment_methods', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_methods', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/payment_methods",
"has_more": false,
"data": [
{
"id": "pm_01jbxc1p2m3e4t5h6o7d8a9b0c",
"object": "payment_method",
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029
},
"status": "active",
"max_amount": 6600,
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"setup_session": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"metadata": {
"reservation_id": "R-2041"
},
"last_used_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
]
}PaymentMethod を取得
/v1/payment_methods/{id}payment_methods:readcurl https://www.swapay-app.com/api/v1/payment_methods/{id} \
-H "Authorization: Bearer $SWAPAY_SECRET_KEY"$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/payment_methods/{id}', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_methods/{id}', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "pm_01jbxc1p2m3e4t5h6o7d8a9b0c",
"object": "payment_method",
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029
},
"status": "active",
"max_amount": 6600,
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"setup_session": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"metadata": {
"reservation_id": "R-2041"
},
"last_used_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}PaymentMethod を削除
/v1/payment_methods/{id}/detachpayment_methods:write登録カードを削除します(決済代行会社のトークンも無効にします)。元に戻せません。
curl -X POST https://www.swapay-app.com/api/v1/payment_methods/{id}/detach \
-H "Authorization: Bearer $SWAPAY_SECRET_KEY" \
-H "Idempotency-Key: bba68bd3-53e8-4365-89e9-486262f8dc60"$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/payment_methods/{id}/detach', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/payment_methods/{id}/detach', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
});
const data = await res.json();{
"id": "pm_01jbxc1p2m3e4t5h6o7d8a9b0c",
"object": "payment_method",
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029
},
"status": "detached",
"max_amount": 6600,
"description": "11/30 カット 予約のキャンセル料(前日 50%・当日 100%)",
"currency": "jpy",
"customer": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"setup_session": "seti_01jbxb1s2e3t4u5p6s7e8s9n0a",
"metadata": {
"reservation_id": "R-2041"
},
"last_used_at": null,
"created": "2026-10-28T03:15:42Z",
"livemode": false
}顧客を作成
/v1/customerscustomers:write加盟店画面の顧客管理と同じお客様です(顧客管理が使えるプラン:mPOS かストアのプロ)。同じメール・電話のお客様がいれば、新しく作らずにそのお客様を返します(200)。メール・電話は暗号化して保管します。
namestring名前(100文字まで)
emailstringメールアドレス
phonestring電話番号(10〜11桁)
metadataobject任意のキーと値
curl -X POST https://www.swapay-app.com/api/v1/customers \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY" \ -H "Idempotency-Key: 6cb4264c-ad22-4d73-8830-ecf25fab4ca2" \ -d 'name= ' \ -d 'email=taro@example.com' \ -d 'phone=090-1234-5678' \ -d 'metadata[member_no]=A-102'
$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/customers', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'name' => '山田 太郎',
'email' => 'taro@example.com',
'phone' => '090-1234-5678',
'metadata[member_no]' => 'A-102',
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/customers', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"name": "山田 太郎",
"email": "taro@example.com",
"phone": "090-1234-5678",
"metadata[member_no]": "A-102"
}),
});
const data = await res.json();{
"id": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"object": "customer",
"name": "山田 太郎",
"email": "taro@example.com",
"phone": "09012345678",
"metadata": {
"member_no": "A-102"
},
"created": "2026-10-28T03:15:42Z",
"livemode": false
}顧客を取得
/v1/customers/{id}customers:readcurl https://www.swapay-app.com/api/v1/customers/{id} \
-H "Authorization: Bearer $SWAPAY_SECRET_KEY"$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/customers/{id}', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/customers/{id}', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"object": "customer",
"name": "山田 太郎",
"email": "taro@example.com",
"phone": "09012345678",
"metadata": {
"member_no": "A-102"
},
"created": "2026-10-28T03:15:42Z",
"livemode": false
}顧客の一覧
/v1/customerscustomers:read新しい順に返します。email・phone は完全一致で探します。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
emailstringメールアドレス(完全一致)
phonestring電話番号(完全一致)
curl https://www.swapay-app.com/api/v1/customers \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/customers', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/customers', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/customers",
"has_more": false,
"data": [
{
"id": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"object": "customer",
"name": "山田 太郎",
"email": "taro@example.com",
"phone": "09012345678",
"metadata": {
"member_no": "A-102"
},
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
]
}顧客を更新
/v1/customers/{id}customers:write指定した項目だけ変えます。ほかのお客様と同じメール・電話にはできません(409 customer_exists)。
namestringemailstringphonestringmetadataobjectcurl -X POST https://www.swapay-app.com/api/v1/customers/{id} \
-H "Authorization: Bearer $SWAPAY_SECRET_KEY" \
-H "Idempotency-Key: 74c10b6d-5650-4232-805f-cdefac9dd62c" \
-d 'name= '$res = (new GuzzleHttp\Client())->request('POST', 'https://www.swapay-app.com/api/v1/customers/{id}', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY'), 'Idempotency-Key' => $orderId],
'json' => [
'name' => '山田 太郎',
],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/customers/{id}', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': orderId,
},
body: JSON.stringify({
"name": "山田 太郎"
}),
});
const data = await res.json();{
"id": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"object": "customer",
"name": "山田 太郎",
"email": "taro@example.com",
"phone": "09012345678",
"metadata": {
"member_no": "A-102"
},
"created": "2026-10-28T03:15:42Z",
"livemode": false
}顧客を削除
/v1/customers/{id}customers:writeお客様の情報を消し、そのお客様の登録カードも削除します(取扱高の集計は残ります)。元に戻せません。
curl -X DELETE https://www.swapay-app.com/api/v1/customers/{id} \
-H "Authorization: Bearer $SWAPAY_SECRET_KEY"$res = (new GuzzleHttp\Client())->request('DELETE', 'https://www.swapay-app.com/api/v1/customers/{id}', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/customers/{id}', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"id": "cus_01jbxa1c2u3s4t5o6m7e8r9a0b",
"object": "customer",
"deleted": true
}精算の一覧・取得
/v1/settlementssettlements:read締めた期間ごとの取扱高・取消返金・手数料・入金額です。1件は GET /settlements/{id}。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
curl https://www.swapay-app.com/api/v1/settlements \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/settlements', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/settlements', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/settlements",
"has_more": false,
"data": [
{
"id": "stl_01jbx8s1e2t3t4l5e6m7e8n9t0",
"object": "settlement",
"period_start": "2026-10-01",
"period_end": "2026-10-15",
"payout_date": "2026-10-31",
"payout_route": "swapay",
"transaction_count": 128,
"gross": 412800,
"refunds": 3960,
"fees": 13374,
"carry_over": 0,
"net": 395466,
"status": "unpaid",
"paid_at": null,
"currency": "jpy",
"livemode": false
}
]
}イベントとウェブフック
ウェブフックは加盟店画面の API管理 > Webhook で登録します。本文はこの Event オブジェクトです。ヘッダー SWAPay-Signature(t=タイムスタンプ,v1=署名)で必ず検証してください:署名シークレットで「t.本文」を HMAC-SHA256 した16進数と v1 を比べ、t が5分以上ずれていたら受け付けないでください。2xx 以外の応答は最大16回(約2日)再送し、同じイベントは同じ id で届きます。
payment_intent.succeededtypeAPI で作った支払いが完了した
payment_intent.payment_failedtypeAPI で作った支払いが失敗した
charge.succeededtype決済が完了した(すべての受付経路)
charge.failedtype決済が失敗した
refund.succeededtype取消返金が完了した
refund.failedtype取消返金が失敗した
subscription.createdtypeサブスクリプションの申込が完了した
subscription.canceledtypeサブスクリプションが解約された
subscription.payment_failedtypeサブスクリプションの決済が失敗した
subscription.payment_succeededtypeサブスクリプションの決済が完了した
setup_session.completedtypeお客様がカードを登録した(PaymentMethod ができた)
payment_method.detachedtype登録カードが削除された
{
"id": "evt_01jbx9e1v2e3n4t5a6b7c8d9e0",
"object": "event",
"type": "payment_intent.succeeded",
"api_version": "2026-11-07",
"created": "2026-10-28T03:15:42Z",
"data": {
"object": {
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3960,
"amount_received": 3960,
"amount_refunded": 0,
"currency": "jpy",
"status": "succeeded",
"description": "ご注文 1029",
"metadata": {
"order_id": "1029"
},
"checkout_url": null,
"next_action": null,
"return_url": "https://shop.example.co.jp/thanks",
"latest_charge": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"customer": null,
"payment_method": null,
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
},
"livemode": false
}イベントの一覧・取得
/v1/eventsevents:read30日分を新しい順に返します。ウェブフックを受け取れなかったときの確認に使えます。1件は GET /events/{id}。
limitinteger1〜100(既定 20)
starting_afterstring前のページの最後の ID。次のページを取るときに指定
created[gte]string作成日時(RFC 3339 か UNIX 秒)以降。gt・lt・lte も使えます
typestringイベントの種類で絞り込み
curl https://www.swapay-app.com/api/v1/events \ -H "Authorization: Bearer $SWAPAY_SECRET_KEY"
$res = (new GuzzleHttp\Client())->request('GET', 'https://www.swapay-app.com/api/v1/events', [
'headers' => ['Authorization' => 'Bearer '.getenv('SWAPAY_SECRET_KEY')],
'http_errors' => false,
]);
$data = json_decode((string) $res->getBody(), true);const res = await fetch('https://www.swapay-app.com/api/v1/events', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.SWAPAY_SECRET_KEY}`,
},
});
const data = await res.json();{
"object": "list",
"url": "/v1/events",
"has_more": false,
"data": [
{
"id": "evt_01jbx9e1v2e3n4t5a6b7c8d9e0",
"object": "event",
"type": "payment_intent.succeeded",
"api_version": "2026-11-07",
"created": "2026-10-28T03:15:42Z",
"data": {
"object": {
"id": "pi_01jbx3q4w2k8m5n6p7r8s9t0va",
"object": "payment_intent",
"amount": 3960,
"amount_received": 3960,
"amount_refunded": 0,
"currency": "jpy",
"status": "succeeded",
"description": "ご注文 1029",
"metadata": {
"order_id": "1029"
},
"checkout_url": null,
"next_action": null,
"return_url": "https://shop.example.co.jp/thanks",
"latest_charge": "ch_01jbx3t9a1b2c3d4e5f6g7h8j9",
"customer": null,
"payment_method": null,
"last_payment_error": null,
"expires_at": "2026-10-29T03:15:42Z",
"created": "2026-10-28T03:15:42Z",
"livemode": false
}
},
"livemode": false
}
]
}