Ai-Sns.io Kitting API リファレンス
← トップへ

Ai-Sns.io Kitting — REST API

キッティングセンター管制SaaS の全 REST エンドポイント。応答は原則 JSON。

ベース URL: https://kit-agent.ai-sns.io | 発行: Freeborn Inc.

285エンドポイント
115GET
162POST
8PUT
41ドメイン

規約・認証

成功は {ok:true,...}、失敗は {ok:false,error}。認証区分: 公開 admin subadmin token

POST /api/admin/login      { "password": "..." }            -> { ok, token }
POST /api/subadmin/login   { "email": "...", "password": "..." } -> { ok, token }
# 以降のリクエスト: Authorization: Bearer <token>
# 顧客ポータル (GET /api/portal/view, POST /api/portal/inquiry) はセッションではなく
# POST /api/portal/issue が発行するポータルトークンで認証します: /api/portal/view?t=<token>
# 無効・期限切れ・失効したトークンは 401 {ok:false,code:"portal_link_invalid"}

ヘルスチェック

ヘルスチェック/マウント確認。

GET/api/ping公開実測 200
ヘルスチェック/マウント確認です。ok フラグ、pong として現在のエポックミリ秒、routes/ の自動マウントが機能していることを示す mounted:true を返します。
レスポンス例
{"ok":true,"pong":1784675483941,"mounted":true}
GET/api/health公開
永続化の実態を返します: durable フラグ、ストレージモード、永続バックエンドがないプロセスでの warning 文字列、store / tenant-cache / account の各カウンタ、呼び出し元について解決された tenantId。
レスポンス例
{"ok":true,"durable":true,"storage":"disk","warning":null,"store":{"mode":"disk","durable":true,"dbPathSet":true,"diskError":null,"hubConfigured":false,"pending":0,"writes":1,"flushes":1,"errors":0,"lastFlush":"2026-08-27T20:51:07.071Z","lastError":null},"tenants":{"cached":10,"dirty":0,"max":500},"accounts":{"accounts":0,"loaded":true},"tenantId":"t-…"}

メトリクス (Metrics/Alerts)

ダッシュボード指標・アラート。

GET/api/metrics/overview公開実測 200
このワークスペース自身の記録から算出する主要 KPI カード。算出できない数値は代替値やサンプル値で埋めず、次のフィールド付きで返します: computed:false reason display:"—" 比較対象の前月がない場合、deltaPct は null です。
レスポンス例
{"ok":true,"month":"2026-08","revenueForecast":{"display":"¥0.00","unit":"M","total":0,"oneTime":0,"recurring":0,"deltaPct":null,"computed":true},"mrr":{"display":"¥0","unit":"K","amount":0,"invoiceRecurring":0,"projected":null,"computed":true},"pipeline":{"display":"—","unit":"M","amount":null,"deals":0,"computed":false,"reason":"商談金額のレコードがありません"}}
GET/api/revenue/mix公開実測 200
#revChart 用の12か月分の売上構成系列(months ラベル、recurring・onetime の万円配列)。任意の ?months=N で直近 N 点に絞り込みます。
パラメータ位置型必須説明
monthsqueryinteger直近 N 点のみを返します。1..120 の範囲外は 400。既定は 12 点の全系列。
レスポンス例
{"ok":true,"months":["25/8","25/9","25/10","25/11","25/12","26/1","26/2","26/3","26/4","26/5","26/6","26/7"],"recurring":[38,40,42,46,46,48,50,50,93,93,140,140],"onetime":[22,65,18,120,34,52,88,93,318,282,60,72]}
GET/api/ops/today公開実測 200
本日の作業行(#todayList): id/time/chip/chipLabel/title/detail/status/statusColor。各項目は長さ上限で切り詰めます。
レスポンス例
{"ok":true,"ops":[{"id":"op-001","time":"09:30","chip":"c-cyan","chipLabel":"作業","title":"北斗商事 交換12台 再キッティング(Intune再登録)","detail":"担当:一条 | Zone A | チェックリスト 8/12 完了","status":"進行中","statusColor":"var(--cyan)"}]}
GET/api/alerts公開実測 200
アラート一覧(#alertList)。アラートごとのアクション(label/danger/toast)と、未対応の遅延アラート件数 lateCount を含みます。
レスポンス例
{"ok":true,"alerts":[{"id":"alert-001","label":"出荷漏れ","late":true,"ack":false,"chip":"c-red","chipLabel":"重大","what":"北斗商事 交換2台 — 予定 07/10 を超過","detail":"...","action":{"label":"対応","danger":true,"toast":"出荷漏れアラートを対応済みとして記録しました"}}],"lateCount":1}
POST/api/alert/:id/ack公開
アラートを1件対応済みにし(ack=true、acked=タイムスタンプを設定)、更新後のアラートを返します。
パラメータ位置型必須説明
idpathstring○metrics-alerts シードのアラート ID(例: 'alert-001')。不明な場合は 404 {ok:false,error:'alert not found'}。
レスポンス例
{"ok":true,"alert":{"id":"alert-001","label":"出荷漏れ","ack":true,"acked":1710000000000,...}}

端末台帳 (Devices)

IMEI単位の端末台帳 CRUD・検索・一括操作。

GET/api/devices公開実測 200
台帳コレクションの全端末を一覧します(imei をキーとする mulberry(42) 生成の178件をシード)。
レスポンス例
{"ok":true,"devices":[{"imei":"356247446539346","serial":"F2LXD73EB4","asset":"HK-26-1001","model":"iPhone 15","maker":"Apple","cust":"北斗商事","mdm":"Intune","status":"保管中","chip":"c-blue",...}],"count":178}
POST/api/device公開
部分的な入力から端末を1台作成します。imei がなければ一意の imei を新規生成し、makeDevice で既定値を補います。
パラメータ位置型必須説明
imeibodystring端末の IMEI(最大40文字)。省略時は 35+13 桁の新しい imei を生成。
modelbodystring端末モデル(最大60文字)。既定値 'iPhone 16'。iPad-* の場合は OS の既定値が切り替わります。
custbodystring顧客(最大60文字)。既定値 '社内検証機'
statusbodystringステータス(最大20文字)。chipFor でチップ色を決定。既定値 '入荷待ち'
mdmbodystringMDM プラットフォーム(最大40文字)。既定値 'Intune'。
serialbodystringシリアル(最大40文字)。既定はモデルのプレフィックス+ゼロ埋めの連番。
assetbodystring資産タグ(最大40文字)。既定値 'HK-26-<n>'。
batbodynumberバッテリー %。既定値 100(切り詰めずそのまま保存)。
notebodystring自由記述メモ(最大300文字)。
リクエスト
{"imei?":"str","model?":"str","cust?":"str","status?":"str","mdm?":"str","serial?":"str","asset?":"str","bat?":100,"...other device fields":"str"}
レスポンス例
{"ok":true,"device":{"imei":"35...","model":"iPhone 16","cust":"社内検証機","status":"入荷待ち","chip":"c-gray",...}}
POST/api/devices/bulk公開
{model,cust,mdm,status,qty} から N 台の端末を作成し、created[] 配列を返します。
パラメータ位置型必須説明
qtybodynumber○作成台数。1..1000 に丸め込み。未指定/0 -> 400。
modelbodystring作成する全端末に適用するモデル。
custbodystring作成する全端末に適用する顧客。
mdmbodystring作成する全端末に適用する MDM。
statusbodystring作成する全端末に適用するステータス。
リクエスト
{"qty":5,"model?":"iPhone 16","cust?":"北斗商事","mdm?":"Intune","status?":"保管中"}
レスポンス例
{"ok":true,"created":[{"imei":"35...","model":"iPhone 16",...}],"count":5}
POST/api/device/:imei公開
imei で指定した既存端末の項目を更新します。imei キーは変更不可、bat はそのまま渡し、その他の項目は切り詰め、status が変わると chip を再計算します。
パラメータ位置型必須説明
imeipathstring○更新する端末の IMEI(例: シード値 356247446539346)。
statusbodystring新しいステータス。chipFor によりチップ色を再計算。
batbodynumberバッテリー %(切り詰めずそのまま代入)。
notebodystringメモ(300文字で切り詰め)。その他の文字列フィールドは 120文字で切り詰め。
リクエスト
{"status?":"作業中","loc?":"B-05","user?":"藤宮 健","bat?":88,"note?":"str"}
レスポンス例
{"ok":true,"device":{"imei":"356247446539346","status":"作業中","chip":"c-cyan",...}}
POST/api/device/:imei/delete公開
imei で指定した端末を1台コレクションから削除します。
パラメータ位置型必須説明
imeipathstring○削除する端末の IMEI(例: シード値 356247446539346)。
レスポンス例
{"ok":true,"imei":"356247446539346"}

案件管理 (Jobs)

8段階の案件カード(キッティング工程)。

GET/api/jobs公開実測 200
インメモリの jobs コレクションから全ジョブ(かんばん)カードを一覧します。
レスポンス例
{"ok":true,"jobs":[{"id":"job-001","c":"東成建設","t":"PoC 20台(iPhone 16e・Intune新規)","s":0,"due":"07/22","ch":"c-blue","tag":"新規"}, ...9 cards]}
POST/api/job公開
ジョブカードを作成します。id(job-…)はサーバーが採番し、stage の既定値は 0 です。
パラメータ位置型必須説明
cbodystring顧客名/会社名(120文字で切り詰め)
tbodystringタスク/タイトル文字列(300文字で切り詰め)
sbodynumberステージ番号(0-7 に丸め込み)。有限値でない場合は 0
duebodystring期日ラベル(例: '07/22'、40文字で切り詰め)
chbodystring色/チップクラス。既定値 'c-blue'(40文字で切り詰め)
tagbodystringタグラベル(40文字で切り詰め)
リクエスト
{"c":"string","t":"string","s":0,"due":"string","ch":"c-blue","tag":"string"}
レスポンス例
{"ok":true,"job":{"id":"job-<generated>","c":"...","t":"...","s":0,"due":"...","ch":"c-blue","tag":"..."}}
POST/api/job/:id公開
既存ジョブカードの stage や各項目を更新します。指定された(null でない)項目のみ変更します。
パラメータ位置型必須説明
idpathstring○案件 ID(例: 'job-001')
cbodystring顧客名(120文字で切り詰め)。null でない場合のみ更新
tbodystringタイトル(300文字で切り詰め)。null でない場合のみ更新
sbodynumberステージ(0-7 に丸め込み)。null でない場合のみ更新
duebodystring期日ラベル(40文字で切り詰め)。null でない場合のみ更新
chbodystring色クラス(40文字で切り詰め)。null でない場合のみ更新
tagbodystringタグ(40文字で切り詰め)。null でない場合のみ更新
リクエスト
{"c":"string","t":"string","s":3,"due":"string","ch":"c-cyan","tag":"string"} (all optional)
レスポンス例
{"ok":true,"job":{"id":"job-001","c":"...","t":"...","s":3,"due":"...","ch":"...","tag":"..."}}
POST/api/job/:id/delete公開
id で指定したジョブカードを削除します。
パラメータ位置型必須説明
idpathstring○削除する案件 ID(例: 'job-005')
レスポンス例
{"ok":true,"id":"job-005"}
GET/api/inquiries要サインイン
このワークスペースのヘルプデスク問合せをすべて、問合せIDの古い順に一覧します。
レスポンス例
{"ok":true,"inquiries":[]}
POST/api/inquiry要サインイン
問合せを作成します。サーバーが次の連番の問合せIDを採番し、レコード id として使用します。
リクエスト
{"cust":"北斗商事","title":"MDM設定"}
レスポンス例
{"ok":true,"inquiry":{"status":"オープン","type":"故障","inquirerName":"","department":"","summary":"","faultyDeviceId":"","sentDeviceId":"","remarks":"","inquiryDate":"","returnDeadline":"","shipDate":"","arrivalDate":"","returnDate":"","returnReceivedDate":"","inquiryId":"00001","id":"00001"}}
POST/api/inquiry/:id要サインイン
問合せ1件の項目・ステータスを更新します。inquiryId と id は保持されます。
パラメータ位置型必須説明
idpathstring○問合せID(例: '00001')
リクエスト
{"status":"クローズ"}
レスポンス例
{"ok":true,"inquiry":{"status":"クローズ","type":"故障","inquirerName":"","department":"","summary":"","faultyDeviceId":"","sentDeviceId":"","remarks":"","inquiryDate":"","returnDeadline":"","shipDate":"","arrivalDate":"","returnDate":"","returnReceivedDate":"","inquiryId":"00001","id":"00001"}}
POST/api/inquiry/:id/delete要サインイン
問合せを1件削除します。
パラメータ位置型必須説明
idpathstring○問合せID(例: '00001')
レスポンス例
{"ok":true,"id":"00001"}

入出荷 (Shipments)

入荷・出荷・在庫ロケーション。

GET/api/shipments公開実測 200
IN/OUT ボードの全入出荷(入出荷)を一覧します。
レスポンス例
{"ok":true,"shipments":[{"id":"SHP-0001","late":true,"created":1784673357631,"updated":1784673357631,"date":"07/10","kind":"out","customer":"北斗商事","detail":"交換端末 2台 → 仙台支店…","carrier":"","status":"超過"}]}
POST/api/shipment公開
出荷を作成します。SHP-#### 形式の id はサーバーが採番します。
パラメータ位置型必須説明
kindbodystring'in' または 'out'。省略時・不正値の場合は 'in'
customerbodystring○顧客名(120文字で切り詰め)。必須(空の場合は 400)
datebodystring表示日付(例: '07/13'、40文字で切り詰め)
detailbodystring自由記述の詳細(400文字で切り詰め)
carrierbodystring運送会社情報(120文字で切り詰め)
statusbodystring予定/手配中/出荷済/入荷済/超過/完了 のいずれか。既定値 予定
latebodyboolean超過フラグ(boolean に変換)
リクエスト
{"kind":"out","customer":"三峰精機","date":"07/20","detail":"8台 → 大阪支店","carrier":"ソラチ配送","status":"予定","late":false}
レスポンス例
{"ok":true,"shipment":{"id":"SHP-0007","date":"07/20","kind":"out","customer":"三峰精機","detail":"…","carrier":"ソラチ配送","status":"予定","late":false,"created":1784...,"updated":1784...}}
POST/api/shipment/:id公開
既存出荷のステータスを進める/項目を更新します。
パラメータ位置型必須説明
idpathstring○出荷 ID(例: SHP-0001)
datebodystring新しい表示日付(40文字で切り詰め)
kindbodystring'in'/'out'。不正値は無視
customerbodystring新しい顧客(120文字で切り詰め)
detailbodystring新しい詳細(400文字で切り詰め)
carrierbodystring新しい運送会社(120文字で切り詰め)
statusbodystring有効なステータスであること(不正なら 400)。完了系ステータスでは遅延フラグを解除
latebodyboolean超過フラグ(boolean に変換)
リクエスト
{"status":"出荷済"}
レスポンス例
{"ok":true,"shipment":{"id":"SHP-0001","status":"出荷済","late":false,"updated":1784...}}
POST/api/shipment/:id/delete公開
id で指定した出荷を削除します。
パラメータ位置型必須説明
idpathstring○出荷 ID(例: SHP-0001)
レスポンス例
{"ok":true}

ヘルプデスク (Tickets)

サポートチケットと対応履歴。スタッフ向け(要サインイン / claimed grant)。顧客ポータルからの問合せは POST /api/portal/inquiry(portal-token)が公開例外。

GET/api/tickets要サインイン実測 200
tickets コレクションの全サポートチケットを一覧します(デモチケット TK-0667..TK-0672 の6件をシード)。
レスポンス例
{"ok":true,"tickets":[{"id":"TK-0672","cust":"北斗商事","kind":"紛失","subject":"営業車内で紛失 → 位置特定&リモートワイプ要請","owner":"一条","sla":"1h 12m","status":"対応中"}]}
POST/api/ticket要サインイン
新規チケットを作成します。id TK-0<next num>(673 から開始)と作成タイムスタンプを自動付与し、入力項目を切り詰めます。
パラメータ位置型必須説明
custbodystring顧客名(別名: customer)。既定値 '—'、120文字で切り詰め。
kindbodystringチケット種別(60文字で切り詰め)。既定値 '問合せ'
subjectbodystring件名。既定値 ''、300文字で切り詰め。
ownerbodystring担当者。既定値 '—'、60文字で切り詰め。
slabodystringSLA ラベル。既定値 '4h 00m'、60文字で切り詰め。
statusbodystringステータス(40文字で切り詰め)。既定値 '受付'
prioritybodystring優先度。既定値 ''、40文字で切り詰め。
リクエスト
{"cust":"string","kind":"string","subject":"string","owner":"string","sla":"string","status":"string","priority":"string"}
レスポンス例
{"ok":true,"ticket":{"id":"TK-0673","cust":"—","kind":"問合せ","subject":"","owner":"—","sla":"4h 00m","status":"受付","priority":"","created":1700000000000}}
POST/api/ticket/:id要サインイン
既存チケットの status/owner/sla/subject/cust/kind/priority を更新します(指定された null でない項目のみ)。
パラメータ位置型必須説明
idpathstring○チケット ID(例: TK-0672)。
statusbodystring新しいステータス(40文字で切り詰め)。
ownerbodystring新しい担当者(60文字で切り詰め)。
slabodystring新しい SLA ラベル(60文字で切り詰め)。
subjectbodystring新しい件名(300文字で切り詰め)。
custbodystring新しい顧客(120文字で切り詰め)。
kindbodystring新しい種別(60文字で切り詰め)。
prioritybodystring新しい優先度(40文字で切り詰め)。
リクエスト
{"status":"string","owner":"string","sla":"string","subject":"string","cust":"string","kind":"string","priority":"string"}
レスポンス例
{"ok":true,"ticket":{"id":"TK-0672","status":"解決",...}}
POST/api/ticket/:id/delete要サインイン
チケットと関連メッセージを削除します。
パラメータ位置型必須説明
idpathstring○削除するチケット ID(例: TK-0672)。
レスポンス例
{"ok":true}
GET/api/ticket/:id/messages要サインイン実測 200
指定チケットの全メッセージを一覧します(記録がなければ空配列)。
パラメータ位置型必須説明
idpathstring○チケット ID(例: TK-0672)。
レスポンス例
{"ok":true,"messages":[]}
POST/api/ticket/:id/message要サインイン
チケットのメッセージ一覧にメッセージ {from,text} を追加します。msg id とタイムスタンプを付与します。
パラメータ位置型必須説明
idpathstring○チケット ID(例: TK-0672)。
frombodystring送信者ラベル。既定値 '—'、60文字で切り詰め。
textbodystring○メッセージ本文(2000文字で切り詰め)。必須(空の場合は 400)。
リクエスト
{"from":"string","text":"string (required)"}
レスポンス例
{"ok":true,"message":{"id":"msg-xxxx","from":"綾瀬","text":"...","ts":1700000000000}}

顧客管理 (Customers)

顧客アカウント・更新・商談。

GET/api/customers公開実測 200
全顧客アカウントを一覧します(id, name, industry, mdm, monthly, devices, since, status, note, renew)。
レスポンス例
{"ok":true,"customers":[{"id":"cust-mrv8frxlg","key":"hokuto","name":"北斗商事","industry":"大手商社 | 500台(iPhone)","mdm":"Intune(Clomo→移行済)","monthly":"¥380,000","devices":"500 台","since":"2025/04","status":"運用中","statusChip":"c-green","note":"豊島倉庫 専用エリア ¥45K/月","renew":{"date":"2027-03-31",...}}]}
POST/api/customer公開
新規顧客アカウントを作成します。name は必須です。生成された id とレコード全体を返します。
パラメータ位置型必須説明
namebodystring○アカウント名(必須。未指定の場合は 400)
industrybodystring業種/端末の概要行
mdmbodystringMDM プラットフォーム
monthlybodystring月額料金(既定値 '—')
devicesbodystring端末台数(既定値 '—')
sincebodystring開始月(既定値 '—')
statusbodystringステータスラベル
statusChipbodystringステータスチップのクラス(既定値 'c-gray')
notebodystring自由記述メモ
keybodystring短いアカウントキー
renewbodyobject更新/商談オブジェクト {date,dateLabel,year,kind,kindChip,what,detail,confidence,confColor} または null
リクエスト
{"name":"...","industry":"...","mdm":"...","monthly":"...","devices":"...","since":"...","status":"...","statusChip":"...","note":"...","key":"...","renew":{...}|null}
レスポンス例
{"ok":true,"id":"cust-xxxx","customer":{"id":"cust-xxxx","name":"...","industry":"","mdm":"","monthly":"—","devices":"—","since":"—","status":"","statusChip":"c-gray","note":"","renew":null}}
POST/api/customer/:id公開
id で指定した既存顧客の項目を更新します。id が見つからない場合は 404。
パラメータ位置型必須説明
idpathstring○顧客 ID(例: cust-mrv8frxlg)
namebodystring更新する shape() の任意の文字列フィールド
renewbodyobjectrenew を上書きする更新オブジェクト、または null
リクエスト
{"name":"...","industry":"...","note":"...","renew":{...}|null, ...any shape fields}
レスポンス例
{"ok":true,"customer":{"id":"cust-mrv8frxlg","name":"...",...}}
POST/api/customer/:id/delete公開
id で指定した顧客を削除します。存在しない場合は 404。
パラメータ位置型必須説明
idpathstring○削除する顧客 ID
レスポンス例
{"ok":true,"id":"cust-mrv8frxlg"}
GET/api/renewals公開実測 200
renew.date を持つ顧客から導出した更新・商談カレンダー。日付の昇順で並びます。
レスポンス例
{"ok":true,"renewals":[{"id":"ren-cust-mrv8frxli","customerId":"cust-mrv8frxli","customer":"天城製薬","date":"2026-08-31","dateLabel":"08/31","year":"2026","kind":"商談","kindChip":"c-orange","what":"最終見積回答期限","detail":"...","confidence":"確度 80%","confColor":"orange"}]}

見積 (Quote)

見積の作成・改訂・PDF元データ。

GET/api/quote/catalog公開実測 200
固定の INITIAL/RUNNING 明細カタログマスタを返します(app.html と同一内容)。
レスポンス例
{"ok":true,"catalog":{"initial":[{"n":"プロジェクト管理費","q":1,"p":300000,"d":"..."}, ...],"running":[{"n":"サービス管理・月次報告","q":1,"p":125000,"d":"..."}, ...]}}
GET/api/quote/new公開
カタログマスタから、指定した1顧客向けの「未保存」の見積を作成します。端末数量はその顧客自身のレコードから取得し、ボリューム値引きもそこから「再計算」します。そのため 1,000台 の区分未満では値引き自体が付きません。不明な custId は 404 customer_not_found、custId も cust も指定がない場合は 400 customer_required。
パラメータ位置型必須説明
custIdquerystringこのワークスペースが所有する顧客 ID(例: 'cust-mtg57z057')。その端末台数が 数量 とボリューム値引きを決定します。不明な場合は 404。
custquerystringまだ顧客一覧にない相手先向けの見積の場合の顧客名。custId 指定時は無視。どちらか一方が必須。
devicesqueryinteger端末数量の上書き(0 未満は 0)。既定は顧客レコード自体の台数。
patternquerystringランニングコストのパターン。'B' 以外はすべて 'A' として扱います。
レスポンス例
{"ok":true,"quote":{"id":null,"custId":"cust-mtg57z057","cust":"三峰精機 御中","pattern":"A","costRate":45,"ini":[{"n":"プロジェクト管理費","q":1,"p":300000,"d":"..."},...,{"n":"iPhone初期キッティング(台)","q":50,"p":1500,"d":"..."}],"run":[...],"totals":{"ini":2425000,"iniTax":242500,"iniTotal":2667500,"run":470000,"runTax":47000,"runTotal":517000,"arr":5640000,"y1":8065000,"costRate":45,"gp":4435750,"gpRate":55,"deviceQty":50,"perDevice":1500,"volumeApplied":false,"volumeQty":0,"volumeMinQty":1000,"taxRate":0.1}}}
エラー
400 — {"ok":false,"error":"customer_required","message":"対象顧客を指定してください。"} — 対象顧客が指定されていません
404 — {"ok":false,"error":"customer_not_found"} — custId に該当する顧客がありません
GET/api/quotes公開実測 200
保存済みの見積をすべて一覧します。各見積には算出済みの totals スナップショットが付きます。
レスポンス例
{"ok":true,"quotes":[{"id":"Q-AMAGI-001","cust":"天城製薬 御中","pattern":"A","costRate":45,"ini":[...],"run":[...],"signId":null,"totals":{"ini":...,"iniTax":...,"iniTotal":...,"run":...,"arr":...,"y1":...}}]}
GET/api/quote/draft公開
このワークスペースで作成中の見積ビルダー下書きを、算出済み合計付きで返します。作成中のものがなければ draft:null。下書きはワークスペースごとに1件(キー 'current')で、画面を移動しても保持されます。
レスポンス例
{"ok":true,"draft":{"cust":"北斗商事","custId":null,"pattern":"A","costRate":45,"ini":[{"n":"キッティング","q":100,"p":1500,"d":""}],"run":[],"updatedAt":1788114480640,"totals":{"ini":150000,"iniTax":15000,"iniTotal":165000,"run":0,"runTax":0,"runTotal":0,"arr":0,"y1":150000,"costRate":45,"gp":82500,"gpRate":55,"deviceQty":0,"perDevice":null,"volumeApplied":false,"volumeQty":0,"volumeMinQty":1000,"taxRate":0.1}}} — 未作成なら {"ok":true,"draft":null}
POST/api/quote/draft公開
作成中の見積ビルダー下書きを保存します(単一の 'current' 下書きを上書き)。明細は正規化され、ボリューム値引きは再計算されます。呼び出し側が独自の `totals` も送った場合は再計算結果と照合し、食い違う数値は項目名を示して 400 quote_inconsistent で「拒否」します。この場合は何も保存されません。
リクエスト
{"cust":"北斗商事","custId":null,"pattern":"A","costRate":45,"ini":[{"n":"キッティング","q":100,"p":1500,"d":""}],"run":[],"totals":{"ini":150000,...}} — totals は任意。付ければ再計算と照合されます
レスポンス例
{"ok":true,"draft":{"cust":"北斗商事","custId":null,"pattern":"A","costRate":45,"ini":[{"n":"キッティング","q":100,"p":1500,"d":""}],"run":[],"updatedAt":1788114480640,"totals":{"ini":150000,"iniTax":15000,"iniTotal":165000,"run":0,"runTax":0,"runTotal":0,"arr":0,"y1":150000,"costRate":45,"gp":82500,"gpRate":55,"deviceQty":0,"perDevice":null,"volumeApplied":false,"volumeQty":0,"volumeMinQty":1000,"taxRate":0.1}}}
エラー
400 — {"ok":false,"error":"quote_inconsistent","message":"イニシャル小計が一致しません:画面 999 / 明細からの再計算 150,000。","errors":[{"code":"figure_mismatch","field":"ini","message":"イニシャル小計が一致しません:画面 999 / 明細からの再計算 150,000。"}]} — 画面の数字と再計算が食い違う場合。保存されません
POST/api/quote/draft/clear公開
このワークスペースで作成中の見積ビルダー下書きを破棄します。冪等で、下書きの有無にかかわらず {ok:true} を返します。保存済みの見積には影響しません。
レスポンス例
{"ok":true}
POST/api/quote/preview公開
「未保存」の見積の発行前検証です。何も保存しません。成功時は算出済み合計付きの見積に加え、顧客向け CSV テキストと PDF 元データを返すため、画面・CSV・PDF は文字どおり同一の計算結果になります。呼び出し側の合計が再計算と食い違う場合、または見積の custId がこのワークスペースに存在しない場合は、問題の数値を示して 400 quote_inconsistent で「拒否」します。
リクエスト
{"id":null,"cust":"北斗商事","custId":"cust-…","pattern":"A","costRate":45,"ini":[{"n":"キッティング","q":100,"p":1500,"d":""}],"run":[{"n":"管理","q":1,"p":125000,"d":""}],"totals":{...}} — totals は任意(付ければ照合されます)
レスポンス例
{"ok":true,"quote":{"cust":"北斗商事","custId":null,"pattern":"A","costRate":45,"ini":[{"n":"キッティング","q":100,"p":1500,"d":""}],"run":[{"n":"管理","q":1,"p":125000,"d":""}],"id":null,"createdAt":1788114480661,"totals":{"ini":150000,"iniTax":15000,"iniTotal":165000,"run":125000,"runTax":12500,"runTotal":137500,"arr":1500000,"y1":1650000,"costRate":45,"gp":907500,"gpRate":55,"deviceQty":0,"perDevice":null,"volumeApplied":false,"volumeQty":0,"volumeMinQty":1000,"taxRate":0.1}},"csv":"\"見積番号\",\"(未保存)\"\r\n\"顧客名\",\"北斗商事\"\r\n...","document":{"meta":{...},"sections":[...],"summary":[...],"totals":{...}}}
エラー
400 — {"ok":false,"error":"quote_inconsistent","message":"イニシャル小計が一致しません:画面 1 / 明細からの再計算 150,000。","errors":[{"code":"figure_mismatch","field":"ini",...}]} — 数字の不一致。顧客不明なら {"code":"customer_unknown","field":"custId","message":"見積の顧客ID(nope)に該当する顧客が存在しません。"}
GET/api/quote/:id公開実測 200
id で指定した保存済み見積を算出済み合計付きで返します。見つからない場合は 404。
パラメータ位置型必須説明
idpathstring○見積 ID(例: 'Q-AMAGI-001')
レスポンス例
{"ok":true,"quote":{"id":"Q-AMAGI-001","cust":"天城製薬 御中","pattern":"A","costRate":45,"ini":[...],"run":[...],"signId":null,"totals":{...}}}
GET/api/quote/:id/csv公開
保存済み見積1件の顧客向け CSV(text/csv; charset=utf-8、BOM 付き、Content-Disposition attachment)。ヘッダーブロック 見積番号・顧客名・発行日・パターン・数量・ボリューム値引き、続いて明細、最後にサマリーブロックの順で、数値は PDF と同一です。※事前に検証します: custId が解決できなくなった見積や数値が食い違う見積は、エクスポートせず 400 quote_inconsistent(JSON)で「拒否」します。
パラメータ位置型必須説明
idpathstring○保存済み見積 ID(例: 'Q-AMAGI-001')
レスポンス例
"見積番号","Q-mtg57yza6"
"顧客名","北斗商事 御中"
"発行日","2026-08-31"
"パターン","A"
"数量(台)","100"
"ボリューム値引き","非適用(1,000台未満)"

"区分","項目","数量","単価","金額"
"イニシャル","iPhone初期キッティング(台)","100","1500","150000"
...
"区分","サマリー","金額"
"イニシャル","小計(税抜)","250000"
..."合計","粗利率(%)","55"
エラー
400 — {"ok":false,"error":"quote_inconsistent","message":"見積の顧客ID(cust-…)に該当する顧客が存在しません。","errors":[{"code":"customer_unknown","field":"custId",...}]}
404 — {"ok":false,"error":"not_found"}
GET/api/quote/:id/document公開
保存済み見積1件の PDF「元データ」です。meta(見積番号/顧客名/発行日/パターン/発行済みフラグ)、行ごとの金額と小計行を含む イニシャル・ランニング の各セクション、サマリー、totals スナップショットを含みます。描画はクライアントが行い、再計算は一切しません。※CSV と同様に事前に検証します: 不整合のある見積は、問題の数値を示して 400 quote_inconsistent で「拒否」します。
パラメータ位置型必須説明
idpathstring○保存済み見積 ID(例: 'Q-AMAGI-001')
レスポンス例
{"ok":true,"document":{"meta":{"quoteNo":"Q-mtg57yza6","cust":"北斗商事 御中","custId":"cust-mtg57yz50","issueDate":"2026-08-31","pattern":"A","issued":true},"sections":[{"key":"ini","title":"イニシャル(構築・初期キッティング)","rows":[{"n":"iPhone初期キッティング(台)","q":100,"p":1500,"amt":150000},...],"lines":[{"label":"イニシャル小計(税抜)","amount":250000},{"label":"消費税(10%)","amount":25000},{"label":"イニシャル合計(税込)","amount":275000}]},{"key":"run","title":"ランニング(月額 LCM運用)","rows":[...],"lines":[...,{"label":"年間継続収益(ARR)","amount":1500000}]}],"summary":[{"label":"初年度合計(税抜)","amount":1750000},{"label":"想定粗利","amount":962500}],"totals":{...}}}
エラー
400 — {"ok":false,"error":"quote_inconsistent","message":"見積の顧客ID(cust-…)に該当する顧客が存在しません。","errors":[{"code":"customer_unknown","field":"custId",...}]}
404 — {"ok":false,"error":"not_found"}
POST/api/quote公開
生成した id(Q-...)で新しい見積を保存します。明細と合計は正規化されます。
パラメータ位置型必須説明
custbodystring顧客名(200文字で切り詰め)。既定値 '御中'
patternbodystring'A' または 'B'(既定値 'A')
costRatebodynumber原価率 %(既定値 45)
inibodyarrayイニシャル明細 [{n,q,p,d}]
runbodyarrayランニング明細 [{n,q,p,d}]
signIdbodystring紐づける署名 ID(任意、120文字で切り詰め)
リクエスト
{"cust":"...","pattern":"A","costRate":45,"ini":[{"n":"...","q":1,"p":100,"d":"..."}],"run":[...],"signId":null}
レスポンス例
{"ok":true,"quote":{"id":"Q-...","cust":"...",...,"totals":{...}}}
POST/api/quote/:id公開
既存の見積をその場で更新します(パッチ方式)。見つからない場合は 404。
パラメータ位置型必須説明
idpathstring○更新する見積 ID
custbodystring更新後の顧客名
patternbodystring'A' または 'B'
costRatebodynumber原価率。0/不正値の場合は現在値を維持
inibodyarray置き換えるイニシャル明細
runbodyarray置き換えるランニング明細
signIdbodystring紐づける署名 ID(null で解除)
リクエスト
{"signId":"S-123"} (any subset of: cust,pattern,costRate,ini,run,signId)
レスポンス例
{"ok":true,"quote":{"id":"Q-AMAGI-001",...,"updatedAt":...,"totals":{...}}}

請求 (Invoices/Billing)

請求書・売上サマリ。

POST/api/quote/:id/issue公開
発行前ゲートです。数量・単価・値引き・税・合計 が一致し、かつ見積がこのワークスペースに存在する顧客を指定していない限り、顧客には何も届きません(CSV/ドキュメントと異なり、ここでは顧客が「必須」です)。成功時は 発行日 を「一度だけ」記録し(issuedAt。再発行しても最初の記録を維持)、CSV と PDF に異なる日付が印字されることはありません。検証済みの見積・ドキュメント・CSV をまとめて返します。失敗時は問題の数値を示して 400 quote_inconsistent を返し、何も記録しません。
パラメータ位置型必須説明
idpathstring○発行する保存済み見積 ID(例: 'Q-AMAGI-001')
レスポンス例
{"ok":true,"quote":{"id":"Q-mtg57yza6","cust":"北斗商事 御中","custId":"cust-mtg57yz50","pattern":"A","costRate":45,"ini":[...],"run":[...],"signId":null,"issuedAt":1788114526682,"createdAt":1788114526678,"updatedAt":1788114526682,"totals":{"ini":250000,"iniTax":25000,"iniTotal":275000,"run":125000,"runTax":12500,"runTotal":137500,"arr":1500000,"y1":1750000,"costRate":45,"gp":962500,"gpRate":55,"deviceQty":100,"perDevice":1500,"volumeApplied":false,"volumeQty":0,"volumeMinQty":1000,"taxRate":0.1}},"document":{"meta":{...,"issued":true},"sections":[...],"summary":[...],"totals":{...}},"csv":"\"見積番号\",\"Q-mtg57yza6\"\r\n..."}
エラー
400 — 発行拒否。顧客未選択: {"ok":false,"error":"quote_inconsistent","message":"対象顧客が選択されていません。顧客を選択してから発行してください。","errors":[{"code":"customer_required","field":"custId",...}]} | 顧客不明: {"code":"customer_unknown","field":"custId"} | 数字の不一致: {"code":"figure_mismatch","field":"ini",...}
404 — {"ok":false,"error":"not_found"}
GET/api/invoices公開実測 200
全請求書を id の新しい順(id の localeCompare 降順)で一覧します。
レスポンス例
{"ok":true,"invoices":[{"id":"INV-2607-004","cust":"三峰精機","month":"2607","desc":"新入社員向けキッティング 8台+送料","amount":19800,"due":"08/15","status":"draft","recurring":false}],"count":5}
POST/api/invoice公開
請求書を作成します。新規の INV- id が指定されない限り、連番 id(INV-YYMM-NNN)を自動生成します。
パラメータ位置型必須説明
custbodystring○顧客名(前後の空白を除去し 120文字で切り詰め)。空の場合は 400。
amountbodynumber○請求金額。有限かつ >= 0 であること(四捨五入)。不正な場合は 400。
statusbodystringdraft|issued|paid|overdue のいずれか。省略時・不正値の場合は draft。
monthbodystring請求月(YYMM 形式厳守、例: 2607)。形式が不正な場合は 400 で拒否します。以前は 8 文字で切り詰めてそのまま保存していたため、どの月にも属さず月次の MRR に黙って計上されない請求書が生じていました。省略時は当月の YYMM。
descbodystring明細の説明(300文字で切り詰め)。
duebodystring支払期日の文字列(20文字で切り詰め)。
idbodystring任意のカスタム ID。/^INV-/ に一致し既存でない場合のみ使用、それ以外は自動採番。
recurringbodyboolean継続課金フラグ(bool に変換)。
リクエスト
{"cust":"string(req)","amount":number(req),"status":"draft|issued|paid|overdue","month":"YYMM","desc":"string","due":"string","id":"INV-...","recurring":bool}
レスポンス例
{"ok":true,"invoice":{"id":"INV-2607-005","cust":"北斗商事","month":"2607","desc":"","amount":10000,"due":"","status":"draft","recurring":false}}
POST/api/invoice/:id公開
既存請求書1件のステータスや項目を更新します。status の列挙値と金額を検証します。
パラメータ位置型必須説明
idpathstring○更新する請求書 ID(例: INV-2607-004)。見つからない場合は 404。
statusbodystring新しいステータス。draft|issued|paid|overdue 以外は 400。
custbodystring顧客名(120文字で切り詰め)。
descbodystring説明(300文字で切り詰め)。
monthbodystring請求月(YYMM 形式厳守)。形式が不正な場合は 400 で拒否。省略時は請求書の既存の月を変更しません。
duebodystring支払期日(20文字で切り詰め)。
amountbodynumber金額。有限かつ >= 0 であること(不正なら 400)。
recurringbodyboolean継続課金フラグ(bool に変換)。
リクエスト
{"status":"...","cust":"string","desc":"string","month":"YYMM","due":"string","amount":number,"recurring":bool} (all optional)
レスポンス例
{"ok":true,"invoice":{"id":"INV-2607-004","cust":"三峰精機","month":"2607","desc":"新入社員向けキッティング 8台+送料","amount":19800,"due":"08/15","status":"issued","recurring":false}}
POST/api/invoices/issue公開
一括発行: 指定月(または当月)の下書き請求書をすべて issued に切り替え、件数を返します。
パラメータ位置型必須説明
monthbodystring対象月 YYMM(8文字で切り詰め)。既定は当月(例: 2607)。
リクエスト
{"month":"YYMM"} (optional; defaults to current month)
レスポンス例
{"ok":true,"count":1}
GET/api/billing/summary公開実測 200
請求サマリーを算出します: MRR/ARR、請求済・入金済・未入金・期限超過・下書きの各合計、継続:単発の比率、入金率。
レスポンス例
{"ok":true,"summary":{"mrr":550000,"arr":6600000,"billed":632500,"paid":550000,"unpaid":82500,"overdue":49500,"draft":19800,"recurring":550000,"oneshot":82500,"ratio":"87:13","recurringPct":87,"paidRatio":87,"month":"2607","count":5}}

シフト (Shift)

現場スタッフのシフト計画。

GET/api/shifts公開実測 200
週次シフト表グリッドと本日の打刻状態を返します。
レスポンス例
{"ok":true,"grid":{"s1":["day","day","day","day","day","off","off"],...},"clock":{"s1":{"in":"09:00","out":null,"status":"in","units":76},...}}
GET/api/staff公開実測 200
シフト表のスタッフ一覧(自社+派遣スタッフ)を返します。
レスポンス例
{"ok":true,"staff":[{"id":"s1","name":"一条","type":"own"},{"id":"a1","name":"派遣A","type":"agency"}]}
POST/api/shifts公開
シフト表グリッドと、任意で打刻データをストアに保存します。
パラメータ位置型必須説明
gridbodyobject○staffId をキーとし、7 日分の勤務ステータス文字列の配列(例: 'day','late','off','disp')を値とするシフト表グリッド。
clockbodyobject任意の打刻オブジェクト(staffId をキー → {in,out,status,units})。
リクエスト
{"grid":{"s1":["day",...]},"clock":{"s1":{"in":"09:00",...}}}
レスポンス例
{"ok":true,"grid":{...},"clock":{...}}
POST/api/shifts/draft公開
「未確定」のシフト案(通常は AI 提案)を、ワークスペースごとのインメモリ領域に一時配置します。「保存されず」、シフト表も「変更されません」: GET /api/shifts は確定済みグリッドを返し続け、提案は `draft` として別に返すため、再読み込みしても提案がシフト表を上書きすることはありません。下書きはワークスペースごとに1件(新しいものが古いものを置き換え)で、12時間で自動的に失効します。書き込みを行うのは POST /api/shifts/draft/apply のみです。
リクエスト
{"grid":{"s1":["off","day","day","day","day","off","off"],"s2":[...]}} — 値は day|late|night|disp|off などの勤務区分。未知の値は off に丸められます
レスポンス例
{"ok":true,"draft":{"grid":{"s1":["off","day","day","day","day","off","off"]},"diff":[{"staffId":"s1","day":0,"from":"day","to":"off"},{"staffId":"s2","day":0,"from":"late","to":"off"},...],"ts":1788114480682,"status":"unconfirmed"}}
エラー
400 — {"ok":false,"error":"grid required"} — grid が無い、またはどの行も 7 日分の配列として読めない
POST/api/shifts/draft/apply公開
一時配置したシフト案を「確定」します。このグループで唯一書き込みを行う呼び出しです。まず変更「前」のシフト表を復元履歴に積み(reason 適用前のシフト、id は applied.restoreId として返却)、その後下書きグリッドを本番グリッドにし、下書きを消去します。何も配置されていない場合(または下書きの有効期限12時間が過ぎた場合)は 404 no draft。
レスポンス例
{"ok":true,"grid":{"s1":["off","day","day","day","day","off","off"]},"applied":{"ts":1788114480690,"diff":[{"staffId":"s1","day":0,"from":"day","to":"off"},...],"restoreId":"SHmtg56zhu0"},"history":[{"id":"SHmtg56zhu0","ts":1788114480690,"reason":"適用前のシフト","grid":{...}}]}
エラー
404 — {"ok":false,"error":"no draft"} — 未確定提案がありません
POST/api/shifts/draft/discard公開
一時配置したシフト案を破棄します。下書きはそもそも保存されていないため、ロールバックは発生しません: `discarded` は下書きが実際に存在したかどうかを示すだけで、`grid` は変更のない確定済みシフト表です。冪等です。
レスポンス例
{"ok":true,"discarded":true,"grid":{"s1":["day","day","day","day","day","off","off"],"s2":["late","late","late","late","late","off","off"],...}} — 未確定提案が無ければ discarded:false
GET/api/shifts/history公開
apply と restore が取得した変更前シフト表のスナップショットを一覧します(新しい順、上限20件)。各要素は { id, ts, reason, grid } で、これらの id が復元先になります。最初の 確定 操作までは空です。
レスポンス例
{"ok":true,"history":[{"id":"SHmtg56zhu0","ts":1788114480690,"reason":"適用前のシフト","grid":{"s1":["day","day","day","day","day","off","off"],"s2":["late","late","late","late","late","off","off"],"s3":["off","day","day","day","off","off","off"],"a1":["off","off","disp","disp","off","off","off"],"a2":["off","off","off","off","off","off","off"]}}]} — 未確定操作がなければ history:[]
POST/api/shifts/restore/:hid公開
履歴スナップショットからシフト表を復元します。復元自体も 確定 操作のため、まず「現在の」シフト表を履歴に積み(reason 復元前のシフト)、一時配置中の下書きは無効になります。履歴にない id は 404 unknown snapshot。
パラメータ位置型必須説明
hidpathstring○GET /api/shifts/history の履歴スナップショット ID(例: 'SHmtg56zhu0')
レスポンス例
{"ok":true,"grid":{"s1":["day","day","day","day","day","off","off"],...},"restored":"SHmtg57z0n8","history":[{"id":"SHmtg57z0q9","ts":1788114526730,"reason":"復元前のシフト","grid":{...}},{"id":"SHmtg57z0n8","ts":1788114526727,"reason":"適用前のシフト","grid":{...}}]}
エラー
404 — {"ok":false,"error":"unknown snapshot"}
POST/api/timeclock/:staffId/punch公開
スタッフの出勤・退勤を打刻し、その打刻行を更新して返します。
パラメータ位置型必須説明
staffIdpathstring○スタッフ ID(40文字で切り詰め)。スタッフ名簿に存在すること(例: 's1','a1')。
dirbodystring'in' または 'out'(8文字で切り詰め)。省略時・不正値の場合は現在のステータスに応じて切り替え。
リクエスト
{"dir":"in"}
レスポンス例
{"ok":true,"staffId":"s1","row":{"in":"09:00","out":null,"status":"in","units":76}}
POST/api/staff公開
スタッフを作成し(type は 'own' または 'agency')、更新後のスタッフ一覧を返します。
リクエスト
{"name":"山田 太郎","type":"own"}
レスポンス例
{"ok":true,"staff":{"id":"smtc01egx1","name":"山田 太郎","type":"own"},"staffList":[{"id":"smtc01egx1","name":"山田 太郎","type":"own"}]}
POST/api/staff/:id公開
スタッフ1名の氏名・種別を更新します。
パラメータ位置型必須説明
idpathstring○スタッフ ID(例: 'smtc03hjxd')。
リクエスト
{"name":"山田 花子","type":"agency"}
レスポンス例
{"ok":true,"staff":{"id":"smtc03hjxd","name":"山田 花子","type":"agency"}}
POST/api/staff/:id/delete公開
スタッフ1名を削除し、その人のシフト表行と打刻行も削除します。
パラメータ位置型必須説明
idpathstring○スタッフ ID(例: 'smtc03hjxd')。
レスポンス例
{"ok":true,"id":"smtc03hjxd","staffList":[]}

入出荷ドック (Dock)

バース予約・受入スケジュール。

GET/api/dock/reservations公開実測 200
ドック・バースの全予約を一覧します(横づけ枠 の週間スケジュールデータ)。
レスポンス例
{"ok":true,"reservations":[{"id":"RV-0001","created":1784673357614,"updated":1784673357614,"date":"2026-07-13","start":"10:00","dur":90,"size":"2t車","dir":"入荷","cust":"北斗商事","note":"返却45台","berth":"A","road":"否","roadStatus":"","permit":"済"}]}
POST/api/dock/reservation公開
id で予約をアップサートします(id がない・不明なら作成、あれば既存を更新)。
パラメータ位置型必須説明
idbodystring予約 ID。指定ありかつ既存なら更新、それ以外はこの ID で作成(省略時は RV-#### を自動採番)。
datebodystring予約日(40文字で切り詰め、例: 2026-07-13)。
startbodystring開始時刻 HH:MM(10文字で切り詰め)。
durbodyinteger所要時間(分)。最小 15、既定値 60。
sizebodystring車格。2t車/4t車/4tロング/大型車 で検証し、それ以外は切り詰めて保存。
dirbodystring方向 入荷|出荷。不正値の場合は 入荷。
custbodystring○顧客名(作成時は必須、120文字で切り詰め)。
notebodystring自由記述メモ(300文字で切り詰め)。
berthbodystringバース A/B/路上待機。不正値の場合は A。
roadbodystring路上待機フラグ 要|否。要 以外はすべて 否。
roadStatusbodystring道路使用許可のステータス文字列(20文字で切り詰め、例: pending/done)。
permitbodystring許可ステータス文字列(20文字で切り詰め、例: 済/要)。
リクエスト
{"id":"RV-0001","date":"2026-07-13","start":"10:00","dur":90,"size":"2t車","dir":"入荷","cust":"北斗商事","note":"返却45台","berth":"A","road":"否","roadStatus":"","permit":"済"}
レスポンス例
{"ok":true,"reservation":{"id":"RV-0001","date":"2026-07-13",..."updated":1784673357614}}
POST/api/dock/reservation/:id/delete公開
id で指定した予約を削除します。
パラメータ位置型必須説明
idpathstring○削除する予約 ID(例: RV-0001)。
レスポンス例
{"ok":true}

データ消去証明 (Erasure)

ワイプ実績と消去証明書。

GET/api/certs公開実測 200
全データ消去証明書を新しい順に一覧します。
レスポンス例
{"ok":true,"certs":[{"no":"KIT-ERZ-2026-1003","date":"2026-07-09","cust":"天城製薬(検証)","count":6,"methodKey":"clear","method":"論理消去","nist":"Clear","devices":[...]}]}
GET/api/erasure/certs公開実測 200
/api/certs の別名です。全データ消去証明書を新しい順に一覧します。
レスポンス例
{"ok":true,"certs":[{"no":"KIT-ERZ-2026-1003",...}]}
GET/api/cert/:no公開実測 200
再印刷用に、証明書番号で証明書を1件取得します。
パラメータ位置型必須説明
nopathstring○証明書番号(例: KIT-ERZ-2026-1001)
レスポンス例
{"ok":true,"cert":{"no":"KIT-ERZ-2026-1001","date":"2026-07-03","cust":"北斗商事","count":45,"methodKey":"purge","method":"暗号化消去","nist":"Purge","devices":[...]}}
POST/api/cert公開
新しい証明書を発行します。番号は保存済みカウンタでサーバーが自動採番します。
パラメータ位置型必須説明
custbodystring○顧客名(120文字で切り詰め、前後空白除去)。空の場合は 400
methodKeybodystring○purge|clear|destroy のいずれか。不正な場合は 400
datebodystringYYYY-MM-DD(10文字で切り詰め)。既定は本日
countbodyintegerdevices[] 省略時の端末台数 1-500。既定値 1
devicesbodyarray任意の端末オブジェクト {model,id,storage,dt,verify,log,al}(500 件まで、正規化)
リクエスト
{"cust":"string","methodKey":"purge|clear|destroy","date":"YYYY-MM-DD","count":1,"devices":[{"model":"iPhone 16","id":"...","storage":"256GB"}]}
レスポンス例
{"ok":true,"cert":{"no":"KIT-ERZ-2026-1004","date":"2026-07-22","cust":"...","count":1,"methodKey":"purge","method":"暗号化消去","nist":"Purge","devices":[...]}}

リプレース提案 (Replace)

バッテリー劣化・更新提案。

GET/api/replace/proposals公開実測 200
端末リプレース提案の顧客別 'proposed'(提案済み)マップを { customer: ISO-timestamp } 形式で返します。
レスポンス例
{"ok":true,"proposals":{}}
POST/api/replace/proposal公開
顧客の端末リプレース提案を提案済みにし({ cust, at:now } をアップサート)、更新後の提案マップを返します。
パラメータ位置型必須説明
custbodystring○提案済みとしてマークする顧客キー/名(120文字で切り詰め)。空・未指定 -> 400。
リクエスト
{ "cust": "<customer>" }
レスポンス例
{"ok":true,"cust":"ACME株式会社","at":"2026-07-22T00:00:00.000Z","proposals":{"ACME株式会社":"2026-07-22T00:00:00.000Z"}}

ネットワーク (Network)

拠点回線・機器監視。

GET/api/network/deals公開実測 200
キャパシティネットワークの取引ボード(provide/accept/request の取引)を新しい順に返します。
レスポンス例
{"ok":true,"deals":[{"id":"dmrv8fry22c","dir":"provide","partner":"ネットワーク公開","kind":"キッティング枠","units":40,"period":"7/15–7/22","rate":1200,"status":"募集中"}]}
POST/api/network/deal公開
ボードに取引を追加します(余剰キャパシティの掲載またはキャパシティの依頼)。deals 配列の先頭に追加します。
パラメータ位置型必須説明
unitsbodyinteger○台数/枠数。整数として解釈し、> 0 でなければ 400。
dirbodystring方向: provide|accept|request。それ以外は 'provide' に変換(16文字で切り詰め)。
partnerbodystringパートナー・相手先名(120文字で切り詰め)。既定値 'ネットワーク公開'
kindbodystring枠の種類(40文字で切り詰め)。既定値 'キッティング枠'
periodbodystring期間ラベル(40文字で切り詰め)。既定値 '—'。
ratebodyinteger単価。整数として解釈、既定値 0。
statusbodystringステータスラベル(24文字で切り詰め)。既定は dir に応じて(承認待ち/対応中/募集中)。
リクエスト
{"dir":"provide","partner":"ネットワーク公開","kind":"キッティング枠","units":40,"period":"7/15–7/22","rate":1200,"status":"募集中"}
レスポンス例
{"ok":true,"deal":{"id":"d...","dir":"provide","partner":"...","kind":"キッティング枠","units":40,"period":"—","rate":0,"status":"募集中"},"deals":[...]}
GET/api/network/centers公開実測 200
キッティングセンターのディレクトリ/マーケットプレイスを返します(デモ用5センターをシード。認証は自己申告で、検証済みではありません)。
レスポンス例
{"ok":true,"centers":[{"id":"c-tsm","name":"豊島 近接センター","region":"東京","mdm":["Intune","Workspace ONE"],"slots":80,"shelf":40,"rate":1100,"certs":["ISMS","Pマーク"]}]}
GET/api/network/oem公開実測 200
ホワイトラベル/OEM テナント設定(ブランド、ロゴ、ドメイン、プラン)を返します。
レスポンス例
{"ok":true,"oem":{"brand":"","logo":"","domain":"","plan":"seat"}}
POST/api/network/oem公開
OEM テナント設定を保存します。単一の 'oem' ドキュメントを上書きします。
パラメータ位置型必須説明
brandbodystringブランド名(24文字で切り詰め)。
logobodystringロゴ(2文字で切り詰め — 絵文字や頭文字を想定)。
domainbodystringカスタムドメイン(48文字で切り詰め)。
planbodystring課金プラン: seat|rev。それ以外は 'seat' に変換(8文字で切り詰め)。
リクエスト
{"brand":"Acme","logo":"A","domain":"acme.example","plan":"seat"}
レスポンス例
{"ok":true,"oem":{"brand":"Acme","logo":"A","domain":"acme.example","plan":"seat"}}
POST/api/network/center公開
提携キッティングセンターを作成または更新し(既知の id を指定した場合は更新)、センター一覧全体を返します。
リクエスト
{"name":"板橋センター"}
レスポンス例
{"ok":true,"center":{"id":"c-mtc01ei95","name":"板橋センター","region":"—","mdm":[],"slots":0,"shelf":0,"rate":0,"certs":[]},"centers":[{"id":"c-mtc01ei95","name":"板橋センター","region":"—","mdm":[],"slots":0,"shelf":0,"rate":0,"certs":[]}]}
POST/api/network/center/:id/delete公開
キッティングセンターを1件削除し、残りの一覧を返します。
パラメータ位置型必須説明
idpathstring○センター ID(例: 'c-mtc01ei95')。
レスポンス例
{"ok":true,"id":"c-mtc01ei95","centers":[]}

需要予測 (Forecast)

16週の需要・要員シミュレーション。

GET/api/forecast公開実測 200
16週分の需要系列、公開されている需要・人員モデルの定数、保存済みのユーザー設定(horizon, sim)を返します。
レスポンス例
{"ok":true,"weekly":[620,600,540,470,560,690,810,940,980,900,700,600,560,540,600,640],"constants":{"PER_PERSON":80,"BASE_STAFF":2,"WORKDAYS":5,"CEIL_DAY":192,"COST_PER_STAFF":310000,"COST_MONTHS":2,"DEAL_REV":3850000,"DEAL_GROSS":1900000},"prefs":{"horizon":12,"sim":2}}
POST/api/forecast/prefs公開
ユーザー設定を保存します。horizon は {8,12,16}、sim は {0,1,2} の範囲で検証し、保存した設定を返します。
パラメータ位置型必須説明
horizonbodynumber予測期間(週)。8、12、16 のいずれか、それ以外は 400
simbodynumberシミュレーション/シナリオ番号。0、1、2 のいずれか、それ以外は 400
リクエスト
{"horizon":12,"sim":2}
レスポンス例
{"ok":true,"prefs":{"horizon":12,"sim":2}}

ラベル・QR (Labels)

管理番号・IMEI・資産QR印刷。

GET/api/labels/templates公開実測 200
保存済みのラベルテンプレートをすべて一覧します。
レスポンス例
{"ok":true,"templates":[]}
POST/api/labels/template公開
サーバー発行の id で新しいラベルテンプレートを作成します。
パラメータ位置型必須説明
namebodystring○テンプレート名(80文字で切り詰め)。未指定または空白のみの場合は 400 で拒否。サニタイズ後に空になった場合の既定値 'テンプレート'
sizebodystringラベルサイズ(s|m|l のいずれか)。不正値の場合は 'm'。
fieldsbodyobjectキー mgmt,imei,cust,model,qr,barcode の真偽値(!!value で変換)。
tsbodynumberタイムスタンプ。既定は Date.now()。
リクエスト
{"name":"string","size":"s|m|l","fields":{"mgmt":bool,"imei":bool,"cust":bool,"model":bool,"qr":bool,"barcode":bool},"ts":number}
レスポンス例
{"ok":true,"template":{"id":"tpl-xxxx","name":"...","fields":{...},"size":"m","ts":1700000000000}}
POST/api/labels/template/:id/delete公開
id で指定したテンプレートを削除します。
パラメータ位置型必須説明
idpathstring○テンプレート ID(40文字で切り詰め)。tplCol に存在すること。
レスポンス例
{"ok":true,"id":"tpl-xxxx"}
GET/api/labels/log公開実測 200
印刷バッチのログを全件一覧します。
レスポンス例
{"ok":true,"log":[]}
POST/api/labels/log公開
印刷バッチの記録をログに追加します。
パラメータ位置型必須説明
sizebodystringラベルサイズ s|m|l。不正値の場合は 'm'。
countbodynumber印刷したラベル枚数。0..100000 に丸め込み、既定値 0。
datebodystring日付文字列(10文字で切り詰め)。既定は本日の ISO 日付(YYYY-MM-DD)。
tsbodynumberタイムスタンプ。既定は Date.now()。
リクエスト
{"size":"s|m|l","count":number,"date":"YYYY-MM-DD","ts":number}
レスポンス例
{"ok":true,"entry":{"id":"lg-xxxx","ts":1700000000000,"date":"2026-07-22","count":0,"size":"m"}}

アンケート (Survey)

CSAT / NPS 回収。

GET/api/survey公開実測 200
保存済みのアンケート状態を返します: 回収済みの回答、回答 id をキーとする解約防止フォローアップ、累計送信数カウンタ。
レスポンス例
{"ok":true,"responses":[],"followups":{},"sent":152}
POST/api/survey/send公開
アンケート送信数カウンタを {batch} だけ加算し(欠落・不正時は 1)、新しい合計を返します。
パラメータ位置型必須説明
batchbodynumber送付したアンケート数。>0 でない場合は 1。
リクエスト
{"batch": 10}
レスポンス例
{"ok":true,"sent":162}
POST/api/survey/response公開
回収したアンケート回答(id,date,cust,src,k,nps,csat,comment)を responses コレクションに追加/アップサートします。
パラメータ位置型必須説明
idbodystring回答 ID(60文字で切り詰め)。未指定時は SR-<id> を自動生成。
datebodystring回答日(20文字で切り詰め)。既定値 ''。
custbodystring顧客名(120文字で切り詰め)。既定値 '—'。
srcbodystring回収チャネル(20文字で切り詰め)。既定値 'ticket'。
kbodystring種別/指標タイプ(10文字で切り詰め)。既定値 'CSAT'。
npsbodynumberNPS スコア。省略時は null、それ以外は + で数値化。
csatbodynumberCSAT スコア。省略時は null、それ以外は + で数値化。
commentbodystring自由記述コメント(400文字で切り詰め)。既定値 ''。
リクエスト
{"id":"SR-1001","date":"2026-07-22","cust":"Acme","src":"ticket","k":"CSAT","nps":9,"csat":5,"comment":"Great"}
レスポンス例
{"ok":true,"response":{"id":"SR-1001","date":"2026-07-22","cust":"Acme","src":"ticket","k":"CSAT","nps":9,"csat":5,"comment":"Great"}}
POST/api/survey/followup/:id公開
:id で指定した回答に対する解約防止フォローアップ {action,note,date} を記録または置換します。
パラメータ位置型必須説明
idpathstring○フォローアップを紐づける回答 ID(60文字で切り詰め)。
actionbodystring実施したフォローアップ対応(120文字で切り詰め)。既定値 ''。
notebodystringフォローアップのメモ(600文字で切り詰め)。既定値 ''。
datebodystringフォローアップ日(20文字で切り詰め)。既定値 ''。
リクエスト
{"action":"Called customer","note":"Resolved billing issue","date":"2026-07-22"}
レスポンス例
{"ok":true,"followup":{"action":"Called customer","note":"Resolved billing issue","date":"2026-07-22"}}

オンボーディング (Onboarding)

導入チェックリスト。

GET/api/onboarding/projects公開実測 200
現在のオンボーディングプロジェクト状態 {sel,tab,projects}(顧客ごとの7ステップ MDM/ABM フロー)を返します。存在しない場合はデモデータを自動シードします。
レスポンス例
{"ok":true,"state":{"sel":"北斗商事","tab":"cust","projects":{"北斗商事":{"mdm":"Intune","steps":{"kickoff":"done","abm":"done","apns":"done","design":"done","pilot":"done","rollout":"done","handover":"wip"},"start":"2026-06-27"},"三峰精機":{...},"天城製薬":{...}}}}
PUT/api/onboarding/projects公開
プロジェクト状態を置き換えます。projects オブジェクトは必須で、sel(120文字で切り詰め)と tab(emp|cust)をサニタイズします。
パラメータ位置型必須説明
selbodystring選択中の顧客キー(120文字で切り詰め)
tabbodystringアクティブなタブ。=== 'emp' なら 'emp'、それ以外は 'cust'
projectsbodyobject○顧客 -> {mdm,steps,start} のマップ。未指定・オブジェクト以外 -> 400
リクエスト
{"sel":"北斗商事","tab":"cust","projects":{"北斗商事":{"mdm":"Intune","steps":{...},"start":"2026-06-27"}}}
レスポンス例
{"ok":true,"state":{"sel":"...","tab":"cust","projects":{...}}}
GET/api/onboarding/requests公開実測 200
社員の端末申請をすべて ts の昇順で一覧します。シードは空です(クライアントと同一)。
レスポンス例
{"ok":true,"requests":[]}
POST/api/onboarding/request公開
保留中の端末申請を作成します。id を同期させるため、クライアント指定の id をそのまま使います。name と dept は必須です。
パラメータ位置型必須説明
idbodystring任意のクライアント ID(60文字で切り詰め)。既定は生成 ID('REQ')
namebodystring○従業員名(120文字で切り詰め)。空 -> 400
deptbodystring○部署(120文字で切り詰め)。空 -> 400
modelbodystring端末モデル(120文字で切り詰め)
mdmbodystringMDM プラットフォーム(60文字で切り詰め)。既定値 'Intune'
usebodystring用途/目的(60文字で切り詰め)
ticketbodystringチケット参照(60文字で切り詰め)
tsbodynumberタイムスタンプ。数値でない場合は Date.now()
リクエスト
{"name":"桐生太郎","dept":"営業部","model":"iPhone 15","mdm":"Intune","use":"field","ticket":"T-100"}
レスポンス例
{"ok":true,"request":{"id":"REQ-...","name":"桐生太郎","dept":"営業部","model":"iPhone 15","mdm":"Intune","use":"field","ticket":"T-100","status":"pending","ts":1700000000000}}
POST/api/onboarding/request/:id公開
id で指定した既存申請を {status} で承認/却下/リセットします。'approved' の場合はリードタイムを設定します(任意の lead 日数、なければ 0.8〜2.4 のランダム値)。
パラメータ位置型必須説明
idpathstring○申請 ID。不明な場合 -> 404 {error:'request not found'}
statusbodystring○approved|rejected|pending のいずれか。それ以外は 400 {error:'invalid status'}
leadbodynumber承認時のリードタイム(日)。数値でない場合は 0.8-2.4 のランダム値(小数第1位に丸め)
リクエスト
{"status":"approved","lead":1.5}
レスポンス例
{"ok":true,"request":{"id":"REQ-...","status":"approved","lead":1.5,...}}

チーム (Team)

メンバー・権限・稼働。

GET/api/team/members公開実測 200
team-members コレクションからチームメンバーの全一覧を返します。
レスポンス例
{"ok":true,"members":[{"id":"t1","name":"藤宮 美咲","ini":"MS","role":"owner","dept":"経営","email":"owner@example.com"}, ...]}
POST/api/team/member公開
新しいメンバーを作成・招待します。id はサーバーが発行し、name は必須です。
パラメータ位置型必須説明
namebodystring○表示名(未指定・空欄は 400、80文字で切り詰め)
inibodystringイニシャル(先頭2文字を大文字化。既定値 'NA')
rolebodystringowner|admin|exec|member|viewer のいずれか(既定値 'member')
deptbodystring部署(60文字で切り詰め。既定値 '—')
emailbodystringメールアドレス(120文字で切り詰め)
scopesbodyobject領域別権限 {mgmt,ops,sales,support,settings}(各値は none|view|edit)
リクエスト
{"name":"string","ini":"string?","role":"owner|admin|exec|member|viewer?","dept":"string?","email":"string?","scopes":{...}?}
レスポンス例
{"ok":true,"member":{"id":"t<generated>","name":"...","ini":"NA","role":"member","dept":"—","email":""}}
POST/api/team/member/:id公開
既存メンバーのロール・スコープ・各フィールドを更新します。最後のオーナーの降格はブロックされます。
パラメータ位置型必須説明
idpathstring○更新対象のメンバーID(例: 't5'。40文字で切り詰め)
rolebodystring新しいロール(最後の owner を降格する場合は 409 で拒否)
namebodystring更新後の名前
inibodystring更新後のイニシャル
deptbodystring更新後の部署
emailbodystring更新後のメールアドレス
scopesbodyobject更新後の領域別権限
リクエスト
{"role":"...?","name":"...?","ini":"...?","dept":"...?","email":"...?","scopes":{...}?}
レスポンス例
{"ok":true,"member":{"id":"t5","name":"御堂 由美","role":"member", ...}}
POST/api/team/member/:id/delete公開
メンバーを id で削除します。残り 1 人のオーナーは削除できません。
パラメータ位置型必須説明
idpathstring○削除対象のメンバーID(例: 't6'。40文字で切り詰め)
レスポンス例
{"ok":true,"id":"t6"}
GET/api/team/plan要サインイン実測 200
現在の課金プランキー(starter|pro|ent)を返します。既定値は 'pro' です。
レスポンス例
{"ok":true,"planKey":"pro"}
POST/api/team/plan要サインイン
現在の課金プランを設定します。starter|pro|ent で検証します。
パラメータ位置型必須説明
planKeybodystring○変更先プラン(starter|pro|ent のいずれか。それ以外は 400。20文字で切り詰め)
リクエスト
{"planKey":"starter|pro|ent"}
レスポンス例
{"ok":true,"planKey":"pro"}
POST/api/team/invite要サインイン
このワークスペースにチームメイトを招待します(owner/admin のみ)。署名付きで有効期限のある招待トークンを発行し、保留中の "invited" メンバー行を保存して招待 URL を返します。保留中の招待もプランのメンバー上限に対して 1 席を消費します。
リクエスト
{"email":"teammate@example.com","role":"member","name":"佐藤 花子"}
レスポンス例
{"ok":true,"inviteUrl":"https://kit-agent.ai-sns.io/signup?invite=<token>","token":"<body>.<sig>","member":{"id":"tmtc03zwxf","name":"佐藤 花子","ini":"NA","role":"member","dept":"—","email":"teammate@example.com","status":"invited"}}
POST/api/team/accept公開
招待トークンを引き換えます。招待先のアドレスに紐づくアカウントを作成し、招待元のワークスペースに参加させます(呼び出し元の匿名ワークスペースではありません)。署名付き kit_tid Cookie を設定し、セッショントークンを返します。
リクエスト
{"inviteToken":"<invite token>","email":"teammate@example.com","password":"YOUR_PASSWORD","name":"佐藤 花子"}
レスポンス例
{"ok":true,"token":"<body>.<sig>","account":{"email":"invitee2@example.com","company":"","name":"佐藤 花子","tenantId":"t-…","created":"2026-08-27T20:54:48.597Z","lastLogin":null},"joinedTenant":"t-…"}

設定 (Settings)

テナント設定・機能フラグ。

GET/api/settings/company公開実測 200
見積・請求書・証明書の PDF に印字する発行者(会社)プロフィールを返します。
レスポンス例
{"ok":true,"company":{"name":"Freeborn Inc.","brand":"Ai-Sns.io Kitting","addr":"東京都板橋区・板橋キッティングセンター","tel":"","email":"","regno":"","rep":"","web":"","bank":"","logo":""}}
PUT/api/settings/company公開
発行者(会社)プロフィールをマージ更新します(テキスト項目+base64 ロゴの dataURL)。
パラメータ位置型必須説明
namebodystring会社の正式名称(300文字で切り詰め)
brandbodystringブランド名・製品名(300文字で切り詰め)
addrbodystring住所(300文字で切り詰め)
telbodystring電話番号(300文字で切り詰め)
emailbodystring連絡先メールアドレス(300文字で切り詰め)
regnobodystring登録番号・インボイス番号(300文字で切り詰め)
repbodystring代表者名(300文字で切り詰め)
webbodystringWebサイトURL(300文字で切り詰め)
bankbodystring振込先口座情報(300文字で切り詰め)
logobodystringロゴの base64 dataURL(6MB で切り詰め)
リクエスト
{"name":"...","brand":"...","addr":"...","tel":"...","email":"...","regno":"...","rep":"...","web":"...","bank":"...","logo":"data:image/png;base64,..."}
レスポンス例
{"ok":true,"company":{...merged record...}}
GET/api/settings/prefs公開実測 200
通知設定を返します(emailNotify / slaAlert の保存フラグ。slaAlert によるアラート処理はありません)。
レスポンス例
{"ok":true,"prefs":{"emailNotify":true,"slaAlert":true}}
PUT/api/settings/prefs公開
通知設定をマージ更新します(emailNotify / slaAlert の保存フラグ。アラート処理はありません)。
パラメータ位置型必須説明
emailNotifybodybooleanメール通知の切替(!! で真偽値に変換。既定値 true)
slaAlertbodybooleanSLA設定の保存フラグ(処理なし)
リクエスト
{"emailNotify":true,"slaAlert":false}
レスポンス例
{"ok":true,"prefs":{"emailNotify":true,"slaAlert":false}}
GET/api/config公開
管理者が制御するサイト設定の公開・読み取り専用ビューです(秘密情報は含みません)。お知らせバナー、メンテナンス状態、フロントエンドの機能トグルを返します。Cache-Control: no-store で送信します。デモワークスペースには追加で demoEnabled:true と demoTenant:true が付きます。
レスポンス例
{"ok":true,"config":{"maintenanceMode":false,"maintenanceMessage":"ただいまメンテナンス中です。しばらくしてから再度お試しください。","registrationOpen":true,"announcementEnabled":false,"announcementText":"","announcementLevel":"info","demoEnabled":true,"signinEnabled":true,"chatBubbleEnabled":true,"primaryCtaLabel":""}}
GET/api/settings/ui公開
このワークスペースのサーバー側 UI 状態データ(不透明な文字列マップ)を返します。表示やフィルタの選択が、キャッシュ消去後や別の端末でも維持されます。
レスポンス例
{"ok":true,"state":{}}
PUT/api/settings/ui公開
UI 状態データをマージ更新します。保存されるのは文字列値のみで、明示的な null はそのキーを削除します。ドキュメント全体の上限は 512KB です。
リクエスト
{"state":{"theme":"dark"}}
レスポンス例
{"ok":true,"keys":1,"size":16}

連携 (Integrations)

Teams / Slack / LINE WORKS 等。

GET/api/integrations/rules要サインイン実測 200
自動化ルールのトグル(trigger->action)と、ユーザーが追加した追加ルールを返します。サインイン(アカウントトークンまたは登録済みワークスペースのセッション)が必要で、共有デモワークスペースでは拒否されます。
レスポンス例
{"ok":true,"rules":{"r-ship":true,"r-inv":true,"r-lost":true,"r-ade":true,"r-sla":true,"r-pay":false},"extraRules":[]}
PUT/api/integrations/rules要サインイン
ルールの状態全体を保存します。rules マップ(id->bool)と extraRules 配列のいずれか、または両方を置き換えます。サインイン(アカウントトークンまたは登録済みワークスペースのセッション)が必要で、共有デモワークスペースでは拒否されます。書き込みには owner または admin ロールが必要です。
パラメータ位置型必須説明
rulesbodyobjectruleId->boolean のマップ(キーは60文字で切り詰め、値は真偽値に変換。オブジェクト以外は 400)
extraRulesbodyarrayルールオブジェクト {id,trig,act,ic,on} の配列(フィールドごとに正規化・切り詰め。配列以外は 400)
リクエスト
{"rules":{"r-ship":true,"r-pay":true},"extraRules":[{"id":"r-x1","trig":"...","act":"...","ic":"⚙️","on":true}]}
レスポンス例
{"ok":true,"rules":{...},"extraRules":[...]}
GET/api/integrations/log要サインイン実測 200
直近の同期ログを新しい順(time の降順)で返します。サインイン(アカウントトークンまたは登録済みワークスペースのセッション)が必要で、共有デモワークスペースでは拒否されます。
レスポンス例
{"ok":true,"log":[{"id":"LOG-0001","service":"intune","kind":"インベントリ取得","result":"ok","time":"2026-07-21T22:06:57.616Z"}]}
POST/api/integrations/log要サインイン
同期ログに新しいエントリを追加し、そのエントリとログ全体(最大 60 件)を返します。サインイン(アカウントトークンまたは登録済みワークスペースのセッション)が必要で、共有デモワークスペースでは拒否されます。書き込みには owner または admin ロールが必要です。
パラメータ位置型必須説明
servicebodystring○サービス名(60文字で切り詰め、前後の空白を除去。必須、未指定は 400)
kindbodystring同期処理の説明(200文字で切り詰め)
resultbodystringok|warn|err のいずれか(それ以外は 'ok' として扱います)
timebodystringISO タイムスタンプ(40文字で切り詰め。既定値は現在時刻)
リクエスト
{"service":"sorachi","kind":"送り状 発行","result":"ok","time":"2026-07-22T00:00:00.000Z"}
レスポンス例
{"ok":true,"entry":{"id":"LOG-0008","service":"sorachi","kind":"送り状 発行","result":"ok","time":"..."},"log":[...]}

コンプライアンス (Compliance)

ISMS/Pマーク/SOC2/APPI・監査ログ・CAPA。

GET/api/compliance公開実測 200
規格(isms/pmark/soc2/appi)ごとの管理策チェックリストと、CAPA 是正処置の全一覧を返します。
レスポンス例
{"ok":true,"controls":{"isms":[true,true,true,true,false,true],"pmark":[...],"soc2":[...],"appi":[...]},"capa":[{"id":"CAPA-2026-014","src":"SOC 2","finding":"変更管理の承認記録に一部欠落","due":"2026-07-25","owner":"一条 玲","state":"対応中"}]}
POST/api/compliance/capa/:id公開
id で指定した是正処置(CAPA)1 件の状態を更新します。
パラメータ位置型必須説明
idpathstring○CAPA ID(例: CAPA-2026-014)
statebodystring○新しい状態の文字列(20文字で切り詰め。trim 後に空でないこと)
リクエスト
{"state":"是正待ち"}
レスポンス例
{"ok":true,"capa":{"id":"CAPA-2026-014","src":"SOC 2","finding":"...","due":"2026-07-25","owner":"一条 玲","state":"是正待ち"}}
PUT/api/compliance/controls/:key公開
規格の管理策チェックリストを新しい boolean 配列で置き換えます。
パラメータ位置型必須説明
keypathstring○管理策セットのキー: isms | pmark | soc2 | appi
controlsbodyboolean[]○真偽値の配列(!! で変換。先頭100件を保持)
リクエスト
{"controls":[true,true,false,true,false,true]}
レスポンス例
{"ok":true,"key":"isms","controls":[true,true,false,true,false,true]}
GET/api/audit-log公開実測 200
追記専用の監査ログ(IMEI の訂正と CSV 取込は自動記録)を新しい順の行として返します。各行は [ts,user,action,target,result,cat] です。
レスポンス例
{"ok":true,"logs":[["2026-07-11 09:02","一条 玲","ログイン(多要素認証)","管制コンソール","成功","login"],["2026-07-11 09:14","綾瀬 涼","端末台帳 更新(ステータス変更)","IMEI 356821…4471","成功","ledger"]]}
POST/api/audit-log公開
監査エントリを新規追加します。ts/user/target/result/cat を省略した場合は既定値を自動補完します。
パラメータ位置型必須説明
actionbodystring○操作内容(200文字で切り詰め。trim 後に空でないこと)
tsbodystringタイムスタンプ(25文字で切り詰め。既定値はサーバーの now() 'YYYY-MM-DD HH:mm')
userbodystring実行者(60文字で切り詰め)。既定値 'システム'
targetbodystring対象(200文字で切り詰め。既定値 '—')
resultbodystring結果(20文字で切り詰め)。既定値 '成功'
catbodystringカテゴリ(20文字で切り詰め。既定値 'audit')
リクエスト
{"action":"消去実行","user":"早瀬 佳奈","target":"北斗商事 45台","result":"成功","cat":"erase"}
レスポンス例
{"ok":true,"entry":["2026-07-22 10:15","早瀬 佳奈","消去実行","北斗商事 45台","成功","erase"]}

ワークデスク (Workdesk)

社内ナレッジ・依頼。

POST/api/compliance/report公開
内部監査報告書の発行前チェックです。対象月、記録件数、CAPA 一覧、発行者欄は、このワークスペース自身の監査ログと設定から再計算します。対象月の形式が不正または未来の月である、ログのタイムスタンプが実在の日時でない、CAPA の期限が不正である、発行者/Pマーク登録番号が欠落または不正である、呼び出し側が指定した claim.count がその月の記録と一致しない、のいずれかの場合は、印刷用の文書ではなく、問題の数値を明示した 422 を返します。対象月を省略すると当月を使用し、当月に記録がなければ実際に記録がある最新の月にフォールバックするため、数値とそのラベルは常に同じ期間を表します。
リクエスト
{"month":"2026-07","claim":{"count":15}} — どちらも任意。claim.count を付けると記録件数と照合されます
レスポンス例
{"ok":true,"doc":{"month":"2026-07","count":15,"byCat":{"login":3,"ledger":2,"erase":3,"ship":2,"perm":2,"mdm":2,"audit":1},"capa":[{"id":"CAPA-2026-014","src":"SOC 2","finding":"...","due":"2026-07-25","owner":"一条 玲","state":"対応中","dueValid":true,"overdue":true,"daysLeft":-37},...],"overdue":3,"org":{"name":"Freeborn Inc.","brand":"Ai-Sns.io Kitting","addr":"...","email":"contact@ai-sns.io","officerTitle":"情報セキュリティ管理責任者","officer":"一条 玲","center":"板橋キッティングセンター","pmark":"第20002676号","isms":"ISO/IEC 27001:2022"},"issuedAt":"2026-08-31 03:28"}}
エラー
422 — 整合しないので発行しない。{"ok":false,"issues":["監査ログ件数 99件 が 2026-07 の記録 15件 と一致しません"],"month":"2026-07"} / {"ok":false,"issues":["監査対象月「2026-13」が YYYY-MM 形式ではありません"],"month":"2026-07"}
POST/api/compliance/custody公開
授受記録(chain of custody)の発行前チェックです。誰がいつ端末を保持していたかを示す記録は、未署名・未完了のステップ、あり得ないタイムスタンプ、時系列順でないステップ、発行者の欠落がある状態では発行できません。問題のステップを明示した 422 を返し、不備を次のように区別します: `invalid` = 致命的な不備(記録をまったく印刷できない)、`incomplete` = 受け渡しがまだ完了していないだけ。`draftable` は invalid が空のときに限り true で、その記録は「進行中」と明示した下書きとしてのみ印刷でき、正式な証跡としては印刷できません。ステップは最大 50 件です。
リクエスト
{"imei":"356938035643809","model":"iPhone 16","cust":"北斗商事","steps":[{"label":"受領","role":"センター","who":"一条","dt":"2026-08-01 09:00","state":"完了","sign":"一条"},{"label":"出荷","who":"綾瀬","dt":"2026-08-02 10:00","state":"完了","sign":"綾瀬"}]} — state は 完了 で確定。sign が空/—/(未署名)は未署名扱い
レスポンス例
{"ok":true,"record":{"imei":"356938035643809","model":"iPhone 16","cust":"北斗商事","steps":[{"label":"受領","role":"","who":"一条","dt":"2026-08-01 09:00","state":"完了","sign":"一条"},{"label":"出荷","role":"","who":"綾瀬","dt":"2026-08-02 10:00","state":"完了","sign":"綾瀬"}],"org":{"name":"Freeborn Inc.","brand":"Ai-Sns.io Kitting","addr":"...","email":"contact@ai-sns.io","officerTitle":"情報セキュリティ管理責任者","officer":"一条 玲","center":"板橋キッティングセンター","pmark":"第20002676号","isms":"ISO/IEC 27001:2022"},"issuedAt":"2026-08-31 03:28"}}
エラー
422 — 発行不可。ハード欠陥: {"ok":false,"issues":["対象端末(IMEI/シリアル)が指定されていません","授受工程が1件もありません"],"invalid":[同左],"incomplete":[],"draftable":false} / 進行中のみ: {"ok":false,"issues":["工程「出荷」が未完了です(状態:予定)","工程「出荷」が未署名です","工程「出荷」の担当者が未確定です"],"invalid":[],"incomplete":[同左],"draftable":true}
GET/api/workdesk/docs公開実測 200
資料ライブラリの文書を一覧します。ユーザーが追加したものを新しい順に、その後にシード文書を元の順序で返します。
レスポンス例
{"ok":true,"docs":[{"id":"sop","name":"キッティング手順書","type":"SOP","size":184320,"status":"索引済","date":"2026/07/21","created":0,"seedIdx":0}]}
POST/api/workdesk/doc公開
文書を作成・upsert します。body の項目はすべて任意で、既定値が適用されます。
パラメータ位置型必須説明
idbodystring資料ID(60文字で切り詰め。省略時は 'doc-...' を自動生成)
namebodystring資料名(200文字で切り詰め)。既定値 '資料-<timestamp>'
typebodystring資料の種別(40文字で切り詰め。既定値 'FILE')
sizebodynumberバイトサイズ(既定値 0)
statusbodystring索引ステータス(40文字で切り詰め)。既定値 '索引済'
datebodystring表示日付(40文字で切り詰め。既定値は today() による日本語表記の日付)
リクエスト
{"name":"...","type":"...","size":123,"status":"...","date":"...","id":"..."}
レスポンス例
{"ok":true,"doc":{"id":"doc-...","name":"...","type":"FILE","size":0,"status":"索引済","date":"2026/07/22","created":1700000000000}}
POST/api/workdesk/doc/:id/delete公開
文書を id で削除します。見つからない場合は 404 です。
パラメータ位置型必須説明
idpathstring○削除対象の資料ID(例: 'sop')
レスポンス例
{"ok":true}
GET/api/workdesk/threads公開実測 200
AI チャットのスレッドを新しい順(created の降順)で一覧します。シードは空です。
レスポンス例
{"ok":true,"threads":[]}
POST/api/workdesk/thread公開
チャットスレッド全体を作成・upsert します。body は任意で、msgs はサニタイズされます。
パラメータ位置型必須説明
idbodystringスレッドID(60文字で切り詰め。省略時は 'thr-...' を自動生成)
titlebodystringタイトル(120文字で切り詰め)。既定値 '新しいチャット'
tsbodystringタイムスタンプ表示ラベル(40文字で切り詰め)
msgsbodyarrayメッセージ [{role,text?,html?,srcs?,typing?}](各要素を cleanMsg で無害化)
リクエスト
{"id":"...","title":"...","ts":"...","msgs":[{"role":"user","text":"..."}]}
レスポンス例
{"ok":true,"thread":{"id":"thr-...","title":"新しいチャット","ts":"","msgs":[],"created":1700000000000}}
POST/api/workdesk/thread/:id公開
msgs の追記・置換、またはスレッド名の変更を行います。追記時にスレッドがなければ作成します。
パラメータ位置型必須説明
idpathstring○スレッドID
titlebodystringスレッド名の変更(120文字で切り詰め)
tsbodystringタイムスタンプ表示ラベル(40文字で切り詰め)
msgsbodyarraymsgs リスト全体を置き換え
appendbodyarray既存リストに msgs を追記
リクエスト
{"title":"...","ts":"...","msgs":[...],"append":[{"role":"ai","text":"..."}]}
レスポンス例
{"ok":true,"thread":{"id":"...","title":"...","ts":"...","msgs":[...],"created":1700000000000}}
POST/api/workdesk/conn公開
コネクタのオン/オフマップ {id:bool,...} を boolean に変換して保存します。
パラメータ位置型必須説明
mapbodyobject{id:bool} のマップ(.map キーがない場合は本文自体をマップとして使用。キーは40文字で切り詰め、値は !! で変換)
リクエスト
{"slack":true,"teams":false}  OR  {"map":{"slack":true}}
レスポンス例
{"ok":true,"conn":{"slack":true,"teams":false}}
GET/api/workdesk/conn公開実測 200
保存済みのコネクタのオン/オフマップを読み込みます(画面復元用)。
レスポンス例
{"ok":true,"conn":{}}
POST/api/workdesk/search公開
このワークスペースの索引済み文書を対象とした実際の検索です。一致がなければヒットなしを返し、根拠のない回答にもっともらしい出典を付けることはありません。
リクエスト
{"q":"キッティング"}
レスポンス例
{"ok":true,"q":"キッティング","hits":[],"indexed":0}

ESG

リユース・CO2・サステナビリティ指標。

GET/api/esg/settings公開実測 200
監査可能な ESG 係数(co2e kg-CO2e/台、ewaste kg/台)を返します。
レスポンス例
{"ok":true,"settings":{"co2e":55,"ewaste":0.42}}
PUT/api/esg/settings公開
ESG 係数をマージ更新します。co2e / ewaste は正の有限数のみ受け付け、それ以外は従来の値を維持します。
パラメータ位置型必須説明
co2ebodynumber1台あたりの kg-CO2e(正の有限数の場合のみ適用。それ以外は従来値を維持)
ewastebodynumber1台あたりの kg(正の有限数の場合のみ適用。それ以外は従来値を維持)
リクエスト
{"co2e": 55, "ewaste": 0.42}
レスポンス例
{"ok":true,"settings":{"co2e":60,"ewaste":0.5}}
GET/api/esg/metrics公開実測 200
年度、月次リユース台数、顧客別のリユース/返却数、および合計値(reuse、ret、循環率 %)を返します。
レスポンス例
{"ok":true,"fy":"2026年度","months":["4","5",...],"monthly":[78,85,...],"customers":[{"name":"北斗商事","reuse":420,"ret":470},...],"totals":{"reuse":1240,"ret":1420,"circularity":87.3}}

顧客ポータル (Portal)

顧客共有ビュー。

POST/api/esg/report公開
ESG レポートの発行前チェックです。すべての数値を、このワークスペースのリユース記録と保存済みの CO2e/電子廃棄物係数から再計算します。顧客別合計が月次実績合計と一致しない、顧客の再利用が返却を上回る、CO2e 係数が正の数でない、呼び出し側が指定した値(units / actualUnits / forecastUnits / co2e / factor)が計算結果と一致しない、のいずれかの場合は、問題の数値を明示した 422 を返します。実績と予測は別々のラベル付き数値として報告し、合算することはありません。`warnings`(例: 公表されている出典の範囲外の係数)は発行を妨げず、200 の応答にも含まれます。
リクエスト
{"scope":"center","claim":{"units":1240,"actualUnits":351,"forecastUnits":889,"co2e":68.2,"factor":55}} — すべて任意。scope は 'center'/'センター全体'(既定)または集計対象の顧客名。claim を付けた項目だけが照合されます
レスポンス例
{"ok":true,"warnings":[],"doc":{"scope":"センター全体","fy":"2026年度","actualThrough":"2026-07","forecastFrom":"2026-08","units":1240,"ret":1420,"co2e":68.2,"ewasteKg":520.8,"circularity":87.3,"actualUnits":351,"forecastUnits":889,"actualCo2e":19.3,"forecastCo2e":48.9,"settings":{"co2e":55,"ewaste":0.42},"basis":{"co2e":{"unit":"kg-CO2e/台","lo":55,"hi":66,"perModel":false,"method":"...","source":"...","scope":"..."},"ewaste":{"unit":"kg/台","lo":0.19,"hi":1.5,...}}}}
エラー
422 — 整合しないので発行しない。{"ok":false,"issues":["対象台数 1台 が集計値 1240台 と一致しません"],"warnings":[]} / {"ok":false,"issues":["CO2e 削減量 1 t が 1240台 × 55 kg-CO2e/台 ÷ 1000 = 68.2 t と一致しません"],"warnings":[]}
GET/api/portals公開実測 200
顧客ポータルの全状態を返します。顧客ごとの {published,suffix,last,name,slug} と、全体カウンタ _tickets(当月累計)および _dls(月平均ダウンロード数)です。
レスポンス例
{"ok":true,"state":{"hokuto":{"published":true,"suffix":"blk3","last":"3分前","name":"北斗商事","slug":"hokuto"},"tosei":{"published":false,"suffix":"1jip","last":"—",...},"_tickets":4,"_dls":63}}
GET/api/portal/viewtoken
1 社の顧客向け読み取り専用ビュー全体を、セッションではなくポータルトークンで指定して返します。ワークスペースと顧客はどちらも署名付きトークンから取得するため、閲覧者が運営者の顧客一覧を見ることはありません。未公開のポータルは { client, published:false, last } のみを返し、それ以外は返しません。公開中の場合は、その顧客自身の端末情報(IMEI は末尾 6 桁以外をマスク、最大 200 行)と直近 20 件のチケットを追加します。Cache-Control: no-store。
パラメータ位置型必須説明
tquerystring○POST /api/portal/issue が発行するポータルトークン。顧客とワークスペースの両方に紐づき、有効期限があり、失効させることもできます。本番環境では必須です。本番以外では、デモ Space が動作し続けるよう旧形式の ?c=<顧客名> も受け付けます。
cquerystring旧形式(本番以外のみ): 顧客名。呼び出し元のワークスペース内で解決します。本番環境で動作している場合は一律に拒否されます。代わりに ?t= を使用してください。
レスポンス例
{"ok":true,"client":{"name":"北斗商事","slug":"hokuto"},"published":true,"last":"たった今","devices":{"total":124,"active":124,"computed":true,"list":[{"imei":"****539346","model":"iPhone 15","status":"保管中","chip":"c-blue","loc":"A-10"},...],"shown":124},"tickets":[{"id":"TK-PG56ZJ90F05","kind":"故障","subject":"端末が起動しません","status":"受付","created":1788114480741,"viaPortal":true}]} — 未公開なら {"ok":true,"client":{...},"published":false,"last":"たった今"} のみ
エラー
401 — {"ok":false,"code":"portal_link_invalid","error":"このリンクは無効または期限切れです"} — トークンが無い・改竄・期限切れ・失効
404 — {"ok":false,"code":"portal_not_found","error":"ポータルが見つかりません"}
500 — {"ok":false,"error":"ポータルを読み込めませんでした"}
POST/api/portal/inquirytoken
ポータル利用顧客からの問合せは、リンクが属するワークスペースの実際のヘルプデスクチケットになります(GET /api/tickets が読むものと同じ `tickets` コレクション)。応答には受付番号(TK-P…。構造上一意で、ポータル経由であることを示します)と受付時刻(エポックミリ秒)を返します。「ポータル経由の問い合わせ(今月)」カウンタは同じ処理で 1 回だけ加算されます。認証はセッションではなくポータルトークンで行います。失敗は送信済みと偽らず失敗(502)として報告し、不明または未公開のポータルからチケットが作成されることはありません。Cache-Control: no-store。
パラメータ位置型必須説明
tquerystringポータルトークン(?t= または body.t で送信可)。いずれの方法でも(本番環境では)必須です。
リクエスト
{"t":"<portal token>","kind":"故障","message":"端末が起動しません","name":"山田","email":"y@example.com"} — kind は 問合せ|故障|交換|紛失|返却|その他(既定 問合せ)。message は必須・2000字まで
レスポンス例
{"ok":true,"ref":"TK-PG56ZJ90F05","ticket":{"id":"TK-PG56ZJ90F05","status":"受付","kind":"故障","cust":"北斗商事"},"created":1788114480741}
エラー
400 — {"ok":false,"code":"message_required","error":"ご用件を入力してください。"}
401 — {"ok":false,"code":"portal_link_invalid","error":"このリンクは無効または期限切れです"}
404 — {"ok":false,"code":"portal_not_found","error":"ポータルが見つかりません"}
409 — {"ok":false,"code":"portal_unpublished","error":"このポータルは現在ご利用いただけません。"} — 未公開ポータルにはチケットを作りません
502 — {"ok":false,"code":"ticket_not_created","error":"送信できませんでした。お手数ですが時間をおいて再度お試しください。"} — 送信できなかったときは、できなかったと答えます
POST/api/portal/:custId公開
顧客ポータル 1 件を更新します。body.action: 'toggle'(既定。published の反転または設定、公開時は last='たった今' を設定)| 'ticket'(全体のチケット数を加算し last を設定)| 'dl'(全体のダウンロード数を加算)| 'touch'(body.last から last を設定)。更新後のポータルとカウンタを返します。
パラメータ位置型必須説明
custIdpathstring○顧客ID: hokuto|mitsumine|amagi|tosei|mizuki のいずれか。不明な場合は 404。
actionbodystringtoggle|ticket|dl|touch のいずれか(既定値 toggle、20文字で切り詰め)。不明な値は 400。
publishedbodybooleanaction=toggle の場合: 公開状態を明示指定(省略時は現在の値を反転)
lastbodystringaction=touch の場合: 最終アクセス表示(40文字で切り詰め)。既定値 'たった今'
リクエスト
{"action":"toggle","published":true,"last":"たった今"}
レスポンス例
{"ok":true,"portal":{"id":"tosei","name":"東成建設","slug":"tosei","published":true,"suffix":"1jip","last":"たった今"},"tickets":4,"dls":63}
POST/api/portal/issue公開
body.custId/id で指定した顧客のポータルを発行(公開)し、published=true と last='たった今' を設定して、公開ポータル URL '/portal.html?t=<name>' を返します。
パラメータ位置型必須説明
custIdbodystring○顧客ID(別名 'id' も可。40文字で切り詰め)。既知の顧客に一致しない場合は 400。
リクエスト
{"custId":"tosei"}
レスポンス例
{"ok":true,"url":"/portal.html?t=%E6%9D%B1%E6%88%90%E5%BB%BA%E8%A8%AD","portal":{"id":"tosei","name":"東成建設","slug":"tosei","published":true,"suffix":"1jip","last":"たった今"}}

QBR

四半期ビジネスレビュー。

GET/api/qbr/history公開実測 200
生成済み QBR の履歴を一覧します(新しい順、最大 20 件)。
レスポンス例
{"ok":true,"history":[]}
POST/api/qbr/check公開
QBR 資料の発行前チェックです。何も書き込みません。必須項目(顧客ID/顧客名/対象四半期ID/対象四半期)が空、アップセルの小計が内訳と一致しない、年額が月額の 12 倍でない、件数項目が 0 以上の整数でない、SLA の割合が 0–100 の範囲外、のいずれかの場合は、問題の数値を明示した 422 を返します。POST /api/qbr は記録前にまったく同じチェックを実行するため、ここで通過した資料は記録できます。
リクエスト
{"custId":"c1","cust":"北斗商事","qId":"2026Q2","q":"2026 Q2","date":"2026-07-22T00:00:00.000Z","figures":{"managed":100,"kit":0,"inbound":0,"outbound":0,"storage":0,"tickets":0,"incidents":0,"hours":0,"sla":99.4,"upsellMonthly":0,"upsellAnnual":0,"storeUplift":0,"addValue":0,"upDelta":0,"help":0}} — figures は任意。渡した項目だけが検算されます
レスポンス例
{"ok":true,"issues":[]}
エラー
422 — {"ok":false,"issues":["必須項目「顧客ID」が空です","必須項目「顧客名」が空です","必須項目「対象四半期ID」が空です","必須項目「対象四半期」が空です"]} / {"ok":false,"issues":["アップセル合計(月額) ¥100,000 が内訳合計 ¥4 と一致しません"]}
POST/api/qbr公開
生成した QBR を履歴に記録します。新しい記録と、上限付きの更新後履歴を返します。
パラメータ位置型必須説明
custIdbodystring○顧客ID(60文字で切り詰め)。必須、未指定は 400。
qIdbodystring○四半期ID(40文字で切り詰め)。必須、未指定は 400。
custbodystring顧客の表示名(120文字で切り詰め)
qbodystring四半期ラベル(60文字で切り詰め)
datebodystringISO 日付文字列(40文字で切り詰め)。省略時は現在の ISO タイムスタンプ。
リクエスト
{"custId":"c1","cust":"Acme","qId":"2026Q2","q":"2026 Q2","date":"2026-07-22T00:00:00.000Z"}
レスポンス例
{"ok":true,"record":{"custId":"c1","cust":"Acme","qId":"2026Q2","q":"2026 Q2","date":"2026-07-22T00:00:00.000Z"},"history":[{...}]}

ナーチャリング (Nurture)

リード育成・シーケンス。

GET/api/nurture公開実測 200
ナーチャリングの設定・履歴ドキュメント 1 件を返します(ステップごとの編集、カスタムのドリップシーケンス、送信履歴フラグ、自動リマインドのトグル)。
レスポンス例
{"ok":true,"doc":{"edits":{},"custom":[],"sent":{},"autoRemind":true}}
POST/api/nurture公開
ナーチャリングの設定・履歴ドキュメントを、上限サイズに整形・切り詰めたうえで保存(置換)します。
パラメータ位置型必須説明
editsbodyobjectステップ別の上書きマップ(キー 'seqId:idx' -> {subject(<=300), body(<=8000)}、最大500キー)
custombodyarrayユーザー定義のドリップシーケンス [{id,name,target,tone,desc,steps:[{day,subject,body}]}](最大100シーケンス、各40ステップ)
sentbodyobject送信履歴フラグのマップ 'leadId:seqId:idx' -> true(最大5000キー)
autoRemindbodyboolean更新リマインダーの自動送信切替(null・省略時は true)
リクエスト
{ "edits": { "seqId:0": {"subject":"...","body":"..."} }, "custom": [ {"id":"...","name":"...","target":"...","tone":"...","desc":"...","steps":[{"day":0,"subject":"...","body":"..."}]} ], "sent": {"leadId:seqId:0":true}, "autoRemind": true }
レスポンス例
{"ok":true,"doc":{"edits":{},"custom":[],"sent":{},"autoRemind":true}}

アカウント・サインイン (Account/Auth)

メール/パスワード・Google・電話番号でのサインアップとサインイン。

POST/api/account/signup公開
このブラウザがすでに使用している匿名ワークスペースを引き継ぐアカウントを作成します。署名付き kit_tid Cookie を設定し、セッショントークンを返します。registrationOpen がオフの場合は拒否され、IP ごとにレート・速度の上限があります。
リクエスト
{"email":"demo.user@example.com","password":"YOUR_PASSWORD","company":"北斗商事","name":"山田 太郎"}
レスポンス例
{"ok":true,"token":"<body>.<sig>","account":{"email":"demo.user@example.com","company":"北斗商事","name":"山田 太郎","tenantId":"t-…","created":"2026-08-27T20:52:56.379Z","lastLogin":null},"adoptedTenant":"t-…"}
POST/api/account/login公開
パスワードでサインインします。セッショントークンを返し、アカウントのワークスペース用に署名付き kit_tid Cookie を設定します。2FA(sec2FA)が有効な場合は代わりに mfaRequired:true とチャレンジ id を返し、/api/account/login/verify で完了させます。
リクエスト
{"email":"demo.user@example.com","password":"YOUR_PASSWORD"}
レスポンス例
{"ok":true,"token":"<body>.<sig>","account":{"email":"demo.user@example.com","company":"北斗商事","name":"山田 太郎","tenantId":"t-…","created":"2026-08-27T20:52:56.379Z","lastLogin":"2026-08-27T20:52:56.416Z"}}
POST/api/account/login/verify公開
/api/account/login で開始した 2FA ログインを、メールで届いたワンタイムコードとチャレンジ id を送信して完了します。
リクエスト
{"email":"demo.user@example.com","challenge":"<challenge id>","code":"123456"}
POST/api/account/logout公開
kit_tid Cookie を消去し、共用端末でワークスペースのデータが漏れないようにします。
レスポンス例
{"ok":true}
GET/api/account/me公開
呼び出し元がサインイン中かどうかを返します。セッショントークンがなければ signedIn:false と匿名の tenantId を、有効な Bearer トークンがあれば signedIn:true とアカウントプロフィールを返します。
レスポンス例
{"ok":true,"signedIn":false,"tenantId":"t-…"} | {"ok":true,"signedIn":true,"account":{"email":"owner.demo@example.com","company":"北斗商事","name":"山田 太郎","tenantId":"t-…","created":"2026-08-27T20:54:38.468Z","lastLogin":null}}
POST/api/account/password要サインイン
現在のパスワードを確認したうえで、サインイン中アカウントのパスワードを変更します。発行済みのセッショントークンはすべて無効になり、新しいトークンを返します。
リクエスト
{"current":"<current password>","next":"<new password>"}
レスポンス例
{"ok":true,"token":"<body>.<sig>"}
GET/api/auth/methods公開
このデプロイで設定済みのサインイン方法を返します。password は常に true で、google、phone、sso(Enterprise OIDC、routes/sso.js)はそれぞれのプロバイダの資格情報が設定されているかを示します。
レスポンス例
{"ok":true,"password":true,"google":false,"phone":false,"sso":false}
GET/api/auth/google/start公開
Google OAuth を開始します。現在のテナントを含む署名付き・有効期限 10 分の state を付けて、Google の同意画面へ 302 リダイレクトします。Google ログインが未設定の場合は 503 です。
GET/api/auth/google/callback公開
Google OAuth のコールバックです。state を検証してコードを交換し、アカウントを検索または作成して kit_tid Cookie を設定し、URL フラグメント(#gt=…)にセッショントークンを付けて /login.html へ 302 リダイレクトします。失敗時は /login.html?err=… にリダイレクトします。
パラメータ位置型必須説明
codequerystring—Google から返された認可コード。
statequerystring—/api/auth/google/start が発行した署名付き state。無効な state の場合は /login.html?err=state にリダイレクトします。
POST/api/auth/phone/start公開
指定した電話番号に SMS のワンタイムコードを送信します。電話番号ログインが未設定の場合は 503 です。
リクエスト
{"phone":"+819012345678"}
レスポンス例
{"ok":true}
POST/api/auth/phone/verify公開
SMS コードを検証し、電話番号をキーとするアカウント(tel:+81…)を検索または作成して kit_tid Cookie を設定し、セッショントークンを返します。
リクエスト
{"phone":"+819012345678","code":"123456"}

課金 (Billing/Stripe)

プランカタログ・Stripe Checkout・Webhook。

GET/api/billing/plans公開
公開のプランカタログ(key、name、priceJpy、limits、features)と、このデプロイで Stripe が設定済みかどうかを返します。秘密情報は含みません。
レスポンス例
{"ok":true,"plans":[{"key":"starter","name":"Starter","priceJpy":128000,"limits":{"devices":100,"members":3,"customers":10},"features":["デバイス最大100台 / メンバー3名","キッティング台帳・出荷管理","MDM連携・基本レポート","メールサポート"]},{"key":"business","name":"Business","priceJpy":388000,"limits":{"devices":300,"members":10,"customers":30},"features":[…]},{"key":"enterprise","name":"Enterprise","priceJpy":908000,"limits":{"devices":500,"members":30,"customers":100},"features":[…]}],"stripeConfigured":false}
GET/api/billing/subscription公開
呼び出し元ワークスペースの現在のプランキーとサブスクリプション状態(一度も設定されていない場合は status "none")、および stripeConfigured を返します。
レスポンス例
{"ok":true,"planKey":"starter","status":"none","stripeConfigured":false}
POST/api/billing/checkout公開
Stripe が設定済み(stripeConfigured:true)の場合に、指定したプランの Stripe Checkout Session を開始します。webhook が結果を正しいワークスペースに反映できるよう、テナント id を client_reference_id と metadata に含めます。課金が未設定の場合は 503 を返します。
リクエスト
{"planKey":"business"}
レスポンス例(200 — Stripe 設定済みの場合のみ)
{"ok":true,"url":"https://checkout.stripe.com/c/pay/cs_test_example"}
レスポンス例(503 — stripeConfigured:false)
{"ok":false,"error":"billing not configured"}
POST/api/billing/webhook公開
Stripe の webhook です。生の body は解析前に STRIPE_WEBHOOK_SECRET で HMAC 検証し、イベント id は重複排除(リプレイ対策)されます。checkout/subscription イベントによってテナントのプランを設定します。
パラメータ位置型必須説明
stripe-signatureheaderstring○Stripe の署名ヘッダー(t=…,v1=…)。検証に失敗した本文は 400 で拒否され、解析されることはありません。

キャパシティ (Capacity)

キッティング能力・保管枠と計画負荷。

GET/api/capacity公開
このワークスペースのキャパシティ状態全体を返します。保存済みの設定、日付順の全計画負荷エントリ、算出した週ビュー、およびサマリーです。
レスポンス例
{"ok":true,"config":{"kittingDaily":192,"storageMax":240,"storageUsed":178,"palletMax":8,"palletUsed":5,"warehouseMax":240,"warehouseUsed":116,"staffCount":2,"perStaff":80,"updated":1787863913818},"load":[{"id":"CAP-0001","date":"2026-08-28","created":1787863913818,"cust":"北斗商事","qty":62,"kind":"kitting","note":"LCM 交換・再キッティング"},…],"week":[…],"summary":{…}}
POST/api/capacity/config公開
このワークスペースのキャパシティ設定を保存・部分更新します。省略した数値項目は現在の値を維持し、updated はサーバー側で記録します。
リクエスト
{"kittingDaily":200,"staffCount":3}
レスポンス例
{"ok":true,"config":{"kittingDaily":200,"storageMax":0,"storageUsed":0,"palletMax":0,"palletUsed":0,"warehouseMax":0,"warehouseUsed":0,"staffCount":3,"perStaff":80,"updated":1787863957335}}
POST/api/capacity/load公開
計画負荷エントリを追加します。次の CAP-#### id はサーバーが割り当てます。
リクエスト
{"date":"2026-09-10","cust":"北斗商事","qty":40,"kind":"kitting","note":"新規"}
レスポンス例
{"ok":true,"entry":{"id":"CAP-0001","date":"2026-09-10","cust":"北斗商事","qty":40,"kind":"kitting","note":"新規","created":1787863957344}}
POST/api/capacity/load/:id公開
負荷エントリ 1 件の date / cust / qty / kind / note を更新します。省略した項目は変更しません。
パラメータ位置型必須説明
idpathstring○負荷エントリID(例: 'CAP-0001')。不明な場合は 404 {ok:false,error:'load entry not found'}。
リクエスト
{"qty":55}
レスポンス例
{"ok":true,"entry":{"id":"CAP-0001","date":"2026-09-10","cust":"北斗商事","qty":55,"kind":"kitting","note":"新規","created":1787863957344}}
POST/api/capacity/load/:id/delete公開
搬入予定を1件削除します。
パラメータ位置型必須説明
idpathstring○負荷エントリID(例: 'CAP-0001')
レスポンス例
{"ok":true,"id":"CAP-0001"}

DaaS (Device as a Service)

DaaS 見積ポートフォリオ・シミュレータ・提案送付履歴。

GET/api/daas公開
このワークスペースの DaaS 状態(見積/契約ポートフォリオ、保存済みシミュレータ設定(未保存の場合は null)、提案送付履歴)を返します。
レスポンス例
{"ok":true,"quotes":[{"id":"DQ-DEMO1","cust":"天城製薬","model":"iPhone 16","qty":1800,"term":36,"res":20,"lcm":620,"war":"full","monthly":5120,"mrr":9216000,"ts":1},…],"sim":null,"sends":[]}
POST/api/daas/quote公開
DaaS の見積/契約を作成または更新します。ポートフォリオには上限があり、古いものから削除されます。
リクエスト
{"cust":"北斗商事","model":"iPhone 16","qty":100,"term":36,"res":20,"lcm":600,"war":"full"}
レスポンス例
{"ok":true,"quote":{"id":"DQmtc01egb0","cust":"北斗商事","model":"iPhone 16","qty":100,"term":36,"res":20,"lcm":600,"war":"full","monthly":0,"mrr":0,"ts":1787863957355}}
POST/api/daas/quote/:id/status公開
DaaS 見積を 下書き(draft) → 提案中(proposed) → 承認(approved) → 契約中(contracted) の順に進めます。前進は1段階ずつのみで、段階を飛ばすと 400 stage skipped で拒否され、次に許可される唯一の段階が示されます。承認 と 契約中 にはさらに顧客と期限内の 有効期限 が必須です。いずれかが欠けている見積は不足フィールドを列挙した 400 で拒否され、有効期限が今日より前の場合は 400 quote expired で拒否されます。それより前の任意の段階への差し戻しは常に可能で、契約日 がクリアされます。totals.mrr / totals.units に計上されるのは 契約中 の見積のみで、それより前の段階は pipeline* に集計されます。
パラメータ位置型必須説明
idpathstring○DaaS 見積ID(例: 'DQ-DEMO1')
リクエスト
{"status":"approved"} — draft|proposed|approved|contracted のいずれか
レスポンス例
{"ok":true,"quote":{"id":"DQmtg56zikh","cust":"北斗商事","model":"iPhone 16","qty":100,"term":36,"res":20,"lcm":600,"war":"full","monthly":5000,"mrr":500000,"expires":"2027-03-31","ts":1788114480716,"status":"approved","statusTs":1788114480721,"statusLabel":"承認"},"from":"proposed","totals":{"units":3950,"mrr":18013000,"arr":216156000,"contracts":4,"pipelineUnits":100,"pipelineMrr":500000,"byStatus":{"draft":0,"proposed":0,"approved":1,"contracted":4}}}
エラー
400 — 段跳ばし: {"ok":false,"error":"stage skipped","from":"proposed","to":"contracted","next":"approved"} | 未知の状態: {"ok":false,"error":"unknown status","statuses":["draft","proposed","approved","contracted"]} | 条件未充足: {"ok":false,"error":"customer and expiry required","missing":["cust","expires"],"needs":["顧客","有効期限"]} | 期限切れ: {"ok":false,"error":"quote expired","expires":"2026-03-31"}
404 — {"ok":false,"error":"quote not found"}
POST/api/daas/quote/:id/delete公開
ポートフォリオから見積を1件削除します。
パラメータ位置型必須説明
idpathstring○見積ID(例: 'DQ-DEMO1')
レスポンス例
{"ok":true,"id":"DQmtc03hi5b"}
POST/api/daas/sim公開
このワークスペースのシミュレータ設定(model、qty、term、residual、LCM、warranty、customer)を保存します。
リクエスト
{"qty":100,"term":36}
レスポンス例
{"ok":true,"sim":{"model":"","qty":100,"term":36,"res":0,"lcm":0,"war":"none","cust":""}}
POST/api/daas/send公開
提案送付履歴を1件追加します(新しい順、最大50件)。
リクエスト
{"cust":"北斗商事","doc":"提案書"}
レスポンス例
{"ok":true,"send":{"ts":1787863957369,"cust":"北斗商事","channel":"","to":"","model":"","qty":0,"mrr":0}}

付帯品受注 (Store)

付帯品カタログと受注。

GET/api/store/catalog公開
付帯品カタログ: 組み込みの参照マスタにこのワークスペースのカスタム商品を連結したものと、カテゴリ一覧を返します。
レスポンス例
{"ok":true,"catalog":[{"id":"p-rug","name":"耐衝撃ケース(現場用)","cat":"ケース","ic":"🛡","price":2800,"cost":1180,"note":"現場向け"},{"id":"p-case","name":"TPUクリアケース","cat":"ケース","ic":"📱","price":1200,"cost":420},…],"cats":[…]}
GET/api/store/orders公開
このワークスペースの付帯品受注履歴と件数を返します。
レスポンス例
{"ok":true,"orders":[{"id":"AO-202608-8220","date":"2026-08-27T20:53:36.583Z","dateStr":"2026/8/28","cust":"北斗商事","job":"KIT-2026-311","dest":"本社 情シス部","count":40,"total":48000,"gp":34400,"lines":[{"id":"p-glass","name":"保護ガラス(9H)","price":1200,"cost":340,"qty":40}],"status":"確定"}],"count":1}
POST/api/store/order公開
付帯品の受注を作成します。count、total、gp は明細行からサーバー側で算出されます。
リクエスト
{"cust":"北斗商事","job":"KIT-2026-311","dest":"本社 情シス部","lines":[{"id":"p-glass","name":"保護ガラス(9H)","price":1200,"cost":340,"qty":40}]}
レスポンス例
{"ok":true,"order":{"id":"AO-202608-8220","date":"2026-08-27T20:53:36.583Z","dateStr":"2026/8/28","cust":"北斗商事","job":"KIT-2026-311","dest":"本社 情シス部","count":40,"total":48000,"gp":34400,"lines":[{"id":"p-glass","name":"保護ガラス(9H)","price":1200,"cost":340,"qty":40}],"status":"確定"}}
POST/api/store/order/:id公開
受注1件の status / cust / job / dest を更新します。明細行と算出済みの合計はここでは変更されません。
パラメータ位置型必須説明
idpathstring○注文ID(例: 'AO-202608-8220')
リクエスト
{"status":"出荷済"}
レスポンス例
{"ok":true,"order":{"id":"AO-202608-8220","date":"2026-08-27T20:53:36.583Z","dateStr":"2026/8/28","cust":"北斗商事","job":"KIT-2026-311","dest":"本社 情シス部","count":40,"total":48000,"gp":34400,"lines":[{"id":"p-glass","name":"保護ガラス(9H)","price":1200,"cost":340,"qty":40}],"status":"出荷済"}}
POST/api/store/order/:id/delete公開
付帯品の受注を1件削除します。
パラメータ位置型必須説明
idpathstring○注文ID(例: 'AO-202608-8220')
レスポンス例
{"ok":true,"id":"AO-202608-8220"}
POST/api/store/product公開
ワークスペース独自のカタログ商品(custom:true)を追加します。追加した商品は GET /api/store/catalog で参照マスタの後に表示されます。
リクエスト
{"name":"USB-Cハブ","cat":"電源","price":3800,"cost":1500}
レスポンス例
{"ok":true,"product":{"id":"p-mtc01eh52","name":"USB-Cハブ","cat":"電源","ic":"📦","price":3800,"cost":1500,"custom":true}}

買取・リファービッシュ (Trade-in)

買取査定・リファービッシュ在庫・買取証書。

GET/api/tradein公開
このワークスペースの買取状態(買取台帳、リファービッシュ在庫、買取受領書)を返します。
レスポンス例
{"ok":true,"buybacks":[{"id":"BB-DEMO01","date":"2026-07-04","model":"iPhone 15","cust":"北斗商事","grade":"A","bat":92,"offer":56400,"resell":76100,"margin":17200,"residual":0.5},…],"inventory":[…],"receipts":[…]}
POST/api/tradein/buyback公開
買取レコードを作成または更新します(margin と residual はサーバー側で算出)。
リクエスト
{"model":"iPhone 15","cust":"北斗商事","grade":"A","bat":92,"offer":56400,"resell":76100}
レスポンス例
{"ok":true,"buyback":{"id":"BB-mtc01ehu4","date":"2026-08-27","model":"iPhone 15","cust":"北斗商事","grade":"A","bat":92,"offer":56400,"resell":76100,"margin":0,"residual":0}}
POST/api/tradein/buyback/:id/delete公開
買取レコードを1件削除します。
パラメータ位置型必須説明
idpathstring○買取ID(例: 'BB-DEMO01')
レスポンス例
{"ok":true,"id":"BB-mtc03hed8"}
POST/api/tradein/inventory公開
リファービッシュ在庫を1件作成または更新します。
リクエスト
{"model":"iPhone 14","grade":"B"}
レスポンス例
{"ok":true,"stock":{"id":"RF-mtc02o5r7","model":"iPhone 14","grade":"B","cost":0,"ask":0,"margin":0}}
POST/api/tradein/inventory/:id/delete公開
リファービッシュ在庫を1件削除します。
パラメータ位置型必須説明
idpathstring○在庫ID(例: 'RF-mtc02o5r7')
レスポンス例
{"ok":true,"id":"RF-mtc03hf99"}
POST/api/tradein/receipt公開
受領書番号(no)をキーに買取受領書を作成または更新します。
リクエスト
{"cust":"北斗商事"}
レスポンス例
{"ok":true,"receipt":{"no":"KIT-BUY-2026-0001","date":"2026-08-27","dateJa":"2026/8/28","cust":"北斗商事","person":"","items":[],"total":0,"ts":1787864016602}}
POST/api/tradein/receipt/:id/delete公開
受領書番号を指定して買取受領書を1件削除します。
パラメータ位置型必須説明
idpathstring○受付番号(例: 'KIT-BUY-2026-0001')
レスポンス例
{"ok":true,"id":"KIT-BUY-2026-0001"}

サポート送付・ウィジェット (Support)

資料送付履歴とサポートウィジェット設定。

GET/api/support/widget公開
このワークスペースのサポートウィジェット設定を、組み込みの既定値をマージして返します。
レスポンス例
{"ok":true,"widget":{"primaryColor":"#2cc5e8","title":"サポート","launcherText":"お困りですか?","position":"bottom-right","allowAttach":true,"allowVoice":true}}
POST/api/support/widget公開
サポートウィジェット設定をマージ更新します。クライアントは変更したキーのみを送信します。
リクエスト
{"title":"サポート窓口"}
レスポンス例
{"ok":true,"widget":{"primaryColor":"#2cc5e8","title":"サポート窓口","launcherText":"お困りですか?","position":"bottom-right","allowAttach":true,"allowVoice":true}}
GET/api/support/sends公開
資料送付履歴を古い順に返します(クライアントのログ順と一致)。
レスポンス例
{"ok":true,"sends":[]}
POST/api/support/send公開
資料送付を1件記録します(doc と送付先は必須。channel の既定値は メール)。
リクエスト
{"doc":"見積書","to":"info@example.com"}
レスポンス例
{"ok":true,"send":{"id":"snd-mtc01ehe3","doc":"見積書","to":"info@example.com","channel":"メール","msg":"","at":1787863957394}}
POST/api/support/send/:id/delete公開
送付履歴を1件削除します。
パラメータ位置型必須説明
idpathstring○送付記録ID(例: 'snd-mtc01ehe3')
レスポンス例
{"ok":true}

月次レポート (Report)

顧客別・月次のレポート生成と保存。

GET/api/reports公開
このワークスペースの保存済みレポートを新しい順に、件数とともに返します。
レスポンス例
{"ok":true,"reports":[],"count":0}
GET/api/report/generate公開
このワークスペース自身の記録からレポートのプレビューを算出します。保存はしません。期間内に算出できるものが何もない場合、hasData は false になります。
パラメータ位置型必須説明
custquerystring—レポートの対象とする顧客名。省略時は 全顧客。
monthquerystring—対象月(YYMM 形式、例: '2608')。既定値は当月。
jobIdquerystring—指定するとジョブ単位のレポートになります(imeis/events/figures.dev はそのジョブ分のみ。id の末尾は -<jobId>。scope.dev=job、scope.label=ジョブ限定)。省略時は顧客単位の集計(id の末尾は -ALL。scope.label=顧客横断(ジョブ非限定))。
レスポンス例
{"ok":true,"report":{"id":"RPT-2608-all-ALL","cust":"","custLabel":"全顧客","month":"2608","monthLabel":"2026年8月度","jobId":"","hasData":false,"figures":{"dev":178,"kit":0,"swap":0,"tk":0,"slaPct":null,"sla":"—","lost":0,"wipe":0,"inb":0,"out":0,"store":178,"revenue":0,"wipeCerts":27},"scope":{"kit":"month","swap":"month","tk":"month","slaPct":"month","sla":"month","lost":"month","wipe":"month","inb":"month","out":"month","revenue":"month","dev":"aggregate","label":"顧客横断(ジョブ非限定)","store":"current","wipeCerts":"current"},"asOf":1787863913867,"undated":{"jobs":0,"tickets":0,"shipments":0},"generatedAt":1787863913867},"hasData":false}
POST/api/report/generate公開
レポートを算出し、保存します。ID 体系: ジョブ単位は RPT-<YYMM>-<cust>-<jobId>、集計(jobId なし)は RPT-<YYMM>-<cust>-ALL。旧形式の RPT-<YYMM>-<cust> の ID は引き続き読み取り可能で、集計の生成によって上書きされることはありません。scope.dev は job|aggregate、scope.label は ジョブ限定 または 顧客横断(ジョブ非限定)。figures.dev は ジョブ登録台数(ジョブに紐づく台数。figures.devLabel)であり、全体の 管理台数 ではありません。jobId "ALL" → 400 job_id_reserved、不明な jobId → 404 job_not_found(いずれも保存されません)。ジョブ単位の数値はそのジョブのみを対象とします。
リクエスト
{"cust":"北斗商事","month":"2608","jobId":"job-…" /* optional; omit for 顧客横断(ジョブ非限定) */}
レスポンス例
{"ok":true,"report":{"id":"RPT-2608-all-ALL","cust":"","custLabel":"全顧客","month":"2608","monthLabel":"2026年8月度","hasData":false,"figures":{…},"scope":{…},"asOf":1787863942144,"undated":{"jobs":0,"tickets":0,"shipments":0},"generatedAt":1787863942144},"hasData":false}
GET/api/report/:id公開
保存済みレポートを ID で1件取得します。
パラメータ位置型必須説明
idpathstring○レポートID(例: 'RPT-2608-all-ALL'(集計)または 'RPT-2608-<cust>-<jobId>)。旧形式の RPT-2608-all も引き続き参照可能。不明な場合は 404 {ok:false,error:'report not found'}。
レスポンス例
{"ok":true,"report":{"id":"RPT-2608-all-ALL","cust":"","custLabel":"全顧客","month":"2608","monthLabel":"2026年8月度","jobId":"","hasData":false,"figures":{…},"scope":{"dev":"aggregate","label":"顧客横断(ジョブ非限定)"},"asOf":1787863942144,"undated":{"jobs":0,"tickets":0,"shipments":0},"generatedAt":1787863942144}}

受入AI (Intake/Vision)

端末受入の画像認識・訂正記録・実測精度・AI利用量。

POST/api/intake/recognize公開
写真から端末を認識します(カタログ指定は任意)。認識できない場合は HTTP 200 で {ok:false,reason,manualEntryRequired:true} を返し、推測した機種を返すことはありません。IP ごとに上限あり(VISION_MAX / VISION_WINDOW_MS)。上限に達したリクエストは計量されません。
リクエスト
{"image":"<base64>","mediaType":"image/png","catalogue":["iPhone 15","iPhone 15 Pro"]}
レスポンス例(ANTHROPIC_API_KEY 未設定の環境で取得)
{"ok":false,"reason":"no_key","manualEntryRequired":true}
POST/api/intake/correction公開
AI の回答とオペレーターが確定した内容を記録し、認識精度を自称ではなく実測で評価できるようにします。
リクエスト
{"recognized":"iPhone 15","corrected":"iPhone 15 Pro","confidence":0.82,"imei":"356247446539346"}
レスポンス例
{"ok":true,"correction":{"id":"cor-mtc01t7c6","recognized":"iPhone 15","corrected":"iPhone 15 Pro","wrong":true,"confidence":0.82,"imei":"356247446539346","at":1787863976472}}
GET/api/intake/accuracy公開
訂正記録から算出した実測の認識精度を返します: サンプル数、誤認識数、精度(サンプルがない場合は null)、誤認識時にモデルが報告した平均信頼度、手入力件数。
レスポンス例
{"ok":true,"samples":0,"wrong":0,"accuracy":null,"avgConfidenceWhenWrong":null,"manualEntries":0}
GET/api/ai/usage公開
AI アドオンの課金根拠となる AI 利用量カウンタ(vision / search の呼び出し数と成功率)を返します。
レスポンス例
{"ok":true,"usage":{}}

為替レート (FX)

外部ソースから取得した USD/JPY レート。

GET/api/fx公開
現在の USD/JPY レートを、取得元、取得時刻、次回更新予定、stale フラグとともに返します。5分間キャッシュされます。
レスポンス例
{"ok":true,"base":"JPY","quote":"USD","rate":0.006274549173641874,"usdJpy":159.37,"updatedAt":"2026-08-27T20:51:03.268Z","nextUpdateAt":"2026-08-27T21:00:00.000Z","refreshesPerDay":4,"source":"yahoo (USDJPY=X, intraday)","stale":false}
POST/api/fx/refresh公開
上流のレート取得元から強制的に再取得し、GET /api/fx と同じペイロードを返します。取得に失敗してもエラーにはならず、前回のレートが stale を反映した状態で返されます。
レスポンス例
{"ok":true,"base":"JPY","quote":"USD","rate":0.006274431065963093,"usdJpy":159.38,"updatedAt":"2026-08-27T20:52:37.557Z","nextUpdateAt":"2026-08-27T21:00:00.000Z","refreshesPerDay":4,"source":"yahoo (USDJPY=X, intraday)","stale":false}

管理者 (Admin)

主管理者認証・テナント管理・サブ管理者CRUD。要adminトークン

POST/api/admin/login公開
主管理者ログイン。パスワードが ADMIN_PASSWORD と一致した場合、有効期間8時間の HMAC 署名付き Bearer トークンを返します。
パラメータ位置型必須説明
passwordbodystring○主管理者パスワード(環境変数 ADMIN_PASSWORD で設定。公開の既定値はありません)
リクエスト
{"password":"YOUR_ADMIN_PASSWORD"}
レスポンス例
{"ok":true,"token":"<body>.<sig>"} | 401 {"ok":false,"error":"パスワードが違います"}
GET/api/admin/tenantsadmin実測 401
全テナントと集計値(合計、active/trial/suspended の件数、MRR、端末数、シート数、サイト数、クライアント数)を返します。
パラメータ位置型必須説明
tokenquerystring管理者トークン(Authorization: Bearer ヘッダーの代替)
レスポンス例
{"ok":true,"tenants":[{"id":"t-itabashi","name":"板橋キッティングセンター","plan":"Business","seats":180,"used":120,"status":"active","mrr":582000,"devices":1204,"clients":[...],"features":{...}}],"stats":{"total":5,"active":3,"trial":1,"suspended":1,"mrr":2487000,...},"origin":"https://..."}
GET/api/admin/tenant/:idadmin実測 401
テナントを1件、派生したクライアントダッシュボード URL と公開サイト URL とともに取得します。
パラメータ位置型必須説明
idpathstring○テナントID(例: t-itabashi)
tokenquerystring管理者トークン(Bearer ヘッダーの代替)
レスポンス例
{"ok":true,"tenant":{...},"dashboards":[{"client":"北斗商事","url":".../portal.html?t=..."}],"published":[{"slug":"itabashi-kitting","url":".../site/itabashi-kitting","live":true}],"origin":"https://..."}
POST/api/admin/tenant/:idadmin
既存テナントの編集可能フィールド(name、plan、seats、used、status、email、devices、mrr、features、clients)を更新します。
パラメータ位置型必須説明
idpathstring○更新対象のテナントID
namebodystringテナントの表示名
planbodystringStarter|Business|Enterprise
seatsbodynumber契約シート数
usedbodynumber使用中のシート数
statusbodystringactive|trial|suspended
emailbodystring連絡先メールアドレス
devicesbodynumber管理端末数
mrrbodynumber月次経常収益(MRR)
featuresbodyobject既存の設定にマージする機能フラグオブジェクト
clientsbodyarrayクライアント名の配列(最大200件)
リクエスト
{"plan":"Enterprise","seats":300,"status":"active","features":{"daas":true}}
レスポンス例
{"ok":true,"tenant":{...updated...}}
POST/api/admin/tenantadmin
新規テナントを作成します(ID は 't-<slug>-<hex>' で自動生成)。既定値は Starter/trial で、基本の機能フラグが設定されます。
パラメータ位置型必須説明
namebodystringテナント名(最大80文字)。既定値 '新規テナント'
planbodystringプラン(既定値 Starter)
seatsbodynumberシート数(既定値 3)
emailbodystring連絡先メールアドレス
リクエスト
{"name":"新規センター","plan":"Business","seats":50,"email":"x@example.jp"}
レスポンス例
{"ok":true,"tenant":{"id":"t-...-a1b2","status":"trial","used":0,"mrr":0,"features":{...}}}
POST/api/admin/tenant/:id/deleteadmin
テナントをストアから削除し、保存します。
パラメータ位置型必須説明
idpathstring○削除対象のテナントID
レスポンス例
{"ok":true}
POST/api/admin/tenant/:id/clientadmin
テナントにクライアント名を追加し、そのクライアントのポータルダッシュボード URL を返します。
パラメータ位置型必須説明
idpathstring○テナントID
clientbodystring○クライアント名(最大80文字。空の場合は 400)
リクエスト
{"client":"新規クライアント"}
レスポンス例
{"ok":true,"url":".../portal.html?t=%E6%96%B0%E8%A6%8F..."}
POST/api/admin/tenant/:id/client/revokeadmin
顧客ポータルのアクセストークンを失効させる。以後、その顧客に発行済みの /portal.html?t=… は全て無効になり、再発行が必要。
パラメータ位置型必須説明
idpathstring○テナントID
リクエスト
{"client":"北斗商事"}
レスポンス例
{"ok":true,"client":"北斗商事","revocations":1}
エラー
400 — {"ok":false,"error":"client name required"} — client が未指定
401 — {"ok":false,"error":"unauthorized"} — 管理者トークンがありません
404 — {"ok":false,"error":"not found"} — テナントが存在しない
POST/api/admin/impersonate/:idadmin
指定テナントのアシストモード('admin_as')用アプリ URL を返します(アプリには注意バナーが表示されます)。
パラメータ位置型必須説明
idpathstring○代理ログインするテナントID
レスポンス例
{"ok":true,"url":".../app?admin_as=%E6%9D%BF%E6%A9%8B..."}
GET/api/admin/subadminsadmin実測 401
全サブ管理者(公開可能なフィールドのみ、パスワードなし)と、割り当て用の簡易テナント一覧 {id,name} を返します。
パラメータ位置型必須説明
tokenquerystring管理者トークン(Bearer ヘッダーの代替)
レスポンス例
{"ok":true,"subadmins":[{"id":"sa-demo","name":"サポート担当 桐生","email":"subadmin@example.com","tenants":["t-itabashi","t-nagoya"],"perms":{"canDelete":true},"active":true,"created":"2026-06-01"}],"tenants":[{"id":"t-itabashi","name":"板橋キッティングセンター"}]}
POST/api/admin/subadminadmin
サブ管理者を作成します。必須の name/email と email の一意性を検証し、パスワード未指定の場合は自動生成します。
パラメータ位置型必須説明
namebodystring○サブ管理者名(最大80文字)
emailbodystring○一意のメールアドレス
passwordbodystringログインパスワード(省略時はランダムな16進文字列)
tenantsbodyarray担当テナントIDの配列(最大200件)
canDeletebodyboolean削除権限を付与
リクエスト
{"name":"新担当","email":"new.subadmin@example.com","tenants":["t-osaka"],"canDelete":false}
レスポンス例
{"ok":true,"subadmin":{...},"password":"<pass>"}
POST/api/admin/subadmin/:idadmin
サブ管理者の name、email、パスワード、割り当てテナント、canDelete 権限、active フラグを更新します。
パラメータ位置型必須説明
idpathstring○サブ管理者ID
namebodystring新しい名前
emailbodystring新しいメールアドレス
passwordbodystring新しいパスワード
tenantsbodyarray担当テナントIDの再割り当て
canDeletebodyboolean削除権限の切替
activebodybooleanアカウントの有効化・無効化
リクエスト
{"active":false,"canDelete":true}
レスポンス例
{"ok":true,"subadmin":{...updated...}}
POST/api/admin/subadmin/:id/deleteadmin
サブ管理者を削除し、保存します。
パラメータ位置型必須説明
idpathstring○削除対象のサブ管理者ID
レスポンス例
{"ok":true}
GET/api/admin/backupsadmin実測 401
全体のバックアップログ(全テナント横断で新しい順に最大120件のスナップショット)と日次バックアップの状態を返します。
パラメータ位置型必須説明
tokenquerystring管理者トークン(Bearer ヘッダーの代替)
レスポンス例
{"ok":true,"log":[{"tenantId":"t-itabashi","tenantName":"板橋キッティングセンター","id":"bk-...","ts":1699999999999,"by":"system","reason":"日次自動バックアップ","sites":1}],"daily":{"last":1699999999999,"tenants":5}}
GET/api/admin/activityadmin実測 401
監査/操作ログを返します(新しい順、最大200件)。
パラメータ位置型必須説明
tokenquerystring管理者トークン(Bearer ヘッダーの代替)
レスポンス例
{"ok":true,"activity":[{"ts":1699999999999,"by":"サポート担当 桐生","role":"subadmin","action":"パスワードを変更","tenantId":"","tenantName":"","detail":""}]}
GET/api/admin/workspacesadmin
実際の顧客一覧: サインアップ済みの全アカウントと実際に適用されているプラン(planKey/planStatus/planSource + limits)、プランカタログ、OPERATOR_TENANT の設定状態を返します。
レスポンス例
{"ok":true,"workspaces":[{"email":"demo.user@example.com","company":"北斗商事","name":"山田 太郎","tenantId":"t-…","created":"2026-08-27T20:52:56.379Z","lastLogin":"2026-08-27T20:53:22.052Z","planKey":"starter","planStatus":"none","planSource":"default","limits":{"devices":100,"members":3,"customers":10}}],"plans":[{"key":"starter","name":"Starter","priceJpy":128000,"limits":{"devices":100,"members":3,"customers":10}},{"key":"business","name":"Business","priceJpy":388000,"limits":{"devices":300,"members":10,"customers":30}},{"key":"enterprise","name":"Enterprise","priceJpy":908000,"limits":{"devices":500,"members":30,"customers":100}}],"operatorTenant":{"configured":false,"value":null,"resolves":false,"affects":["/d/<slug>-<suffix>/<last6> の端末ステータスページ","公開フォームからのリード/予約の帰属先"],"note":"OPERATOR_TENANT が未設定です。…"}}
POST/api/admin/workspace/:tid/planadmin
ワークスペースに実際に適用するプランを付与・変更します(Stripe のセルフサービスではなく請求書払いの顧客向けの上書き)。操作ログに記録し、変更前後のプランを返します。
パラメータ位置型必須説明
tidpathstring○GET /api/admin/workspaces で取得したワークスペース(テナント)ID。形式が不正な場合は 400、どのアカウントにも所有されていない場合は 404 {ok:false,error:'no such workspace'}。
リクエスト
{"planKey":"business","status":"active","reason":"invoice-billed"}
レスポンス例
{"ok":true,"tenantId":"t-…","planKey":"business","status":"active","previous":"starter","limits":{"devices":300,"members":10,"customers":30}}
POST/api/admin/workspace/:tid/impersonateadmin
アシストモード: ワークスペースを所有するアカウントの短期セッションを発行し、/app?admin_as=… のリンクを返します。付与されるのはその顧客自身の権限のみで(それ以上の権限や他テナントへのアクセスは一切なし)、顧客がパスワードを変更した時点で終了します。assist-start として記録されます。
パラメータ位置型必須説明
tidpathstring○GET /api/admin/workspaces で取得したワークスペース(テナント)ID。
レスポンス例
{"ok":true,"url":"https://kit-agent.ai-sns.io/app?admin_as=%E5%8C%97%E6%96%97%E5%95%86%E4%BA%8B&assist=<token>","expiresAt":1787865802201}
GET/api/admin/accountsadmin
全エンドユーザーアカウント(email、company、name、tenantId、created、lastLogin)を返します。パスワード関連の情報は返しません。
レスポンス例
{"ok":true,"accounts":[]}
POST/api/admin/account/:email/deleteadmin
エンドユーザーアカウントを1件削除します。ワークスペースのデータ本体は残るため復元可能です。テナントのゲートが解除されるのは、そのテナントを所有するアカウントが他に残っていない場合のみです。
パラメータ位置型必須説明
emailpathstring○URL エンコードしたアカウントのメールアドレス(例: 'demo.user%40example.com')
レスポンス例(404 の場合を取得。200 の本文は {ok:true,removed:{email,tenantId}})
{"ok":false,"error":"account not found"}
GET/api/admin/configadmin
セキュリティ設定を含むサイト全体の設定、meta(updatedAt/updatedBy)、出荷時の既定値を返します。
レスポンス例
{"ok":true,"config":{"maintenanceMode":false,"maintenanceMessage":"ただいまメンテナンス中です。しばらくしてから再度お試しください。","registrationOpen":true,"announcementEnabled":false,"announcementText":"","announcementLevel":"info","demoEnabled":true,"signinEnabled":true,"chatBubbleEnabled":true,"primaryCtaLabel":"","secEnabled":true,"secIpGuard":true,"secIpBlocklist":"","secLoginThrottle":true,"secMaxAttempts":8,"secGenericErrors":true,"secValidityCap":30,"secRequirePII":false,"sec2FA":false,"secLoginNotify":false,"secDeviceCheck":false,"secBehavioral":false,"sec3DS":false,"secNoLogin":false},"meta":{"updatedAt":null,"updatedBy":null},"defaults":{…}}
PUT/api/admin/configadmin
サイト全体の設定を部分更新します。{config:{…}} とパッチオブジェクト単体のどちらも受け付けます。既知のキーのみが適用され、meta には変更者が 'admin' として記録されます。
リクエスト
{"config":{"announcementEnabled":true,"announcementText":"9/1 メンテナンス"}}
レスポンス例
{"ok":true,"config":{"maintenanceMode":false,"registrationOpen":true,"announcementEnabled":true,"announcementText":"9/1 メンテナンス","announcementLevel":"info","demoEnabled":true,"signinEnabled":true,"chatBubbleEnabled":true,"primaryCtaLabel":"","secEnabled":true,…},"meta":{"updatedAt":null,"updatedBy":null}}
GET/api/admin/delete-requestsadmin
保留中のサブ管理者削除承認とそのアクセスコードを返します。破壊的な削除に2人目の人間を必要とするための別経路です。期限切れのリクエストは読み取り時に破棄されます。
レスポンス例
{"ok":true,"requests":[]}
GET/api/admin/security/eventsadmin
直近200件のセキュリティ対策イベント(サインアップ、認証失敗、ブロック、MFA チャレンジ)を返します。
レスポンス例
{"ok":true,"events":[]}

サブ管理者 (Sub-Admin)

担当クライアント限定の運用(メモ・ファイル・削除)。要subadminトークン

POST/api/subadmin/login公開
サブ管理者ログイン。email とパスワードを subadmins マップと照合し、有効期間8時間の HMAC トークンを発行します。
パラメータ位置型必須説明
emailbodystring○サブ管理者のメールアドレス(照合前に小文字化・trim)
passwordbodystring○平文パスワード(環境変数 SUBADMIN_PASSWORD で設定。公開の既定値はありません)
リクエスト
{"email":"subadmin@example.com","password":"YOUR_PASSWORD"}
レスポンス例
{"ok":true,"token":"<b64>.<sig>","sub":{"id":"sa-demo","name":"サポート担当 桐生","email":"subadmin@example.com","tenants":["t-itabashi","t-nagoya"],"perms":{"canDelete":true},"active":true,"created":"2026-06-01"}}
GET/api/subadmin/mesubadmin実測 401
認証済みサブ管理者のプロフィール、担当範囲のテナント、集計値を返します。
パラメータ位置型必須説明
tokenquerystringAuthorization: Bearer ヘッダーの代替
レスポンス例
{"ok":true,"sub":{...},"tenants":[{"id":"t-itabashi",...}],"stats":{"tenants":2,"devices":1414,"clients":5,"sites":1},"origin":"https://kit-agent.ai-sns.io"}
GET/api/subadmin/tenant/:idsubadmin実測 401
担当範囲内のテナント1件と、派生したダッシュボード、公開サイト、バックアップ、サブ管理者の権限を取得します。
パラメータ位置型必須説明
idpathstring○テナントID(サブ管理者の担当範囲内であること。シード: t-itabashi, t-nagoya)
tokenquerystringBearer ヘッダーの代替
レスポンス例
{"ok":true,"tenant":{"id":"t-itabashi","clients":["北斗商事",...],"sites":["itabashi-kitting"]},"dashboards":[{"client":"北斗商事","url":".../portal.html?t=..."}],"published":[{"slug":"itabashi-kitting","url":".../site/itabashi-kitting","live":true}],"backups":[],"perms":{"canDelete":true},"origin":"..."}
POST/api/subadmin/tenant/:idsubadmin
担当範囲内テナントの非中核項目の編集。変更できるのは連絡先メールアドレスのみで、主要な設定は変更できません。
パラメータ位置型必須説明
idpathstring○テナントID(担当範囲内であること)
emailbodystring新しい連絡先メールアドレス(最大120文字)
plan/seats/mrr/status/featuresbodyanyいずれかが含まれる場合は 403(サブ管理者は基本設定を変更できません)
リクエスト
{"email":"new@example.co.jp"}
レスポンス例
{"ok":true,"tenant":{"id":"t-itabashi","email":"new@example.co.jp",...}}
POST/api/subadmin/tenant/:id/clientsubadmin
担当範囲内のテナントにクライアント名を追加し、そのポータル URL を返します。
パラメータ位置型必須説明
idpathstring○テナントID(担当範囲内であること)
clientbodystring○クライアント名(最大80文字。空の場合は 400)
リクエスト
{"client":"新規クライアント"}
レスポンス例
{"ok":true,"url":"https://kit-agent.ai-sns.io/portal.html?t=%E6%96%B0%E8%A6%8F..."}
POST/api/subadmin/impersonate/:idsubadmin
担当範囲内のテナントについて、クライアントアプリへのアシストログイン URL を生成します(サポート用の代理ログイン)。
パラメータ位置型必須説明
idpathstring○テナントID(担当範囲内であること)
レスポンス例
{"ok":true,"url":"https://kit-agent.ai-sns.io/app?admin_as=%E6%9D%BF%E6%A9%8B...&by=subadmin"}
POST/api/subadmin/delete-requestsubadmin
クライアント/サイト/テナントの削除を申請します。6桁のアクセスコード(有効期限10分)を生成します。canDelete 権限が必要です。
パラメータ位置型必須説明
tenantIdbodystring○テナントID(担当範囲内であること)
targetTypebodystring'client'|'site'|'tenant'(既定値 'client')
targetIdbodystring削除対象の ID・名前(最大120文字)
リクエスト
{"tenantId":"t-itabashi","targetType":"client","targetId":"北斗商事"}
レスポンス例
{"ok":true,"requestId":"dr-<hex>","sentTo":["itabashi@example.co.jp","マスター管理者"],"expiresInMin":10,"demoCode":"123456"}
POST/api/subadmin/delete-confirmsubadmin
メールで届いたアクセスコードで削除申請を確定し、自動バックアップの後に担当範囲内で削除を実行します。
パラメータ位置型必須説明
requestIdbodystring○delete-request で得た ID(このサブ管理者のものであること)
codebodystring○6桁のアクセスコード
リクエスト
{"requestId":"dr-<hex>","code":"123456"}
レスポンス例
{"ok":true,"targetType":"client"}
GET/api/subadmin/activitysubadmin実測 401
サブ管理者自身の操作または担当範囲内テナントに絞り込んだ操作ログを、最大150件返します。
パラメータ位置型必須説明
tokenquerystringBearer ヘッダーの代替
レスポンス例
{"ok":true,"activity":[{"ts":1700000000000,"by":"サポート担当 桐生","role":"subadmin","action":"サポートメモを追加","tenantId":"t-itabashi","tenantName":"板橋キッティングセンター","detail":"..."}]}
GET/api/subadmin/backups-allsubadmin実測 401
サブ管理者の全担当テナントを横断して集約したバックアップログ(新しい順、最大120行)を返します。
パラメータ位置型必須説明
tokenquerystringBearer ヘッダーの代替
レスポンス例
{"ok":true,"log":[{"tenantId":"t-itabashi","tenantName":"板橋キッティングセンター","id":"bk-...","ts":1700000000000,"reason":"...","by":"..."}]}
POST/api/subadmin/passwordsubadmin
認証済みサブ管理者が自分でパスワードを変更します。
パラメータ位置型必須説明
currentbodystring○現在のパスワード(誤りの場合は 401。平文で照合)
nextbodystring○新しいパスワード(6文字以上。未満は 400)
リクエスト
{"current":"YOUR_CURRENT_PASSWORD","next":"YOUR_NEW_PASSWORD"}
レスポンス例
{"ok":true}
GET/api/notes/:tenantIdsubadmin実測 401
テナントのサポートメモ一覧を返します(管理者は全テナント、サブ管理者は担当範囲内のみ)。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(サブ管理者の担当範囲内であること。シード: t-itabashi)
tokenquerystringBearer ヘッダーの代替
レスポンス例
{"ok":true,"notes":[{"id":"nt-...","ts":1700000000000,"by":"サポート担当 桐生","text":"...","done":false}]}
POST/api/notes/:tenantIdsubadmin
テナントのメモ一覧にサポートメモ(最大600文字)を追加します。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(サブ管理者の担当範囲内)
textbodystring○メモ本文(trim、最大600文字。空の場合は 400)
リクエスト
{"text":"クライアントへ連絡済み"}
レスポンス例
{"ok":true,"note":{"id":"nt-...","ts":1700000000000,"by":"サポート担当 桐生","text":"...","done":false}}
POST/api/notes/:tenantId/:noteIdsubadmin
特定のサポートメモを更新(text/done)または削除します。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(担当範囲内)
noteIdpathstring○メモID(nt-...)
delbodyboolean真の場合はメモを削除し {ok:true} を返します
donebodyboolean完了フラグの切替
textbodystring新しい本文(最大600文字)
リクエスト
{"done":true}
レスポンス例
{"ok":true,"note":{"id":"nt-...","done":true,"text":"..."}}
GET/api/files/:tenantIdsubadmin実測 401
テナントのアップロード済みファイルのメタデータ一覧を返します(データ本体は含みません)。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(担当範囲内。シード: t-itabashi)
tokenquerystringBearer ヘッダーの代替
レスポンス例
{"ok":true,"files":[{"id":"fl-...","ts":1700000000000,"by":"サポート担当 桐生","name":"手順書.pdf","type":"application/pdf","size":10240}]}
POST/api/files/:tenantIdsubadmin
テナントに添付する base64 のファイル/資料(最大約2MB)をアップロードします。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(担当範囲内)
namebodystringファイル名(最大160文字。既定値 'file')
typebodystringMIME タイプ(最大80文字)
databodystring○Base64・データ本体(空の場合は 400、2,800,000文字を超える場合は 413)
sizebodynumber申告サイズ(既定値は data.length)
リクエスト
{"name":"doc.pdf","type":"application/pdf","data":"<base64>"}
レスポンス例
{"ok":true,"file":{"id":"fl-...","ts":1700000000000,"by":"...","name":"doc.pdf","type":"application/pdf","size":12345}}
GET/api/files/:tenantId/:fileId/downloadsubadmin実測 401
ダウンロード用に、ファイル1件の base64 データ全体を返します。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(担当範囲内)
fileIdpathstring○ファイルID(fl-...)。見つからない場合は 404
tokenquerystringBearer ヘッダーの代替
レスポンス例
{"ok":true,"name":"doc.pdf","type":"application/pdf","data":"<base64>"}
POST/api/files/:tenantId/:fileId/deletesubadmin
テナントのファイル一覧からアップロード済みファイルを削除します。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(担当範囲内)
fileIdpathstring○削除対象のファイルID
レスポンス例
{"ok":true}
POST/api/subadmin/workspace/:tid/impersonatesubadmin
サブ管理者用のアシストモード。対象は割り当てられたテナントに限られます。付与されるのは顧客自身の権限のみで、plan/seats/mrr/status/features には触れられません。assist-start として記録されます。
パラメータ位置型必須説明
tidpathstring○このサブ管理者の担当範囲に含まれるワークスペース(テナント)ID。

バックアップ (Backup/Export)

日次バックアップ・状態エクスポート。要BACKUP_TOKEN

GET/api/admin/backupsadmin実測 401
主管理者用の全体バックアップログ(全テナント横断の直近120件のスナップショット行)と日次自動バックアップの状態を返します。
パラメータ位置型必須説明
tokenquerystring管理者 JWT(Authorization: Bearer <token> でも送信可)。必須。
レスポンス例
{"ok":true,"log":[{"tenantId":"t-itabashi","tenantName":"板橋キッティングセンター","id":"bk-...","ts":1784600000000,"by":"system","reason":"日次自動バックアップ","sites":1}],"daily":{"last":1784600000000,"tenants":5}}
GET/api/backups/:tenantIdadmin実測 401
テナント1件のバックアップスナップショットのメタデータ一覧を新しい順に返します(管理者または担当範囲内のサブ管理者向け)。
パラメータ位置型必須説明
tenantIdpathstring○テナントID(例: t-itabashi。シードテナント: t-itabashi, t-osaka, t-nagoya, t-fukuoka, t-sapporo)
tokenquerystring管理者またはサブ管理者の JWT(Authorization: Bearer でも可)。必須。
レスポンス例
{"ok":true,"backups":[{"id":"bk-lz...","ts":1784600000000,"by":"system","reason":"日次自動バックアップ","sites":1}]}
GET/api/subadmin/backups-allsubadmin実測 401
ログイン中のサブ管理者の担当範囲全体のバックアップログ: 割り当てテナントのみを対象とした直近120件のスナップショット行。
パラメータ位置型必須説明
tokenquerystringサブ管理者 JWT(role==='subadmin'。Authorization: Bearer でも可)。必須。
レスポンス例
{"ok":true,"log":[{"tenantId":"t-nagoya","tenantName":"名古屋モバイル管理","id":"bk-...","ts":1784600000000,"by":"system","reason":"日次自動バックアップ","sites":0}]}
GET/api/export/statetoken実測 503(BACKUP_TOKEN 未設定)
自動オフサイトバックアップ用の実行時データ全件ダンプ(全 tenants/sites/subadmins/backups/leads/signs/bookings など + 件数)。
パラメータ位置型必須説明
tokenquerystringバックアップトークン。環境変数 BACKUP_TOKEN と一致すること(既定値なし: 未設定時は 503 export disabled)。ヘッダー x-backup-token を推奨。必須(いずれか一方)。
レスポンス例
{"ok":true,"exportedAt":1784675572317,"space":"Aisnsio/kitting","tenants":{"t-itabashi":{...}},"sites":{...},"backups":{...},"counts":{"tenants":5,"backups":5,...}}
POST/api/backup/:tenantIdadmin
テナント1件のスナップショットを任意の理由ラベル付きで即時作成します(テナントレコードとそのサイトをディープコピー)。
パラメータ位置型必須説明
tenantIdpathstring○スナップショット対象のテナントID(例: t-itabashi)
tokenquerystring管理者または担当範囲内のサブ管理者の JWT(または Authorization: Bearer)。必須。
reasonbodystringバックアップの理由・ラベル(120文字で切り詰め)。既定値 '手動バックアップ'
リクエスト
{"reason":"設定変更前の手動バックアップ"}
レスポンス例
{"ok":true,"backup":{"id":"bk-lz9x...","ts":1784675000000,"by":"マスター管理者","reason":"手動バックアップ","sites":1}}
POST/api/restore/:tenantId/:backupIdadmin
ロールバック: 保存済みスナップショットからテナント(とそのサイト)を復元します。復旧できるよう、先に現在の状態を自動でスナップショットします。
パラメータ位置型必須説明
tenantIdpathstring○ロールバック対象のテナントID(例: t-itabashi)
backupIdpathstring○復元するスナップショットID(例: bk-lz9x2a。GET /api/backups/:tenantId で取得)
tokenquerystring管理者または担当範囲内のサブ管理者の JWT(または Authorization: Bearer)。必須。
レスポンス例
{"ok":true,"tenant":{"id":"t-itabashi","name":"板橋キッティングセンター","plan":"Business","sites":["itabashi-kitting"],...}}

公開フォーム・OAuth・その他 (Misc)

申込/パートナー/予約/署名/CRM・OAuth連携。

POST/api/synthia公開
Synthia AI チャットプロキシ: ANTHROPIC_API_KEY が設定されていれば message と history を Anthropic Claude に転送し、未設定の場合はクライアントが組み込みのモックを使うようフォールバックフラグを返します。
パラメータ位置型必須説明
messagebodystring○ユーザーのメッセージ(4000文字で切り詰め)
historybodyarray過去の会話 [{role:'user'|'assistant',content}](直近8件を使用)
リクエスト
{"message":"string","history":[{"role":"user","content":"..."}]}
レスポンス例
{"ok":false,"fallback":true,"reason":"no_key"} | {"ok":true,"text":"...","model":"claude-opus-4-8"}
GET/api/marketprice公開実測 200
買取・下取り向けに、SerpAPI / Yahoo Shopping / Google CSE で中古端末の相場をリアルタイムに検索します。キーが未設定の場合は参考メモを返します。
パラメータ位置型必須説明
modelquerystring○端末機種のキーワード(80文字以内。未指定は 400)
condquerystring状態のキーワード(24文字以内)
レスポンス例
{"ok":true,"live":false,"model":"iPhone 13","note":"ライブ相場APIキーが未設定です…"}
GET/api/connect/status要サインイン実測 200
全13件の連携プロバイダ(MDM/Apple/配送/会計/チャット)を、接続状態、configured フラグ、redirectUri、本番稼働ガイドとともに返します。
レスポンス例
{"ok":true,"origin":"https://kit-agent.ai-sns.io","providers":[{"key":"intune","name":"Microsoft Intune","group":"MDM","authType":"oauth","connected":false,"configured":false,"guide":{...}}]}
GET/api/connect/:provider要サインイン実測 200
OAuth を開始します。OAuth プロバイダの場合は認可 URL へリダイレクト(302)し、資格情報型プロバイダや資格情報が未設定の場合は HTML ポップアップを返します。
パラメータ位置型必須説明
providerpathstring○プロバイダーキー(例: intune, freee, moneyforward, lineworks)
レスポンス例
HTTP 200 text/html popup, OR 302 redirect to authorize URL, OR 404 text 'unknown provider'
GET/api/connect/:provider/callback公開実測 200
OAuth リダイレクトコールバック: state を検証し、プロバイダでコードをトークンに交換して保存し、opener に postMessage する HTML ポップアップを返します。
パラメータ位置型必須説明
providerpathstring○プロバイダーキー
codequerystringOAuth 認可コード
statequerystring認可ステップで発行された CSRF 用 state
errorquerystringプロバイダーのエラーコード
レスポンス例
HTTP 200 text/html popup ('接続に失敗しました' on state mismatch / '接続が完了しました' on success)
POST/api/connect/:provider/credentials要サインイン
資格情報型プロバイダの API キー/トークン/Webhook の資格情報を保存します。Webhook プロバイダの場合は検証のため実際にテスト POST を送信します。
パラメータ位置型必須説明
providerpathstring○資格情報のプロバイダーキー(例: jamf, teams, sorachi)
fieldsbodyobject○フィールドキー->値のマップ(プロバイダーの全フィールドが必須)
リクエスト
{"fields":{"webhook":"https://..."}}
レスポンス例
{"ok":true,"tested":true} | {"ok":false,"error":"...が未入力です"}
POST/api/connect/:provider/disconnect要サインイン
プロバイダの保存済みトークン/資格情報を削除します。
パラメータ位置型必須説明
providerpathstring○プロバイダーキー
レスポンス例
{"ok":true}
POST/api/site/publish公開
ホワイトラベルのテナント向けマーケティングサイト(slug+HTML)を公開し、/site/<slug> で配信します。
パラメータ位置型必須説明
slugbodystring○a-z0-9- のスラッグ(40文字以内。無害化後に空の場合は 400)
htmlbodystring○サイトの HTML(800000文字以内)
namebodystring表示名(120文字以内)
リクエスト
{"slug":"acme","html":"<html>..","name":"Acme"}
レスポンス例
{"ok":true,"slug":"acme","url":"https://.../site/acme"}
GET/api/site/list公開実測 200
公開中のホワイトラベルサイトを、slug、名前、更新日時、公開 URL とともに一覧で返します。
レスポンス例
{"ok":true,"sites":[{"slug":"acme","name":"Acme","updated":1780000000000,"url":"https://.../site/acme"}]}
POST/api/site/:slug/unpublish公開
slug を指定して公開サイトを削除します。
パラメータ位置型必須説明
slugpathstring○削除するサイトのスラッグ
レスポンス例
{"ok":true}
GET/site/:slug公開
公開テナントサイトの HTML をそのまま配信します(/api パスではありません)。slug が不明な場合は 404 の HTML ページを返します。
パラメータ位置型必須説明
slugpathstring○公開中のサイトのスラッグ
レスポンス例
<!doctype html>...stored site HTML... (or 404 HTML)
POST/api/lead公開
公開リード獲得: サイトのウィジェットやフォームからの CRM リードを保存します。
パラメータ位置型必須説明
namebodystring担当者名(120文字以内)
emailbodystringメールアドレス(160文字以内)
companybodystring会社名(160文字以内)。name/email/company のいずれか1つ以上が必須
phonebodystring電話番号(40文字以内)
messagebodystringメッセージ(1500文字以内)
sourcebodystring流入元タグ(60文字以内、既定値 'web')
tenantbodystring所属テナント(80文字以内)
リクエスト
{"name":"..","email":"..","company":"..","message":".."}
レスポンス例
{"ok":true,"id":"L-xxxx"}
GET/api/leads公開実測 200
全 CRM リードを返します(新しい順)。
レスポンス例
{"ok":true,"leads":[{"id":"L-..","name":"QA Test","email":"qa@example.com","source":"signup","status":"new","created":1784675609773}]}
POST/api/lead/:id公開
リードの status/notes/連絡先フィールドを更新します。
パラメータ位置型必須説明
idpathstring○リードID
statusbodystringリードのステータス
notesbodystringメモ(3000文字以内)
name/company/email/phonebodystring連絡先フィールド(200文字以内)
リクエスト
{"status":"contacted","notes":".."}
レスポンス例
{"ok":true,"lead":{...}} | 404 {"ok":false}
POST/api/lead/:id/delete公開
ID を指定してリードを削除します。
パラメータ位置型必須説明
idpathstring○リードID
レスポンス例
{"ok":true}
POST/api/sign/create公開
署名可能な電子署名ドキュメント(見積/契約)を作成し、署名用 URL を返します。
パラメータ位置型必須説明
titlebodystring書類タイトル(最大160文字)。既定値 '御見積書'
clientbodystringクライアント名(120文字以内)
emailbodystring署名者のメールアドレス(160文字以内)
amountbodystring金額表示ラベル(40文字以内)
bodyHtmlbodystring文書本文の HTML(200000文字以内)
リクエスト
{"title":"..","client":"..","amount":"..","bodyHtml":".."}
レスポンス例
{"ok":true,"id":"SG-xxxx","url":"https://.../sign.html?id=SG-xxxx"}
GET/api/sign/:id公開実測 404
署名可能なドキュメントを取得します(公開署名ページが読み取ります)。
パラメータ位置型必須説明
idpathstring○文書ID SG-xxxx
レスポンス例
{"ok":true,"doc":{"id":"SG-..","title":"..","status":"pending",...}} | 404 {"ok":false,"error":"not found"}
POST/api/sign/:id/submit公開
ドキュメントに署名します: 署名者名・署名・タイムスタンプ・IP を記録し、status を 'signed' にします。
パラメータ位置型必須説明
idpathstring○文書ID
namebodystring○署名者名(120文字以内)
agreedbodyboolean○同意フラグ(false・未指定は 400)
signaturebodystring署名画像データ(200000文字以内)
リクエスト
{"name":"..","agreed":true,"signature":"data:.."}
レスポンス例
{"ok":true,"status":"signed","signedAt":1780000000000}
GET/api/sign/:id/status公開実測 404
ドキュメントの署名状態のみを返します。
パラメータ位置型必須説明
idpathstring○文書ID
レスポンス例
{"ok":true,"status":"pending","signedName":"","signedAt":0} | 404 {"ok":false}
GET/api/signs公開実測 200
全電子署名ドキュメントを返します(メタデータ、新しい順)。
レスポンス例
{"ok":true,"signs":[{"id":"SG-..","title":"..","client":"..","status":"pending","created":..}]}
POST/api/booking公開
公開の相談予約。status が 'meeting' の CRM リードも紐づけて作成します。
パラメータ位置型必須説明
namebodystring氏名(120文字以内)
emailbodystringメールアドレス(160文字以内)。name/email のいずれか1つ以上が必須
companybodystring会社名(160文字以内)
phonebodystring電話番号(40文字以内)
whenbodystring希望日時(60文字以内)
topicbodystring相談内容(400文字以内)
リクエスト
{"name":"..","email":"..","when":"..","topic":".."}
レスポンス例
{"ok":true,"id":"B-xxxx"}
GET/api/bookings公開実測 200
全相談予約を返します(新しい順)。
レスポンス例
{"ok":true,"bookings":[{"id":"B-..","name":"..","email":"..","status":"requested","created":..}]}
POST/api/booking/:id公開
予約の status を更新します。
パラメータ位置型必須説明
idpathstring○予約ID
statusbodystring新しいステータス(30文字以内)
リクエスト
{"status":"confirmed"}
レスポンス例
{"ok":true,"booking":{...}} | 404 {"ok":false}
POST/api/referral公開
紹介者の紹介コードを作成または更新し、共有用の ?ref= URL を返します。
パラメータ位置型必須説明
referrerbodystring紹介者名(最大120文字)。既定値 '紹介者'
codebodystring希望するコード(24文字以内。省略時は自動生成)
リクエスト
{"referrer":"..","code":".."}
レスポンス例
{"ok":true,"code":"abc12","url":"https://.../?ref=abc12"}
GET/api/referrals公開実測 200
すべての紹介コードをクリック数・リード数付きで一覧します。
レスポンス例
{"ok":true,"referrals":[{"code":"abc12","referrer":"..","clicks":0,"leads":0,"created":..}]}
POST/api/referral/:code/track公開
紹介コードのクリックカウンタを加算します。
パラメータ位置型必須説明
codepathstring○紹介コード(大文字・小文字を区別しない)
レスポンス例
{"ok":true}
POST/api/signup公開
セルフサービスのトライアル申込: トライアル(Starter)テナントと紐づく CRM リードを作成し、見込み客用のアプリ URL を返します。
パラメータ位置型必須説明
emailbodystring○メールアドレス(160文字以内。空の場合は 400)
companybodystring会社名(80文字以内。テナント名として使用)
namebodystring担当者名(80文字以内)
planbodystring希望プランのラベル(リードのメッセージに保存)
リクエスト
{"email":"..","company":"..","name":".."}
レスポンス例
{"ok":true,"tenant":{"id":"t-..","name":".."},"url":"https://.../app?prospect=.."}
POST/api/partner公開
パートナー/代理店プログラムへの申込。パートナーレコード・紹介コード・紐づくリードを作成します。
パラメータ位置型必須説明
companybodystring○会社名(120文字以内。空の場合は 400)
emailbodystring○メールアドレス(160文字以内。空の場合は 400)
contactbodystring担当者名(120文字以内)
regionbodystring地域(60文字以内)
notebodystringメモ(800文字以内)
リクエスト
{"company":"..","email":"..","contact":"..","region":".."}
レスポンス例
{"ok":true,"id":"P-xxxx","code":"acme12","referralUrl":"https://.../?ref=acme12"}
GET/api/partners公開実測 200
パートナー申込をすべて一覧します(新しい順)。
レスポンス例
{"ok":true,"partners":[{"id":"P-..","company":"..","email":"..","tier":"Silver","status":"applied","code":".."}]}
POST/api/partner/:id公開
パートナーのステータス/ティア/案件数/売上/メモを更新します。
パラメータ位置型必須説明
idpathstring○パートナーID
status/tier/notebodystringテキストフィールド(800文字以内)
deals/revenuebodynumber数値指標(+ で数値に変換)
リクエスト
{"status":"active","tier":"Gold","deals":3,"revenue":500000}
レスポンス例
{"ok":true,"partner":{...}} | 404 {"ok":false}
POST/api/review公開
公開レビュー・NPS の投稿(承認待ちの未承認状態で保存され、モデレーション後に公開)。
パラメータ位置型必須説明
commentbodystring○レビュー本文(800文字以内。空の場合は 400)
ratingbodynumber1〜5(範囲外は丸め)
namebodystring名前(最大80文字)。既定値 '匿名'
companybodystring会社名(120文字以内)
npsbodynumber0〜10(範囲外は丸め。既定値 rating*2)
リクエスト
{"rating":5,"comment":"..","name":"..","nps":9}
レスポンス例
{"ok":true}
GET/api/reviews公開実測 200
承認済みレビューを、算出した平均評価・件数・NPS スコア付きで一覧します。
レスポンス例
{"ok":true,"reviews":[{"id":"RV-965da4","name":"情シス部長","company":"北斗商事","rating":5,"nps":9,...}],"avg":4.7,"count":3,"nps":..}
GET/api/events公開実測 200
開催予定のウェビナー/イベント 3 件の固定リストを返します。
レスポンス例
{"ok":true,"events":[{"id":"ev-mdm","title":"30分でわかる:Intune 連携キッティングの進め方","date":"2026-08-05 15:00","seats":100}]}
POST/api/event/:id/register公開
ウェビナーに申し込みます。紐づく CRM リード(source 'webinar')を作成します。
パラメータ位置型必須説明
idpathstring○イベントID(ev-mdm|ev-lcm|ev-ai)
emailbodystring○メールアドレス(160文字以内。空の場合は 400)
namebodystring氏名(120文字以内)
companybodystring会社名(160文字以内)
リクエスト
{"email":"..","name":"..","company":".."}
レスポンス例
{"ok":true} | 404 {"ok":false} for unknown event
POST/api/ab公開
A/B ランディングテストのイベント(view または convert)をバリアント a または b に記録します。
パラメータ位置型必須説明
variantbodystring'a' または 'b'(既定値 'a')
eventbodystring'view' または 'convert'(既定値 'view')
リクエスト
{"variant":"b","event":"convert"}
レスポンス例
{"ok":true}
GET/api/ab公開実測 200
バリアント a・b の現在の A/B テストカウンタを返します。
レスポンス例
{"ok":true,"stats":{"a":{"view":0,"convert":0},"b":{"view":1,"convert":0}}}
GET/api/export/statetoken実測 401
自動バックアップ用のランタイムデータ全量ダンプ(メモリ上の全コレクション+件数)。バックアップトークンが必要です。
パラメータ位置型必須説明
tokenquerystring○バックアップトークン(X-Backup-Token ヘッダーでも可)。BACKUP_TOKEN と一致すること
レスポンス例
{"ok":false,"error":"unauthorized"} (no token) | {"ok":true,"exportedAt":..,"tenants":{..},"leads":{..},"counts":{..}}
GET/healthz公開実測 200
ヘルスチェック。
レスポンス例
{"status":"ok"}
GET/api/public/status公開
埋め込み用ステータスウィジェットのデータソース: 公開済みポータルの状態、最終更新の文字列、およびその顧客の端末の「件数」。匿名アクセス可・CORS 有効・レート制限あり。端末数を算出できない場合は数値を表示せず、その旨(computed:false + reason)を返します。
パラメータ位置型必須説明
sitequerystring○ポータルのスラッグ(例: 'hokuto')。公開中のポータルに一致しない場合は 404。形式が不正な場合は 400 を返します: {ok:false,error:'site が不正です'}
レスポンス例
{"ok":true,"site":"hokuto","published":true,"status":"operational","label":"稼働中","devices":{"total":124,"active":124,"computed":true},"lastTouch":"3分前","generated":1787863942136,"total":124,"active":124}
該当するエンドポイントがありません。

機械可読仕様: /openapi.json(OpenAPI 3.0)