公開API v1→v2 マイグレーションガイド

はじめに

このドキュメントは、ZAICO公開API v1を利用しているエンジニアが、v2へ移行する際に必要な情報をまとめたものです。

v2では以下の主要な変更が行われています:

対象読者

公開APIを利用するクライアントアプリケーションの開発者

関連ドキュメント


1. 破壊的変更の一覧

1.1 URLパス構造の変更

v1ではリソースに直接アクセスしていましたが、v2ではcompany_id(拠点ID)によるスコープが必須になりました。

バージョン パス構造
v1 /api/v1/{resource}
v2 /api/v2/orgs/companies/{company_id}/{resource}
# v1
GET /api/v1/inventories

# v2
GET /api/v2/orgs/companies/123/inventories

v2では、すべてのリソース操作でURLにcompany_idを含める必要があります。company_idは認証ユーザーがアクセス可能な拠点のIDです。

1.2 レスポンス構造の変更(エンベロープ形式)

v1では配列やオブジェクトを直接返していましたが、v2ではエンベロープ形式に統一されました。

コレクション(一覧)レスポンス:

// v1: 配列を直接返却
[
  { "id": 1, "title": "在庫A" },
  { "id": 2, "title": "在庫B" }
]

// v2: エンベロープ形式
{
  "data": [
    { "id": 1, "title": "在庫A" },
    { "id": 2, "title": "在庫B" }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 100,
    "total_count": 2,
    "total_pages": 1
  }
}

単一リソースレスポンス:

// v1: オブジェクトを直接返却
{ "id": 1, "title": "在庫A" }

// v2: エンベロープ形式
{
  "data": { "id": 1, "title": "在庫A" }
}

1.3 ページネーションの変更

項目 v1 v2
方式 HTTPヘッダ レスポンスボディ
全件数 Total-Count ヘッダ pagination.total_count
ページリンク Link ヘッダ(RFC 5988) pagination.current_page / pagination.total_pages
デフォルト/最大ページサイズ 1000件(固定) エンドポイントによって異なる3.4 ページネーション仕様(エンドポイント別) を参照)
ページネーション形式 オフセット方式(ページ番号) オフセット方式が基本。inventory_histories のみトークンベース

注意: v1 は全エンドポイント共通で Total-Count / Link ヘッダ + 1000件固定でしたが、v2 は エンドポイントごとに DEFAULT / MAX の per_page が異なります。一覧取得の挙動を実装する際は 3.4 節を必ず確認してください。

v1のページネーション(HTTPヘッダ):

HTTP/1.1 200 OK
Total-Count: 2500
Link: <https://web.zaico.co.jp/api/v1/inventories?page=1>; rel="first",
      <https://web.zaico.co.jp/api/v1/inventories?page=2>; rel="next",
      <https://web.zaico.co.jp/api/v1/inventories?page=3>; rel="last"

v2のページネーション(レスポンスボディ):

{
  "data": [...],
  "pagination": {
    "current_page": 1,
    "per_page": 100,
    "total_count": 2500,
    "total_pages": 25
  }
}

1.4 エラーレスポンス形式の変更(RFC 7807)

v2ではエラーレスポンスがRFC 7807 Problem Details形式に変更されました。

項目 v1 v2
Content-Type application/json application/problem+json
フィールド code, status, message title, status, detail
// v1
{
  "code": 403,
  "status": "error",
  "message": "Could not access API. Please Check Token or enabled API function."
}

// v2
{
  "title": "Forbidden",
  "status": 403,
  "detail": "編集権限がありません"
}

1.5 認証方式の変更

項目 v1 v2
認証スキーム Bearer / Token 両対応 Bearer のみ
対応トークン 拠点向けAPIトークン(従来) 拠点向けAPIトークン(従来) / 組織向けAPIトークン(新プラン)
組織向けAPIトークン(新プラン) 非対応 対応(新プランのみ)

各APIトークン種別の v1/v2 ごとの呼び出し可否は 3.3 APIトークン v1/v2 互換性マトリクス を参照してください。

v2ではTokenスキームは廃止されました。すべてのリクエストでBearerスキームを使用してください。

# v1(どちらも利用可能)
Authorization: Bearer {token}
Authorization: Token {token}

# v2(Bearerのみ)
Authorization: Bearer {token}

1.6 フィールド形式の変更

一部のフィールドの型や形式が変更されています。

フィールド v1 v2
optional_attributes 配列 [{"name": "色", "value": "赤"}] Hash {"色": "赤"}
is_quantity_auto_conversion_by_unit 文字列 "0" / "1" boolean false / true
checked_at ISO 8601 datetime "2025-01-15T00:00:00+09:00" ISO 8601 date "2025-01-15"
日時フィールド全般 秒精度 ミリ秒精度(.000

2. エンドポイント対応表

2.1 v1→v2対応エンドポイント

v2のベースパス: /api/v2/orgs/companies/{company_id}

機能 メソッド v1 パス v2 パス
在庫
在庫一覧 GET /api/v1/inventories {base}/inventories
在庫詳細 GET /api/v1/inventories/:id {base}/inventories/:id
在庫作成 POST /api/v1/inventories {base}/inventories
在庫更新 PUT/PATCH /api/v1/inventories/:id {base}/inventories/:id
在庫削除 DELETE /api/v1/inventories/:id {base}/inventories/:id
ポイントインタイム GET /api/v1/inventories/point_in_time {base}/inventories/point_in_time
在庫添付ファイル
添付ファイル一覧 GET /api/v1/inventory_attachments/:inventory_id {base}/inventories/:inventory_id/attachments
添付ファイル作成 POST /api/v1/inventory_attachments/:inventory_id {base}/inventories/:inventory_id/attachments
添付ファイル削除 DELETE /api/v1/inventory_attachments/:inventory_id/:id {base}/inventories/:inventory_id/attachments/:id
在庫セット
在庫セット一覧 GET /api/v1/inventories_sets {base}/inventories_sets
在庫セット詳細 GET /api/v1/inventories_sets/:id {base}/inventories_sets/:id
在庫セット作成 POST /api/v1/inventories_sets {base}/inventories_sets
在庫セット更新 PUT/PATCH /api/v1/inventories_sets/:id {base}/inventories_sets/:id
在庫セット削除 DELETE /api/v1/inventories_sets/:id {base}/inventories_sets/:id
入庫(購入)
入庫一覧 GET /api/v1/purchases {base}/purchases
入庫詳細 GET /api/v1/purchases/:id {base}/purchases/:id
入庫作成 POST /api/v1/purchases {base}/purchases
入庫更新 PUT/PATCH /api/v1/purchases/:id {base}/purchases/:id
入庫削除 DELETE /api/v1/purchases/:id {base}/purchases/:id
出庫(梱包伝票)
出庫一覧 GET /api/v1/packing_slips {base}/packing_slips
出庫詳細 GET /api/v1/packing_slips/:id {base}/packing_slips/:id
出庫作成 POST /api/v1/packing_slips {base}/packing_slips
出庫更新 PUT/PATCH /api/v1/packing_slips/:id {base}/packing_slips/:id
出庫削除 DELETE /api/v1/packing_slips/:id {base}/packing_slips/:id
配送
配送一覧 GET /api/v1/deliveries {base}/deliveries
配送削除 DELETE /api/v1/deliveries/:id {base}/deliveries/:id
顧客
顧客一覧 GET /api/v1/customers {base}/customers
顧客詳細 GET - {base}/customers/:id
顧客作成 POST /api/v1/customers {base}/customers
顧客更新 PUT/PATCH /api/v1/customers/:id {base}/customers/:id
顧客削除 DELETE /api/v1/customers/:id {base}/customers/:id
その他
在庫属性一覧 GET /api/v1/inventory_attributes {base}/inventory_attributes
在庫履歴一覧 GET /api/v1/inventory_histories {base}/inventory_histories
在庫グループアイテム一覧 GET /api/v1/inventory_group_items {base}/inventory_group_items
在庫グループアイテム詳細 GET /api/v1/inventory_group_items/:id {base}/inventory_group_items/:id
発注点更新 PUT /api/v1/inventory_group_items/:id/order_points {base}/inventory_group_items/:id/order_points
発注点警告ON POST /api/v1/inventory_group_items/:id/order_points/warning_on {base}/inventory_group_items/:id/order_points/warning_on
発注点警告OFF POST /api/v1/inventory_group_items/:id/order_points/warning_off {base}/inventory_group_items/:id/order_points/warning_off
プロフィール GET /api/v1/profile/me /api/v2/orgs/profile/me

2.2 v2で新規追加されたエンドポイント

メソッド パス 説明
GET /api/v2/orgs/companies 拠点一覧(新プラン)
GET /api/v2/orgs/subscriptions/current サブスクリプション情報
GET/POST/PUT/DELETE /api/v2/orgs/item_masters 組織品目マスタ(新プラン)
GET/DELETE {base}/purchase_items 購入アイテム
GET/POST/PUT/DELETE {base}/inventories/:inventory_id/inventory_variants バリアント(一覧・詳細・作成・更新・削除)
GET {base}/shipping_clients 配送業者一覧
GET/POST/PUT/DELETE {base}/categories カテゴリ(一覧・作成・更新・削除)
GET/POST/PUT/DELETE {base}/sales_orders/orders 受注(一覧・詳細・作成・更新・削除)
GET/POST/PUT/DELETE {base}/sales_orders/item_masters 受注商品マスタ(一覧・詳細・作成・更新・削除)
GET/POST/PUT/DELETE {base}/purchase_orders/orders 発注(一覧・詳細・作成・更新・削除)
POST {base}/zaicon/weight ZAICON 重量データ登録
GET {base}/zaicon/repeater/firmware/check ZAICON ファームウェア更新チェック
GET {base}/zaicon/repeater/firmware ZAICON ファームウェア取得
GET {base}/zaicon/repeater/firmwares ZAICON ファームウェア一覧

3. 認証方式の移行ガイド

3.1 拠点向けAPIトークン(従来)

拠点向けAPIトークン(従来)は v1 / v2 のどちらでも利用できます。

# v1/v2 共通
curl -H "Authorization: Bearer xzxu-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  https://web.zaico.co.jp/api/v2/orgs/companies/123/inventories

拠点向けAPIトークン(従来)で認証した場合、そのユーザーが所属する拠点のみアクセスできます(旧プラン)。

3.2 新プラン/旧プランの違い

項目 旧プラン 新プラン(組織プラン)
認証トークン 拠点向けAPIトークン(従来) 組織向けAPIトークン(新プラン) / 拠点向けAPIトークン(従来)
アクセス可能な拠点 1拠点のみ org 配下の複数拠点
company_id スコープ 自身の company_id のみ org 配下の任意の company_id
拠点一覧API 利用不可 GET /api/v2/orgs/companies で一覧取得可能

旧プランの場合:

新プランの場合:

3.3 APIトークン v1/v2 互換性マトリクス

APIトークン種別ごとに、v1/v2 の呼び出し可否が異なります。

APIトークン種別 v1 v2 備考
拠点向けAPIトークン(従来) 新旧両プランで利用可。v2 では自身の拠点 company_id のみアクセス可
組織向けAPIトークン(新プラン) v2 専用。v1 では認証パスが存在しないため呼び出し不可

ポイント:

3.4 ページネーション仕様(エンドポイント別)

v2 のページネーションは エンドポイントごとに per_page のデフォルト値(DEFAULT)と最大値(MAX)が異なります。v1 のように全エンドポイント共通で「デフォルト 1000件・固定」ではない点に注意してください。

オフセット方式(ページ番号)

オフセット方式のレスポンスは pagination.current_page / per_page / total_count / total_pages を返します。

エンドポイント DEFAULT MAX
inventories / inventory_variants 100 1000
inventories_sets / inventory_attributes / inventory_group_items / inventory_attachments / categories / customers / deliveries / packing_slips / purchases / purchase_items / shipping_clients 100 100
inventories/point_in_time 100 100
companies (index、固定値) 20
sales_orders/orders / purchase_orders/orders 20 50
sales_orders/item_masters 20 上限なし

レスポンス例(オフセット方式):

{
  "data": [...],
  "pagination": {
    "current_page": 1,
    "per_page": 100,
    "total_count": 2500,
    "total_pages": 25
  }
}

per_page パラメータに MAX を超える値を指定した場合は MAX 値にクランプされ、未指定または 0 以下の場合は DEFAULT 値が使われます。

トークンベース方式(inventory_histories のみ)

inventory_histories は DynamoDB をデータソースとするため、トークンベースのページネーションを採用しています。current_page / total_count / total_pages は返却されず、代わりに次ページ取得用のトークンが next_page_token として返ります。

エンドポイント DEFAULT MAX
inventory_histories 50 100

レスポンス例(トークンベース):

{
  "data": [...],
  "pagination": {
    "per_page": 50,
    "next_page_token": "eyJpZCI6IjEyM..."
  }
}

次ページ取得の方法:

レスポンスに含まれる next_page_token を、次のリクエストの next_page_token クエリパラメータに指定します。next_page_tokennull の場合は次のページが存在しないことを意味します。

# 1ページ目
curl -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventory_histories?per_page=50"

# 2ページ目(next_page_token を指定)
curl -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventory_histories?per_page=50&next_page_token=eyJpZCI6IjEyM..."

4. リクエスト/レスポンスの具体例(Before/After)

4.1 在庫一覧取得(GET)

v1:

curl -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v1/inventories?page=1"

レスポンス:

// HTTP/1.1 200 OK
// Total-Count: 150
// Link: <...?page=1>; rel="first", <...?page=2>; rel="last"

[
  {
    "id": 1,
    "title": "テスト在庫",
    "quantity": "10.0",
    "logical_quantity": "10.0",
    "unit": "個",
    "category": "果物",
    "categories": ["果物"],
    "state": "出荷待ち",
    "place": "倉庫A",
    "etc": "備考テキスト",
    "code": "INV-001",
    "item_image": { "url": null },
    "stocktake_attributes": {
      "checked_at": "2025-01-15T00:00:00+09:00",
      "stocktake_difference": "5.0"
    },
    "optional_attributes": [
      { "name": "色", "value": "赤" },
      { "name": "サイズ", "value": "M" }
    ],
    "quantity_management_attributes": {
      "order_point_quantity": "80.0"
    },
    "created_at": "2025-01-01T00:00:00+09:00",
    "updated_at": "2025-06-15T10:30:00+09:00",
    "update_date": "2025-06-15T10:30:00+09:00",
    "create_user_name": "田中太郎",
    "update_user_name": "田中太郎",
    "user_group": "基本グループ",
    "is_quantity_auto_conversion_by_unit": "1",
    "quantity_auto_conversion_by_unit_name": "箱",
    "quantity_auto_conversion_by_unit_factor": "12.0"
  }
]

v2:

curl -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventories?page=1&per_page=100"

レスポンス:

{
  "data": [
    {
      "id": 1,
      "title": "テスト在庫",
      "quantity": "10.0",
      "logical_quantity": "10.0",
      "unit": "個",
      "category": "果物",
      "categories": ["果物"],
      "state": "出荷待ち",
      "place": "倉庫A",
      "etc": "備考テキスト",
      "code": "INV-001",
      "group_tag": null,
      "item_image": { "url": null },
      "stocktake_attributes": {
        "checked_at": "2025-01-15",
        "stocktake_difference": "5.0"
      },
      "optional_attributes": {
        "色": "赤",
        "サイズ": "M"
      },
      "quantity_management_attributes": {
        "order_point_quantity": "80.0"
      },
      "created_at": "2025-01-01T00:00:00.000+09:00",
      "updated_at": "2025-06-15T10:30:00.000+09:00",
      "update_date": "2025-06-15T10:30:00.000+09:00",
      "create_user_name": "田中太郎",
      "update_user_name": "田中太郎",
      "user_group": "基本グループ",
      "is_quantity_auto_conversion_by_unit": true,
      "quantity_auto_conversion_by_unit_name": "箱",
      "quantity_auto_conversion_by_unit_factor": "12.0",
      "org_item_master": null,
      "variant_setting": {
        "enabled": false
      }
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 100,
    "total_count": 150,
    "total_pages": 2
  }
}

主な違い:

4.2 在庫詳細取得(GET)

v1:

curl -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v1/inventories/1"

レスポンス:

{
  "id": 1,
  "title": "テスト在庫",
  "quantity": "10.0",
  "..."
}

v2:

curl -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventories/1"

レスポンス:

{
  "data": {
    "id": 1,
    "title": "テスト在庫",
    "quantity": "10.0",
    "..."
  }
}

主な違い:

4.3 在庫作成(POST)

v1:

curl -X POST \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "新しい在庫",
    "quantity": "100",
    "unit": "個",
    "category": "電子部品",
    "place": "倉庫B",
    "code": "INV-002"
  }' \
  "https://web.zaico.co.jp/api/v1/inventories"

v2:

curl -X POST \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "新しい在庫",
    "quantity": "100",
    "unit": "個",
    "category": "電子部品",
    "place": "倉庫B",
    "code": "INV-002"
  }' \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventories"

主な違い:

4.4 在庫更新(PUT)

v1:

curl -X PUT \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "更新された在庫名",
    "quantity": "200"
  }' \
  "https://web.zaico.co.jp/api/v1/inventories/1"

v2:

curl -X PUT \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "更新された在庫名",
    "quantity": "200"
  }' \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventories/1"

4.5 在庫削除(DELETE)

v1:

curl -X DELETE \
  -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v1/inventories/1"

v2:

curl -X DELETE \
  -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventories/1"

v2 のレスポンス(DELETE 全般):

HTTP/1.1 204 No Content

v2 の DELETE 系エンドポイント(destroy アクション)は、削除成功時に 204 No Content を返し、レスポンスボディは空 です(data エンベロープも返却しません)。

v1 ではエンドポイントによって 200 OK で削除結果オブジェクトを返すケースがありましたが、v2 では削除成功時は一貫して 204 No Content で body なしです。クライアント側で JSON パースを試みているとエラーになる可能性があるため、ステータスコードのみで成否を判定してください。

4.6 エラーレスポンス例

認証エラー(401 Unauthorized):

// v1
{
  "code": 401,
  "status": "error",
  "message": "Could not access API. Please Check Token or enabled API function."
}

// v2(Content-Type: application/problem+json)
{
  "title": "Unauthorized",
  "status": 401,
  "detail": "トークンが無効または未指定です"
}

権限エラー(403 Forbidden):

// v1
{
  "code": 403,
  "status": "error",
  "message": "Could not access API. Please check your account permission."
}

// v2(Content-Type: application/problem+json)
{
  "title": "Forbidden",
  "status": 403,
  "detail": "編集権限がありません"
}

リソース未検出(404 Not Found):

// v1
{
  "code": 404,
  "status": "error",
  "message": "Inventory not found."
}

// v2(Content-Type: application/problem+json)
{
  "title": "Not Found",
  "status": 404,
  "detail": "Inventory が見つかりません"
}

バリデーションエラー(v1: 422 → v2: 400):

注意: バリデーションエラーのHTTPステータスコードがv1の422 Unprocessable Entityからv2の400 Bad Requestに変更されています。ステータスコードでエラーを分岐しているクライアントは修正が必要です。

// v1
{
  "code": 422,
  "status": "error",
  "message": "Title can't be blank"
}

// v2(Content-Type: application/problem+json)
{
  "title": "Bad Request",
  "status": 400,
  "detail": "タイトルを入力してください"
}

5. エラーハンドリングの移行ガイド

5.1 エラーレスポンスフィールド対応表

v1フィールド v2フィールド 説明
code status HTTPステータスコード(整数)
status - v2には対応フィールドなし(v1では常に "error"
message detail エラーの詳細メッセージ(オプション)
- title v2で追加。HTTPステータスのテキスト表現(例: "Not Found"

5.2 HTTPステータスコード一覧

ステータス title 発生条件
400 Bad Request パラメータ不足、バリデーションエラー(v1では422で返していたケースを含む)
401 Unauthorized トークン無効、トークン未指定
403 Forbidden 権限不足、company_idアクセス不可
404 Not Found リソース未検出、company_id不正(旧プラン)
500 Internal Server Error サーバー内部エラー

5.3 エラーハンドリングのコード例

v1からv2へのエラーハンドリング移行の疑似コード例:

// v1のエラーハンドリング
function handleV1Error(response) {
  const error = response.data;
  console.error(`Error ${error.code}: ${error.message}`);
}

// v2のエラーハンドリング
function handleV2Error(response) {
  // Content-Typeが application/problem+json であることを確認
  const error = response.data;
  console.error(`${error.title} (${error.status}): ${error.detail || ''}`);
}
# v1のエラーハンドリング
def handle_v1_error(response):
    error = response.json()
    print(f"Error {error['code']}: {error['message']}")

# v2のエラーハンドリング
def handle_v2_error(response):
    error = response.json()
    print(f"{error['title']} ({error['status']}): {error.get('detail', '')}")

6. その他の変更点

6.1 デフォルトページサイズの変更

v1 では全エンドポイント共通でデフォルト 1000件(固定、変更不可)でしたが、v2 では per_page パラメータで指定可能になりました。ただしデフォルト値・最大値はエンドポイントごとに異なります

詳細は 3.4 ページネーション仕様(エンドポイント別) を参照してください。

# v2: per_page パラメータで1ページあたりの件数を指定(在庫一覧の場合は最大1000件)
curl -H "Authorization: Bearer {token}" \
  "https://web.zaico.co.jp/api/v2/orgs/companies/123/inventories?per_page=500"

6.2 optional_attributesの形式変更

v1(配列形式):

"optional_attributes": [
  { "name": "色", "value": "赤" },
  { "name": "サイズ", "value": "M" }
]

v2(Hashオブジェクト形式):

"optional_attributes": {
  "色": "赤",
  "サイズ": "M"
}

v1ではnameとvalueのペアの配列でしたが、v2ではキーバリューのHashオブジェクトに変更されました。

6.3 boolean/日付フィールドの形式変更

is_quantity_auto_conversion_by_unit:

// v1: 文字列
"is_quantity_auto_conversion_by_unit": "1"  // または "0"

// v2: boolean
"is_quantity_auto_conversion_by_unit": true  // または false

checked_at(棚卸日):

// v1: ISO 8601 datetime
"checked_at": "2025-01-15T00:00:00+09:00"

// v2: ISO 8601 date(日付のみ)
"checked_at": "2025-01-15"

6.4 v2で追加されたパラメータ・レスポンスフィールド

v2では以下のパラメータ・フィールドが新規追加されています。

在庫(Inventories):

バリアント(InventoryVariants):

入庫(Purchases):

出庫(PackingSlips):

配送(Deliveries):

6.5 v2で強化されたプランチェック

v2ではプラン別の機能制限チェックが強化されています。v1ではプランチェックが不足していた一部パラメータについて、v2では適切に制御されます。

パラメータ 必要な機能
stocktake_attributes 棚卸機能(stocktake
quantity_management_attributes 発注点機能(order_point
optional_attributes 追加項目機能(inventory_optional_attribute
単位換算パラメータ 単位換算機能(quantity_auto_conversion_by_unit
variants バリエーション機能(inventory_variant
shipping_instruction 出荷指示機能(shipping_order)またはビジネス管理者機能(business_admin

契約プランで該当機能が無効な場合、これらのパラメータは送信してもサイレントに無視されます。


移行チェックリスト

v1からv2への移行作業の完了確認に使用してください。