認証
すべてのAPIリクエストは、APIキーをベアラートークンとして使用します。アプリ内の 開発者 → APIキーから作成できます。 読み取り専用 または 読み取り/書き込み.
curl https://savrsoft.com/api/v1/events \ -H "Authorization: Bearer savr_live_your_key_here"
ベースURL: https://savrsoft.com/api/v1 ・すべてのレスポンスはJSON形式です。エラー時は { "error": "…" } のような4xx/5xxステータスが返されます。
ステータスコード
| コード | 発生タイミング |
|---|---|
200 | 読み取り成功。 |
201 | 作成成功。ボディは { "id": 42 } です — 残りの情報が必要な場合はレコードを取得してください。 |
400 | 必須フィールドが未入力です。例: { "error": "name is required" }、またはページネーションカーソルが読み取れませんでした。 |
401 | APIキーがない、不正な形式である、または失効しているキーです。 |
403 | 読み取り専用キーで書き込み操作が行われました。読み書き可能なキーを以下から作成してください 開発者 → APIキー. |
404 | レコードが存在しないか、他の組織に属しています——この2つのケースは意図的に区別されません。認識できないパスやメソッドの場合も同様に返されます。 |
このAPIの範囲
APIは 読み取りと作成のみです。 DELETE, PUT または PATCH
のエンドポイントは存在しません——これらを使用したリクエストは、認識できないパスと同様に 404 Unknown endpointを返します。削除や
編集はアプリ内で行うため、連携先がケータリング業者のレコードを破壊することはできません。作成以外の書き込みアクセスが必要な場合は、
作ろうとしているものを教えてください.
ページネーション
すべての一覧エンドポイントはページネーションに対応しています。次を渡してください: limit (デフォルト 100、最大 500)を渡し、
に従ってください next_cursor まで has_more が false:
{
"data": [ ... ],
"has_more": true,
"next_cursor": "eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0"
}
カーソルはそのまま返して次のページを取得してください。中身は不透明なものとして扱ってください — エンコード方式は変更される可能性があります:
curl "https://savrsoft.com/api/v1/clients?limit=100&cursor=eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0" \ -H "Authorization: Bearer savr_live_your_key_here"
ページネーションは、オフセットではなく最後に受け取った行を基準にしています。そのため、ページ取得中に行が作成または削除されても、レコードをスキップしたり重複して取得したりすることはありません。カーソルは無期限に有効です。
| パラメータ | 動作 |
|---|---|
limit | 1〜500。未指定、ゼロ、負の値、または数値以外の場合は100にフォールバックします。500を超える値は500に制限されます。 |
cursor | next_cursor 前のページからの値です。最初のページでは省略してください。読み取れないカーソル(破損している、または別のエンドポイントのもの)を指定した場合は、 400 Invalid cursor を返し、黙って最初から再開することはありません。 |
並び順: /events と /invoices は新しい順、 /recipes と
/clients は名前順で、名前が重複する場合はidで順序が確定するため、名前が重複してもページングは安定して動作します。
エンドポイント
/v1/me組織情報(id、名前、通貨)。
/v1/eventsイベント一覧を新しい順に取得します。ページネーション対応 — 詳細は上記の ページネーション をご覧ください。
/v1/events/{id}料理付きの単一イベント。
/v1/events · 読み取り/書き込み権限が必要イベントを作成します。ボディ:
{ "name": "Acme holiday party", "event_date": "2026-12-18",
"guests": 120, "price_per_head": 55, "event_type": "corporate" }
/v1/recipes · GET/v1/recipes/{id}レシピ一覧(アレルゲン&食事制限フラグ付き)、または材料付きの単一レシピを取得します。一覧はページネーションされ、名前順に並びます。
/v1/clients · POST/v1/clients顧客一覧(ページネーション、名前順)を取得、または新規作成します。作成ボディ: { "name": "...", "email": "...", "phone": "...", "company": "..." }
/v1/invoices · GET/v1/invoices/{id}計算済みの合計金額付き請求書一覧を新しい順に取得、または明細付きの単一請求書を取得します。一覧はページネーションされます。
Webhooks
エンドポイントを 開発者 → Webhooksに登録してください。イベント発生時に POST でJSONペイロードを送信します:
{
"id": "evt_abc123",
"type": "event.inquiry",
"created_at": "2026-07-17T18:20:00.000Z",
"data": { "id": 42, "name": "Corporate lunch — Dana Ruiz", ... }
}
イベントタイプ
| タイプ | 発火タイミング |
|---|---|
event.created | イベントが作成された |
event.inquiry | 新しいオンラインケータリングリクエストが届いた |
invoice.sent | 請求書が送信済みとしてマークされた |
invoice.paid | 請求書が支払い済みとしてマークされた |
proposal.approved | クライアントが提案を承認した |
client.created | クライアントが作成された |
署名の検証
各配信には x-savrsoft-signature ヘッダーが含まれます:これは生のリクエストボディをwebhook署名シークレットで鍵付けしたHMAC-SHA256です。同様に計算して比較してください:
// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', SIGNING_SECRET)
.update(rawBody).digest('hex');
if (sig !== req.headers['x-savrsoft-signature']) reject();
