API仕様書

ReserveG 外部連携API v1.0.0。POSレジや基幹システムから、商品・予約・受取枠を読み書きするためのREST APIです。

最終更新: 2026年8月26日

1.概要

JSON を返す REST API です。すべてのエンドポイントは /api/v1 の下にあります。

項目内容
ベースURLhttps://(このサイトのドメイン)/api/v1
形式リクエスト・応答ともに JSON(UTF-8)
認証APIキー(Authorization: Bearer)
バージョンv1.0.0(パスの /v1 が変わらない限り、後方互換を壊す変更はしません)
対象範囲APIキーを発行した店舗のデータのみ

できること・できないこと

商品の登録・更新・削除、予約の参照とステータス変更、受取枠の参照ができます。予約の新規作成はAPIでは行えません(在庫と枠の整合を守るため、 お客様向けの予約ページからのみ受け付けます)。

2.認証

  1. 1管理画面の「データ連携 → API連携」で APIキーを発行します。 権限は read(参照のみ)と write(参照と更新)から選びます。
  2. 2発行直後に表示されるキーを控えます。表示されるのはこの一度きりで、あとから確認する方法はありません。
  3. 3リクエストの Authorization ヘッダーに付けて送ります。
Authorization: Bearer rg_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

キーは店舗に紐づいています。1本のキーから見えるのは、その発行元の店舗のデータだけです。 複数店舗を運営している場合は、店舗ごとにキーを発行してください。

キーの取り扱い

キーはパスワードと同じです。ブラウザで動くコードや公開リポジトリには置かないでください。 漏れた可能性があるときは管理画面から「無効化」し、新しいキーを発行してください。 無効化したキーは即座に 401 を返すようになります。

3.共通の約束ごと

日付と時刻

  • pickupDate / pickupTime と、クエリの date / from / to はすべて日本時間(JST)の文字列です(YYYY-MM-DD、HH:mm)
  • createdAt / updatedAt / pickupAt は ISO 8601 の UTC(2026-08-27T00:00:00.000Z)です

金額

すべて税込の整数(円)です。unitPrice にはオプションの追加料金が 含まれます(amount = unitPrice × qty)。

一覧のページング

一覧系は limit(既定50・最大200)と offset を受け取り、pagination を添えて返します。

{
  "data": [ ... ],
  "pagination": { "total": 128, "limit": 50, "offset": 0, "hasMore": true }
}

部分更新

PATCH はボディに書いた項目だけを変更します。 省略した項目は現在の値のままです。

レート制限

APIキーごとの回数制限は設けていません。ただしDBへの負荷を避けるため、一覧の取得は limit(最大200)で区切り、定期取得は必要な範囲だけを指定してください。

予約フォーム側の制限

お客様向けの予約ページには連投の抑止があります(同一IP・同一電話番号で短時間に集中した場合)。APIからの参照・更新はこの制限の対象外です。

互換性

既存フィールドの削除や意味の変更は行いません。フィールドの追加はあり得るので、未知のキーを無視できる作りにしておいてください。

4.エラー

失敗したときは、HTTPステータスと合わせて次の形の JSON を返します。

{
  "error": {
    "code": "invalid_request",
    "message": "日付は YYYY-MM-DD 形式で指定してください。",
    "details": [{ "field": "date", "message": "..." }]
  }
}
codeHTTP起きるとき
unauthorized401APIキーが未指定・不正・無効化済み。
forbidden403read キーで更新系を呼んだ。
invalid_request400パラメータやリクエストボディが不正。
not_found404指定したIDのデータが無い。
conflict409SKUの重複、在庫不足などで処理できない。
server_error500サーバー側の想定外のエラー。

message はそのまま画面に出せる日本語です。 処理の分岐には code を使ってください。

5.エンドポイント

GET/api/v1/shopread でも可

店舗情報を取得する

APIキーに紐づく店舗の基本情報・受付設定・営業時間・臨時休業日を返します。

応答の例

{
  "id": "clx1shop00001",
  "slug": "garoop-omiyage",
  "name": "ガループ物産 京都駅前店",
  "kind": "souvenir",
  "accepting": true,
  "slotIntervalMin": 60,
  "leadTimeMin": 720,
  "maxDaysAhead": 30,
  "slotCapacity": 40,
  "maxItemsPerOrder": 30,
  "businessHours": [
    { "weekday": 0, "openTime": "09:00", "closeTime": "20:00", "closed": false }
  ],
  "closedDates": [{ "date": "2027-01-01", "reason": "元日" }]
}
GET/api/v1/availabilityread でも可

受取枠の空き状況を取得する

公開ページと同じ計算(営業時間・定休日・臨時休業日・リードタイム・枠あたりの上限)で、受取可能な日付と時間枠を返します。remaining が null のときは枠の上限を設けていません。

パラメータ

fromstringこの日以降に絞る(JST・YYYY-MM-DD)。
tostringこの日以前に絞る(JST・YYYY-MM-DD)。
openOnlybooleantrue なら、選べる枠が1つ以上ある日だけを返します。指定できる値: true / false

応答の例

{
  "accepting": true,
  "slotIntervalMin": 60,
  "leadTimeMin": 720,
  "slotCapacity": 40,
  "data": [
    {
      "date": "2026-09-01",
      "weekday": 2,
      "closed": false,
      "closedReason": null,
      "hasOpenSlot": true,
      "slots": [
        { "time": "09:00", "remaining": 40, "disabled": false },
        { "time": "10:00", "remaining": 38, "disabled": false }
      ]
    }
  ]
}
GET/api/v1/categoriesread でも可

商品カテゴリの一覧

並び順の昇順で返します。

応答の例

{
  "data": [
    { "id": "clx1category001", "name": "銘菓", "sortOrder": 0,
      "createdAt": "2026-08-26T00:00:00.000Z", "updatedAt": "2026-08-26T00:00:00.000Z" }
  ]
}
GET/api/v1/optionsread でも可

オプション(ラッピング等)の一覧

オプショングループと、その選択肢を返します。selectType は single(1つだけ)または multi(いくつでも)です。

応答の例

{
  "data": [
    {
      "id": "clx1group0001",
      "name": "ラッピング",
      "description": "贈りもの用の包装をお選びいただけます。",
      "selectType": "single",
      "required": true,
      "sortOrder": 0,
      "choices": [
        { "id": "clx1choice001", "name": "掛け紙(無料)", "priceDelta": 0, "sortOrder": 1, "available": true },
        { "id": "clx1choice002", "name": "化粧箱入り", "priceDelta": 330, "sortOrder": 2, "available": true }
      ]
    }
  ]
}
GET/api/v1/productsread でも可

商品の一覧

絞り込みとページングに対応しています。

パラメータ

qstring商品名・SKU の部分一致(大文字小文字を区別しません)。
categoryIdstringカテゴリIDで絞り込みます。
availableboolean公開中(true)/非公開(false)で絞り込みます。指定できる値: true / false
limitinteger1回に返す件数(1〜200)。既定値: 50
offsetinteger読み飛ばす件数。ページングに使います。既定値: 0

応答の例

{
  "data": [{
    "id": "clx1product0001",
    "sku": "OMI-001",
    "name": "抹茶生八つ橋 15個入",
    "description": "宇治抹茶をたっぷり使った定番の生八つ橋。",
    "price": 980,
    "imageUrl": "https://example.com/yatsuhashi.jpg",
    "categoryId": "clx1category001",
    "available": true,
    "sortOrder": 0,
    "maxPerOrder": 0,
    "stock": null,
    "optionGroupIds": ["clx1group0001", "clx1group0002"],
    "createdAt": "2026-08-26T00:00:00.000Z",
    "updatedAt": "2026-08-26T00:00:00.000Z"
  }],
  "pagination": { "total": 7, "limit": 50, "offset": 0, "hasMore": false }
}
POST/api/v1/productswrite キーが必要

商品を登録する

sku を指定した場合、店舗内で重複していると 409 を返します。categoryId と optionGroupIds は同じ店舗のものだけ指定できます。

リクエストボディ(JSON)

name必須string商品名(120文字まで)。
price必須integer税込単価(円)。
skustring | null商品コード。店舗内で一意。
descriptionstring | null説明(500文字まで)。
imageUrlstring | null画像URL(http/https)。
categoryIdstring | nullカテゴリID。
availableboolean公開するか。既定 true。
sortOrderinteger並び順。小さいほど先。既定 0。
maxPerOrderinteger1予約あたりの上限。0 で無制限。
stockinteger | null在庫数。null で在庫管理しない。
optionGroupIdsstring[]この商品で使うオプショングループのID。

応答の例

{
  "id": "clx1product0001",
  "sku": "OMI-001",
  "name": "抹茶生八つ橋 15個入",
  "description": "宇治抹茶をたっぷり使った定番の生八つ橋。",
  "price": 980,
  "imageUrl": "https://example.com/yatsuhashi.jpg",
  "categoryId": "clx1category001",
  "available": true,
  "sortOrder": 0,
  "maxPerOrder": 0,
  "stock": null,
  "optionGroupIds": ["clx1group0001", "clx1group0002"],
  "createdAt": "2026-08-26T00:00:00.000Z",
  "updatedAt": "2026-08-26T00:00:00.000Z"
}
GET/api/v1/products/{id}read でも可

商品を1件取得する

見つからない場合は 404 を返します。

パラメータ

id必須string商品ID。

応答の例

{
  "id": "clx1product0001",
  "sku": "OMI-001",
  "name": "抹茶生八つ橋 15個入",
  "description": "宇治抹茶をたっぷり使った定番の生八つ橋。",
  "price": 980,
  "imageUrl": "https://example.com/yatsuhashi.jpg",
  "categoryId": "clx1category001",
  "available": true,
  "sortOrder": 0,
  "maxPerOrder": 0,
  "stock": null,
  "optionGroupIds": ["clx1group0001", "clx1group0002"],
  "createdAt": "2026-08-26T00:00:00.000Z",
  "updatedAt": "2026-08-26T00:00:00.000Z"
}
PATCH/api/v1/products/{id}write キーが必要

商品を更新する

指定した項目だけを変更します。optionGroupIds を指定した場合はその内容で置き換え、指定しなければ現状のままです。

パラメータ

id必須string商品ID。

リクエストボディ(JSON)

namestring商品名。
priceinteger税込単価(円)。
stockinteger | null在庫数。
availableboolean公開するか。
…-そのほか、登録時と同じ項目を指定できます。

応答の例

{
  "id": "clx1product0001",
  "sku": "OMI-001",
  "name": "抹茶生八つ橋 15個入",
  "description": "宇治抹茶をたっぷり使った定番の生八つ橋。",
  "price": 980,
  "imageUrl": "https://example.com/yatsuhashi.jpg",
  "categoryId": "clx1category001",
  "available": true,
  "sortOrder": 0,
  "maxPerOrder": 0,
  "stock": null,
  "optionGroupIds": ["clx1group0001", "clx1group0002"],
  "createdAt": "2026-08-26T00:00:00.000Z",
  "updatedAt": "2026-08-26T00:00:00.000Z"
}
DELETE/api/v1/products/{id}write キーが必要

商品を削除する

過去の予約明細は商品名を控えているため、削除しても受注履歴は残ります。

パラメータ

id必須string商品ID。

応答の例

{ "deleted": true, "id": "clx1product0001" }
GET/api/v1/reservationsread でも可

予約の一覧

受取日時の早い順に返します。status を省略すると、キャンセル以外(active)だけが対象です。

パラメータ

datestring受取日ちょうど1日ぶん(JST・YYYY-MM-DD)。from / to より優先されます。
fromstring受取日の開始(JST・両端を含む)。
tostring受取日の終了(JST・両端を含む)。
statusstringステータス。pending(受付済) / confirmed(確定) / ready(準備完了) / completed(受渡済) / canceled(キャンセル)。active(キャンセル以外・既定)/ all も指定できます。指定できる値: pending / confirmed / ready / completed / canceled / active / all
codestring受付番号での完全一致。
limitinteger1回に返す件数(1〜200)。既定値: 50
offsetinteger読み飛ばす件数。ページングに使います。既定値: 0

応答の例

{
  "data": [{
    "id": "clx1reservation01",
    "code": "387169",
    "status": "pending",
    "customerName": "山田 太郎",
    "customerPhone": "090-1234-5678",
    "customerEmail": null,
    "pickupAt": "2026-08-27T00:00:00.000Z",
    "pickupDate": "2026-08-27",
    "pickupTime": "09:00",
    "total": 4300,
    "totalQty": 3,
    "note": "のし名入れ: 山下",
    "items": [
      {
        "id": "clx1item0001",
        "productId": "clx1product0001",
        "label": "抹茶生八つ橋 15個入",
        "options": "ラッピング: ギフト包装(リボン付き)(+¥550) / のし: 御中元",
        "unitPrice": 1530,
        "qty": 2,
        "amount": 3060
      }
    ],
    "createdAt": "2026-08-26T01:23:45.000Z",
    "updatedAt": "2026-08-26T01:23:45.000Z"
  }],
  "pagination": { "total": 1, "limit": 50, "offset": 0, "hasMore": false }
}
GET/api/v1/reservations/{idOrCode}read でも可

予約を1件取得する

予約ID・受付番号(6桁)のどちらでも引けます。店頭のPOSからは受付番号で照会できます。

パラメータ

idOrCode必須string予約ID または 受付番号。

応答の例

{
  "id": "clx1reservation01",
  "code": "387169",
  "status": "pending",
  "customerName": "山田 太郎",
  "customerPhone": "090-1234-5678",
  "customerEmail": null,
  "pickupAt": "2026-08-27T00:00:00.000Z",
  "pickupDate": "2026-08-27",
  "pickupTime": "09:00",
  "total": 4300,
  "totalQty": 3,
  "note": "のし名入れ: 山下",
  "items": [
    {
      "id": "clx1item0001",
      "productId": "clx1product0001",
      "label": "抹茶生八つ橋 15個入",
      "options": "ラッピング: ギフト包装(リボン付き)(+¥550) / のし: 御中元",
      "unitPrice": 1530,
      "qty": 2,
      "amount": 3060
    }
  ],
  "createdAt": "2026-08-26T01:23:45.000Z",
  "updatedAt": "2026-08-26T01:23:45.000Z"
}
PATCH/api/v1/reservations/{idOrCode}write キーが必要

予約のステータスを変更する

管理画面と同じ処理を通ります。canceled にすると在庫管理中の商品の在庫が戻り、canceled から戻すと再度引き当てます。在庫が足りず引き当て直せない場合は 409 を返します。

パラメータ

idOrCode必須string予約ID または 受付番号。

リクエストボディ(JSON)

status必須stringpending(受付済) / confirmed(確定) / ready(準備完了) / completed(受渡済) / canceled(キャンセル) のいずれか。

応答の例

{
  "id": "clx1reservation01",
  "code": "387169",
  "status": "pending",
  "customerName": "山田 太郎",
  "customerPhone": "090-1234-5678",
  "customerEmail": null,
  "pickupAt": "2026-08-27T00:00:00.000Z",
  "pickupDate": "2026-08-27",
  "pickupTime": "09:00",
  "total": 4300,
  "totalQty": 3,
  "note": "のし名入れ: 山下",
  "items": [
    {
      "id": "clx1item0001",
      "productId": "clx1product0001",
      "label": "抹茶生八つ橋 15個入",
      "options": "ラッピング: ギフト包装(リボン付き)(+¥550) / のし: 御中元",
      "unitPrice": 1530,
      "qty": 2,
      "amount": 3060
    }
  ],
  "createdAt": "2026-08-26T01:23:45.000Z",
  "updatedAt": "2026-08-26T01:23:45.000Z"
}

6.よくある使い方

当日の受取予定を取り込む

curl -H "Authorization: Bearer $RESERVEG_KEY" \
  "https://example.com/api/v1/reservations?date=2026-09-01"

status を省略しているので、キャンセル以外の予約が受取時刻の早い順に返ります。 件数が50件を超える場合は pagination.hasMore を見て offset を進めてください。

店頭で受け渡したことを記録する

curl -X PATCH -H "Authorization: Bearer $RESERVEG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"completed"}' \
  "https://example.com/api/v1/reservations/387169"

受付番号でそのまま指定できるので、店頭で読み上げてもらった番号をPOSに入力するだけで済みます。

在庫を基幹システムから同期する

# 1. SKU で商品を探す
curl -H "Authorization: Bearer $RESERVEG_KEY" \
  "https://example.com/api/v1/products?q=OMI-001"

# 2. 見つかったIDの在庫を更新する
curl -X PATCH -H "Authorization: Bearer $RESERVEG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stock": 24}' \
  "https://example.com/api/v1/products/clx1product0001"
在庫は予約が入るたびに自動で減ります。基幹システムから定期的に上書きする場合は、 その間に入った予約ぶんが打ち消されないよう、更新の間隔と基準時刻の扱いにご注意ください。

空いている枠を自社サイトに表示する

curl -H "Authorization: Bearer $RESERVEG_KEY" \
  "https://example.com/api/v1/availability?openOnly=true&to=2026-09-07"

予約ページと同じ計算結果が返るので、表示がずれることはありません。 実際の予約は予約ページ(/s/店舗のURL)へ誘導してください。

7.機械可読の仕様(OpenAPI)

OpenAPI 3.1 の定義を /api/v1/openapi.json で配信しています(認証不要)。Swagger UI・Postman・各言語のコード生成に そのまま読み込めます。

# Postman: File → Import → Link に上記URLを貼る
# openapi-generator でクライアントを作る例
npx @openapitools/openapi-generator-cli generate \
  -i https://example.com/api/v1/openapi.json \
  -g typescript-fetch -o ./reserveg-client

この仕様書と openapi.json は同じ定義(src/lib/api/spec.ts)から 生成しているため、内容が食い違うことはありません。