APIリファレンスと統合のヒント。
CommonRockは認証・セッション・簡易DBを提供し、アプリ側のサーバ実装を最小化します。
CommonRockのAPIは2つの認証方式をサポートしています。エンドポイントによって、片方または両方の方式で呼び出せます。
ブラウザやモバイルアプリから直接呼び出す場合に使用します。
バックエンドサーバから呼び出す場合に使用します。
各公開クライアントには一連のスコープが付与されます。匿名呼び出しとエンドユーザ認証済み呼び出しで異なるスコープ集合を設定できます。付与外のスコープの呼び出しは 403 client_scope_denied を返します。
| スコープ | 許可される操作 |
|---|---|
| end_users:signup | 新規エンドユーザを登録(サインアップ)します。 |
| end_users:login | エンドユーザをログインさせ、トークンを発行します。 |
| end_users:refresh | エンドユーザのリフレッシュトークンをローテーションします。 |
| end_users:logout | 現在のエンドユーザセッションを失効します。 |
| end_users:me | 現在のエンドユーザのプロフィールを読み取ります。 |
| sql:execute | 公開 SQL クエリ定義を実行します(同期・非同期)。 |
| tables:rw | 公開対応テーブルの行を、エンドユーザにスコープして読み書きします。 |
| relay:proxy | リレー経由でリソースサーバへリクエストをプロキシします。 |
バックエンドからOpaqueトークンをイントロスペクトします。
curl -X POST /org_demo_payments/v1/sessions/introspect \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"token":"access_token"}'ブラウザ/ネイティブからは Public Client (X-Client-Id) を、サーバ側からは API Secret Key (X-API-Key) を使います。Public Client で許可する Origin はポータル側で先に設定してください。
// app/api/login/route.ts (Next.js App Router)
// 1. Browser → your Next.js Route Handler
// 2. Route Handler → CommonRock public endpoint with X-Client-Id / X-Client-Key
// 3. Set HttpOnly session cookie back to the browser
import { NextResponse } from "next/server";
const COMMONROCK_BASE = process.env.COMMONROCK_API_BASE_URL!;
const CLIENT_ID = process.env.COMMONROCK_CLIENT_ID!;
const CLIENT_KEY = process.env.COMMONROCK_CLIENT_KEY!;
export async function POST(request: Request) {
const body = await request.json();
const res = await fetch(`${COMMONROCK_BASE}/v1/public/end-users/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Client-Id": CLIENT_ID,
"X-Client-Key": CLIENT_KEY,
Origin: request.headers.get("origin") ?? ""
},
body: JSON.stringify(body)
});
const payload = await res.json();
if (!res.ok) return NextResponse.json(payload, { status: res.status });
const response = NextResponse.json({ ok: true, user: payload.user });
response.cookies.set("cr_at", payload.access_token, {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: payload.expires_in
});
return response;
}本番では Public Client / API Secret Key を必ず .env など秘匿化された場所に保管してください。
Route Handler でサーバ側にキーを置き、HttpOnly Cookie でブラウザに返すパターンを推奨。
ネイティブアプリは Public Client + 端末情報を Origin として送る運用。Secret Key は埋め込まない。
サーバ間 API は X-API-Key + allowed_cidrs/allowed_origins で IP 帯を絞ること。
公開APIのリクエスト/レスポンス仕様を詳述します。
ユーザ登録・ログイン・セッション管理
外部IDとパスワードで新規登録し、アクセストークンとリフレッシュトークンを発行します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| external_id | string | 必須 | アプリ内ユーザID(最大128バイト。半角英数字なら128文字) |
| password | string | 必須 | 12文字以上で大文字・小文字・数字を含むこと。よくあるパスワードや漏洩実績のあるパスワードは拒否されます。 |
| device_id | string | 任意 | 最大128文字。body か X-Device-Id ヘッダで必須 |
curl -X POST /org_demo_payments/v1/public/end-users/signup \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-d '{"external_id":"user-1","password":"password123","device_id":"iphone-15"}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| token | string | 必須 | アクセストークン(Opaque) |
| refresh_token | string | 必須 | リフレッシュトークン |
| end_user.id | uuid | 必須 | エンドユーザID |
| end_user.external_id | string | 必須 | 外部ID |
| session_id | uuid | 必須 | セッションID |
| expires_at | datetime | 必須 | アクセストークン有効期限(ISO8601) |
| refresh_expires_at | datetime | 必須 | リフレッシュ有効期限(ISO8601) |
{
"token":"access_token",
"refresh_token":"refresh_token",
"end_user":{"id":"uuid","external_id":"user-1"},
"session_id":"uuid",
"expires_at":"2026-02-04T13:00:00Z",
"refresh_expires_at":"2026-03-05T13:00:00Z"
}{
"code":"external_id_conflict",
"message":"External ID already registered",
"detail":{"code":"external_id_conflict","message":"External ID already registered"}
}外部IDとパスワードでログインし、トークンを再発行します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| external_id | string | 必須 | 外部ID |
| password | string | 必須 | パスワード |
| device_id | string | 任意 | 最大128文字。body か X-Device-Id ヘッダで必須 |
curl -X POST /org_demo_payments/v1/public/end-users/login \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-d '{"external_id":"user-1","password":"password123","device_id":"iphone-15"}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| token | string | 必須 | アクセストークン |
| refresh_token | string | 必須 | リフレッシュトークン |
| end_user.id | uuid | 必須 | エンドユーザID |
| end_user.external_id | string | 必須 | 外部ID |
| session_id | uuid | 必須 | セッションID |
| expires_at | datetime | 必須 | アクセストークン有効期限 |
| refresh_expires_at | datetime | 必須 | リフレッシュ有効期限 |
{
"token":"access_token",
"refresh_token":"refresh_token",
"end_user":{"id":"uuid","external_id":"user-1"},
"session_id":"uuid",
"expires_at":"2026-02-04T13:00:00Z",
"refresh_expires_at":"2026-03-05T13:00:00Z"
}{
"code":"invalid_credentials",
"message":"Invalid credentials",
"detail":{"code":"invalid_credentials","message":"Invalid credentials"}
}リフレッシュトークンでアクセストークンを再発行します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| refresh_token | string | 必須 | リフレッシュトークン |
| device_id | string | 任意 | 最大128文字。body か X-Device-Id ヘッダで必須 |
curl -X POST /org_demo_payments/v1/public/end-users/refresh \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-d '{"refresh_token":"refresh_token","device_id":"iphone-15"}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| token | string | 必須 | 新しいアクセストークン |
| refresh_token | string | 必須 | 新しいリフレッシュトークン |
| end_user.id | uuid | 必須 | エンドユーザID |
| end_user.external_id | string | 必須 | 外部ID |
| session_id | uuid | 必須 | セッションID |
| expires_at | datetime | 必須 | アクセストークン有効期限 |
| refresh_expires_at | datetime | 必須 | リフレッシュ有効期限 |
{
"token":"new_access_token",
"refresh_token":"new_refresh_token",
"end_user":{"id":"uuid","external_id":"user-1"},
"session_id":"uuid",
"expires_at":"2026-02-04T13:10:00Z",
"refresh_expires_at":"2026-03-05T13:10:00Z"
}{
"code":"invalid_refresh_token",
"message":"Invalid refresh token",
"detail":{"code":"invalid_refresh_token","message":"Invalid refresh token"}
}アクセストークンを失効します。
curl -X POST /org_demo_payments/v1/public/end-users/logout \ -H 'Origin: https://app.example.com' \ -H 'X-Client-Id: pk_live_***' \ -H 'X-Client-Key: pk_live_***' \ -H 'Authorization: Bearer access_token'
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| status | string | 必須 | ok 固定 |
{"status":"ok"}{
"code":"invalid_session",
"message":"Invalid session",
"detail":{"code":"invalid_session","message":"Invalid session"}
}アクセストークンに紐づくエンドユーザを取得します。
curl /org_demo_payments/v1/public/end-users/me \ -H 'Origin: https://app.example.com' \ -H 'X-Client-Id: pk_live_***' \ -H 'X-Client-Key: pk_live_***' \ -H 'Authorization: Bearer access_token'
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| id | uuid | 必須 | エンドユーザID |
| external_id | string | 必須 | 外部ID |
{"id":"uuid","external_id":"user-1"}{
"code":"invalid_session",
"message":"Invalid session",
"detail":{"code":"invalid_session","message":"Invalid session"}
}SQLクエリ定義の実行(同期・非同期)
登録済みSQLクエリ定義を実行してページング取得します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| query_definition_id | uuid | 必須 | SQLクエリ定義ID |
| params | object | 任意 | SQLパラメータ。auth. で始まる名前は予約済みのため拒否されます。 |
| limit | int | 任意 | 1〜200(SQL_MAX_ROWS でデプロイ毎に変更可、既定200) |
| cursor | string | 任意 | offset or keyset cursor |
| cursor_mode | string | 任意 | offset / keyset (default offset) |
curl -X POST /org_demo_payments/v1/public/sql/execute \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-H 'Authorization: Bearer access_token' \
-d '{"query_definition_id":"uuid","params":{"author_id":"user-1"},"limit":200}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| rows | array | 必須 | 結果行 |
| next_cursor | string | 任意 | 次ページのカーソル |
| warnings[].code | string | 任意 | 警告コード |
| warnings[].message | string | 任意 | 警告メッセージ |
{"rows":[{"id":"uuid","title":"post-1"}],"next_cursor":"200","warnings":[{"code":"order_by_missing","message":"ORDER BY is missing; pagination may be unstable"}]}{
"code":"template_server_only",
"message":"This template is not available to public clients",
"detail":{"code":"template_server_only","message":"This template is not available to public clients"}
}SQLクエリ定義をバックグラウンド実行に投入し、結果をポーリングします。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| query_definition_id | uuid | 必須 | SQLクエリ定義ID |
| params | object | 任意 | SQLパラメータ。auth. で始まる名前は予約済みのため拒否されます。 |
| limit | int | 任意 | 1〜200(SQL_MAX_ROWS でデプロイ毎に変更可、既定200) |
curl -X POST /org_demo_payments/v1/public/sql/execute-async \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-d '{"query_definition_id":"uuid","params":{"author_id":"user-1"}}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| job_id | string | 必須 | 非同期ジョブ ID |
| status | string | 必須 | queued / running / succeeded / failed |
| submitted_at | datetime | 必須 | ジョブ受理時刻(ISO8601) |
| expires_at | datetime | 必須 | ジョブと結果の有効期限(ISO8601) |
| storage | string | 必須 | 結果の保存先(redis または memory) |
{
"job_id":"uuid",
"status":"queued",
"submitted_at":"2026-06-12T01:00:00Z",
"expires_at":"2026-06-12T01:15:00Z",
"storage":"redis"
}非同期 SQL ジョブのステータスと(終了時は)結果を取得します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| job_id | string | 必須 | 非同期ジョブ ID |
curl /org_demo_payments/v1/public/sql/execute-async/<job_id> \ -H 'Origin: https://app.example.com' \ -H 'X-Client-Id: pk_live_***' \ -H 'X-Client-Key: pk_live_***'
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| job_id | string | 必須 | 非同期ジョブ ID |
| status | string | 必須 | queued / running / succeeded / failed |
| result | object | 任意 | status が succeeded のときの結果ペイロード |
| error | object | 任意 | status が failed のときのエラーエンベロープ |
| expires_at | datetime | 必須 | ジョブと結果の有効期限(ISO8601) |
{
"job_id":"uuid",
"status":"succeeded",
"result":{"rows":[{"id":"uuid","title":"post-1"}],"next_cursor":null},
"expires_at":"2026-06-12T01:15:00Z"
}{
"code":"async_sql_job_not_found",
"message":"Async SQL job not found",
"detail":{"code":"async_sql_job_not_found","message":"Async SQL job not found"}
}スキーマレスなテーブル・カラム・行
プロジェクトのユーザDBテーブルを一覧、または型付きカラムで新規作成します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| columns | ColumnDefinition[] | 必須 | カラム定義の配列 |
| columns[].name | string | 必須 | カラム名 |
| columns[].type | string | 必須 | text / integer / numeric / boolean / timestamptz / uuid のいずれか |
| columns[].nullable | boolean | 任意 | NULL を許可するか(既定 true) |
| columns[].encrypted | boolean | 任意 | true の場合、サーバはクライアント側暗号化済みの不透明な暗号文を保存します(既定 false) |
# List tables
curl /org_demo_payments/v1/tables -H 'X-API-Key: sk_live_***'
# Create a table
curl -X POST /org_demo_payments/v1/tables \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"name":"posts","columns":[{"name":"title","type":"text"},{"name":"likes","type":"integer","nullable":true}]}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| id | uuid | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| columns | array | 必須 | カラム定義の配列 |
{
"id":"uuid",
"name":"posts",
"columns":[
{"name":"title","type":"text","nullable":true,"encrypted":false},
{"name":"likes","type":"integer","nullable":true,"encrypted":false}
]
}テーブルと全行を削除します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| table_name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
curl -X DELETE /org_demo_payments/v1/tables/posts -H 'X-API-Key: sk_live_***'
{"status":"ok"}テーブルに型付きカラムを追加、または既存カラムを削除します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| table_name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| name | string | 必須 | カラム名 |
| type | string | 必須 | text / integer / numeric / boolean / timestamptz / uuid のいずれか |
| nullable | boolean | 任意 | NULL を許可するか(既定 true) |
| encrypted | boolean | 任意 | true の場合、サーバはクライアント側暗号化済みの不透明な暗号文を保存します(既定 false) |
# Add a column
curl -X POST /org_demo_payments/v1/tables/posts/columns \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"name":"body","type":"text","nullable":true}'
# Drop a column
curl -X DELETE /org_demo_payments/v1/tables/posts/columns/body -H 'X-API-Key: sk_live_***'{"status":"ok"}ソート・ページング・カーソルで行を一覧、または新しい行を挿入します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| table_name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| sort | string | 任意 | ソート対象カラム。先頭に - を付けると降順 |
| limit | int | 任意 | 1ページの件数。1〜200(既定50) |
| cursor | string | 任意 | 前回レスポンスの不透明なページングカーソル |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| <column> | any | 任意 | 行のカラム名と値のペア |
# List rows (newest first, page of 20)
curl '/org_demo_payments/v1/tables/posts/rows?sort=-created_at&limit=20' \
-H 'X-API-Key: sk_live_***'
# Insert a row
curl -X POST /org_demo_payments/v1/tables/posts/rows \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"title":"hello","likes":0}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| rows | array | 必須 | 結果行 |
| next_cursor | string | 任意 | 前回レスポンスの不透明なページングカーソル |
{"rows":[{"id":"uuid","title":"hello","likes":0}],"next_cursor":null}ID を指定して1行を取得・部分更新・削除します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| table_name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| row_id | uuid | 必須 | 行 ID(UUID) |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| <column> | any | 任意 | 行のカラム名と値のペア |
# Get a row
curl /org_demo_payments/v1/tables/posts/rows/<row_id> -H 'X-API-Key: sk_live_***'
# Update a row
curl -X PATCH /org_demo_payments/v1/tables/posts/rows/<row_id> \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"likes":5}'
# Delete a row
curl -X DELETE /org_demo_payments/v1/tables/posts/rows/<row_id> -H 'X-API-Key: sk_live_***'{"id":"uuid","title":"hello","likes":5}現在のエンドユーザ向けに公開対応テーブルを一覧します。
curl /org_demo_payments/v1/public/tables \ -H 'Origin: https://app.example.com' \ -H 'X-Client-Id: pk_live_***' \ -H 'X-Client-Key: pk_live_***' \ -H 'Authorization: Bearer access_token'
{"tables":[{"name":"posts","columns":[{"name":"title","type":"text"}]}]}現在のエンドユーザにスコープされた行を一覧、または挿入します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| table_name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| sort | string | 任意 | ソート対象カラム。先頭に - を付けると降順 |
| limit | int | 任意 | 1ページの件数。1〜200(既定50) |
| cursor | string | 任意 | 前回レスポンスの不透明なページングカーソル |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| <column> | any | 任意 | 行のカラム名と値のペア |
# List the current end user's rows
curl '/org_demo_payments/v1/public/tables/posts/rows?limit=20' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-H 'Authorization: Bearer access_token'
# Insert a row (auto-scoped to the end user)
curl -X POST /org_demo_payments/v1/public/tables/posts/rows \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-H 'Authorization: Bearer access_token' \
-d '{"title":"my post"}'{"rows":[{"id":"uuid","title":"my post"}],"next_cursor":null}{
"code":"end_user_id_not_writable",
"message":"end_user_id is managed by the server",
"detail":{"code":"end_user_id_not_writable","message":"end_user_id is managed by the server"}
}ID を指定して現在のエンドユーザの行を取得・部分更新・削除します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| table_name | string | 必須 | テーブル名(小文字・英数字・アンダースコア) |
| row_id | uuid | 必須 | 行 ID(UUID) |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| <column> | any | 任意 | 行のカラム名と値のペア |
curl -X PATCH /org_demo_payments/v1/public/tables/posts/rows/<row_id> \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-H 'Authorization: Bearer access_token' \
-d '{"title":"edited"}'{"id":"uuid","title":"edited"}リソースサーバへのプロキシ・非同期ディスパッチ・ルートポリシー
設定済みリソースサーバの上流へ任意メソッドをプロキシし、レスポンスをそのまま返します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| resource_server_id | string | 必須 | リソースサーバ ID(rs_...) |
| path | string | 必須 | リソースサーバのターゲットに付加される上流パス |
curl -X POST /org_demo_payments/v1/public/relay/rs_xxx/v1/messages \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-H 'Authorization: Bearer access_token' \
-d '{"text":"hello upstream"}'(the upstream response is returned verbatim, including status and headers)
リレーリクエストをバックグラウンド配送に投入し、上流レスポンスをポーリングします。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| resource_server_id | string | 必須 | リソースサーバ ID(rs_...) |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| method | string | 任意 | ディスパッチする HTTP メソッド(既定 GET) |
| path | string | 必須 | リソースサーバのターゲットに付加される上流パス |
| query | string | 任意 | 生のクエリ文字列(最大4096文字) |
| headers | object | 任意 | 上流へ転送するヘッダ名/値のマップ |
| body_base64 | string | 任意 | Base64 エンコードしたリクエストボディ |
curl -X POST /org_demo_payments/v1/public/relay/rs_xxx/dispatch-async \
-H 'Content-Type: application/json' \
-H 'Origin: https://app.example.com' \
-H 'X-Client-Id: pk_live_***' \
-H 'X-Client-Key: pk_live_***' \
-d '{"method":"POST","path":"v1/messages","body_base64":"eyJ0ZXh0IjoiaGkifQ=="}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| job_id | string | 必須 | 非同期ジョブ ID |
| status | string | 必須 | queued / running / succeeded / failed |
| submitted_at | datetime | 必須 | ジョブ受理時刻(ISO8601) |
| expires_at | datetime | 必須 | ジョブと結果の有効期限(ISO8601) |
| relay_mode | string | 必須 | 解決された relay mode(public / wireguard_push / local_agent) |
{
"job_id":"uuid",
"status":"queued",
"submitted_at":"2026-06-12T01:00:00Z",
"expires_at":"2026-06-12T01:05:00Z",
"relay_mode":"wireguard_push"
}リレージョブのステータスを取得、または完了までロングポーリングします。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| job_id | string | 必須 | 非同期ジョブ ID |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| timeout_sec | int | 任意 | 待機タイムアウト秒数。1〜300(既定30) |
# Poll once curl /org_demo_payments/v1/public/relay/jobs/<job_id> \ -H 'Origin: https://app.example.com' \ -H 'X-Client-Id: pk_live_***' \ -H 'X-Client-Key: pk_live_***' # Long-poll up to 30s curl '/org_demo_payments/v1/public/relay/jobs/<job_id>/wait?timeout_sec=30' \ -H 'Origin: https://app.example.com' \ -H 'X-Client-Id: pk_live_***' \ -H 'X-Client-Key: pk_live_***'
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| job_id | string | 必須 | 非同期ジョブ ID |
| status | string | 必須 | queued / running / succeeded / failed |
| response_status_code | int | 任意 | 上流の HTTP ステータスコード |
| response_headers | object | 任意 | 上流のレスポンスヘッダ |
| response_body_base64 | string | 任意 | Base64 エンコードした上流のレスポンスボディ |
{
"job_id":"uuid",
"status":"succeeded",
"response_status_code":200,
"response_headers":{"content-type":"application/json"},
"response_body_base64":"eyJvayI6dHJ1ZX0="
}{
"code":"relay_job_not_found",
"message":"Relay job not found",
"detail":{"code":"relay_job_not_found","message":"Relay job not found"}
}push トンネル断時に使うルート別フォールバックポリシーを管理します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| resource_server_id | string | 必須 | リソースサーバ ID(rs_...) |
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| method | string | 必須 | ポリシーが一致する HTTP メソッド(任意は *) |
| path_pattern | string | 必須 | ポリシーが一致するパスパターン |
| on_tunnel_down | string | 必須 | push トンネル断時の挙動:poll または fail |
| allow_nonidempotent_fallback | boolean | 任意 | 非冪等メソッドのポーリングフォールバックを許可するか |
# List route policies
curl /org_demo_payments/v1/relay/rs_xxx/policies -H 'X-API-Key: sk_live_***'
# Upsert a route policy
curl -X PUT /org_demo_payments/v1/relay/rs_xxx/policies \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"method":"POST","path_pattern":"/v1/messages","on_tunnel_down":"fail","allow_nonidempotent_fallback":false}'
# Set the per-RS default
curl -X PUT /org_demo_payments/v1/relay/rs_xxx/policy-default \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"on_tunnel_down":"poll"}'
# Delete a route policy
curl -X DELETE /org_demo_payments/v1/relay/rs_xxx/policies/<policy_id> -H 'X-API-Key: sk_live_***'{
"policies":[
{"id":"uuid","method":"POST","path_pattern":"/v1/messages","on_tunnel_down":"fail","allow_nonidempotent_fallback":false}
],
"default_on_tunnel_down":"poll"
}セッションイントロスペクション
トークンが有効かを他サーバから検証します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| token | string | 任意 | アクセストークン |
| required_scopes | string[] | 任意 | 将来拡張用(現在未使用) |
curl -X POST /org_demo_payments/v1/sessions/introspect \
-H 'Content-Type: application/json' \
-H 'X-API-Key: sk_live_***' \
-d '{"token":"access_token"}'| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| active | boolean | 必須 | 有効なら true |
| project_id | uuid | 任意 | プロジェクトID |
| end_user_id | uuid | 任意 | エンドユーザID |
| session_id | uuid | 任意 | セッションID |
| expires_at | datetime | 任意 | 有効期限 |
{"active":true,"project_id":"uuid","end_user_id":"uuid","session_id":"uuid","expires_at":"2026-02-04T13:00:00Z"}{
"code":"invalid_api_key",
"message":"Invalid API key",
"detail":{"code":"invalid_api_key","message":"Invalid API key"}
}シークレット API キーはプランごとにレート制限されます。上限に達すると API は 429 rate_limited を返します。
| プラン | リクエスト/秒 | バースト |
|---|---|---|
| Free | 60 | 240 |
| Pro | 200 | 800 |
| Max | 1000 | 4000 |
| Enterprise | 無制限 | 無制限 |
429 レスポンスには ratelimit-limit / ratelimit-remaining / ratelimit-reset / retry-after ヘッダに加えて、どのバケットに当たったかを示す x-ratelimit-reason(submit / service_plan / secret_plan / public_client)が付きます。
リソースサーバは Portal のリレータブルから RS 単位のリレーレート制限(relay_rate_limit_rps / burst)を追加設定できます。
2xx 以外のレスポンスはすべて同じ構造化エンベロープを使います。code と message はトップレベルと detail の両方に重複します。
| Code | HTTP | 説明 |
|---|---|---|
| invalid_credentials | 401 | 認証情報が不正 |
| totp_required | 403 | TOTPコードが必要 |
| invalid_totp | 401 | TOTPコードが不正 |
| project_not_found | 404 | プロジェクトが見つからない |
| invalid_cursor | 400 | カーソルが不正 |
| invalid_sql | 400 | SQLが不正 |
| sql_too_complex | 400 | SQL複雑度超過 |
| missing_api_key | 401 | APIキーが未指定 |
| invalid_api_key | 401 | APIキーが不正 |
| restrictions_required | 403 | 制限が未設定 |
| origin_required | 403 | Originヘッダ必須 |
| origin_denied | 403 | Originが許可されていない |
| ip_denied | 403 | IPが許可されていない |
| invalid_public_scopes | 400 | 公開スコープが不正 |
| sql_template_not_found | 404 | SQLテンプレートがない |
| maintenance_mode | 503 | メンテナンス中 |
| csrf_failed | 403 | CSRF検証失敗 |
| rate_limited | 429 | レート制限に到達 |
| invalid_session | 401 | セッションが無効または失効しています。再認証してください。 |
| invalid_refresh_token | 401 | リフレッシュトークンが無効か使用済みです。再認証してください。 |
| account_locked | 403 | 失敗回数が多すぎるため、アカウントが一時的にロックされています。 |
| authorization_required | 401 | このテンプレートにはエンドユーザのアクセストークンが必要です。 |
| service_busy | 503 | サービスが一時的に混雑しています。バックオフして再試行してください。 |
| validation_error | 422 | リクエスト検証に失敗しました。detail.errors[] を参照してください。 |
| external_id_conflict | 409 | external_id は既に登録済みです。 |
| template_not_found | 404 | SQLテンプレートがない |
| template_server_only | 403 | このテンプレートはサーバ専用で、公開クライアントからは呼べません。 |
| relay_failed | 502 | リレー上流に到達できませんでした。 |
| relay_timeout | 504 | リレー上流が時間内に応答しませんでした。 |
| tunnel_unavailable | 503 | リレーの push トンネルが利用できず、フォールバックも無効です。 |
| relay_body_too_large | 413 | リレーのリクエストボディが上限を超えています。 |
上記の表は安定したクライアント契約エラーコードの一覧です。各エンドポイント固有のエラーは API リファレンスの各エンドポイント詳細を参照してください。
エラーエンベロープ
2xx 以外のレスポンスはすべて同じ JSON エンベロープを使います。code と message はトップレベルと detail の両方に重複します。detail には title / recovery / action_kind / action_label と、(検証エラー時は)errors[] が含まれることがあります。
{
"code": "invalid_session",
"message": "Invalid session",
"detail": {
"code": "invalid_session",
"message": "Invalid session",
"title": "Session expired",
"recovery": "Sign in again to continue.",
"action_kind": "reauth",
"action_label": "Sign in"
}
}バリデーション (422)
検証エラーは HTTP 422・code=validation_error で、フィールドエラーの配列が detail.errors[] に入ります。
{
"code": "validation_error",
"message": "Invalid request parameters",
"detail": {
"code": "validation_error",
"message": "Invalid request parameters",
"errors": [
{"field": "external_id", "code": "external_id_required", "message": "external_id is required"}
]
}
}シークレットキー認証エラー
{
"code": "rate_limited",
"message": "Rate limit exceeded",
"detail": {"code": "rate_limited", "message": "Rate limit exceeded"}
}リトライ vs 再認証
503 service_busy やその他の 5xx は一過性として扱い、指数バックオフで再試行してください。一方、401 invalid_session と 401 invalid_refresh_token は認証情報が無効になったことを意味します。リトライせず再認証してください(再ログイン、またはリフレッシュトークンのローテーション)。429 rate_limited は retry-after / ratelimit-reset の窓が過ぎるまでバックオフしてください。
API変更履歴を時系列で掲載します。