ログイン

API

シンプルなREST APIで旅行の作成、旅程の管理、コラボレーションが可能です。

認証

すべてのAPIリクエストには、AuthorizationヘッダーにBearerトークンとしてAPIキーが必要です。

設定 → APIキーでキーを生成してください。キーはすぐにコピーしてください。再度表示されません。

curl https://keen-sturgeon-487.convex.site/api/v1/trips \
  -H "Authorization: Bearer osk_your_key_here"

Scopes

The four base scopes are trips:read, trips:write, messages:read, and messages:write. Each can be limited to a single trip by appending :<tripId>. For example, a key with only the scope trips:write:jx7abc... can create and update content on that one trip but nothing else. In the settings UI, leave "Limit to trip" blank for a key that works everywhere, or paste a trip ID to scope it down.

SDKs

You do not need a client to use the REST API, but the official TypeScript SDK takes care of the tedious bits: auto-generated idempotency keys, retry with exponential backoff on 429 and 5xx, cursor pagination iterators, typed errors, and an unauthenticated share-token consumer.

TypeScript

npm install @osoto/api-client
import { OsotoClient } from '@osoto/api-client';

const client = new OsotoClient({
  apiKey: process.env.OSOTO_API_KEY!,
  baseUrl: 'https://keen-sturgeon-487.convex.site/api/v1',
});

const me = await client.me();
const { _id: tripId } = await client.createTrip({
  groupId: me.defaultGroupId!,
  title: 'Cotswolds',
  startDate: '2026-07-15',
  endDate: '2026-07-22',
});

// Async iterator loops every page automatically.
for await (const leg of client.iterateLegs(tripId)) {
  console.log(leg.title);
}

Model Context Protocol

Agents that speak MCP (Claude Desktop, Claude Code, Cursor, Windsurf, OpenClaw) can consume the REST API through @osoto/mcp-server without writing any client code.

npx @osoto/mcp-server

Full MCP setup instructions →

レート制限

APIキーは1分あたり60リクエストに制限されています。レート制限の状態はレスポンスヘッダーで返されます。

ParameterTypeDescription
X-RateLimit-Limitintegerウィンドウあたりの許可リクエスト数
X-RateLimit-Remaininginteger現在のウィンドウの残りリクエスト数
Retry-Afterintegerウィンドウリセットまでの秒数(429の場合のみ)

Idempotency and retries

Retries are safe. You have two tools for making sure a flaky network does not create duplicates: an Idempotency-Key header for individual mutations, and a clientRef field for upserting rows by a caller-supplied identifier.

Idempotency-Key header

Any POST, PATCH, or DELETE may include an Idempotency-Key header (max 255 characters). Retries with the same key replay the cached response; retries with the same key but a different body return 409 IDEMPOTENCY_CONFLICT. Cached responses expire after 24 hours.

curl -X POST https://keen-sturgeon-487.convex.site/api/v1/trips \
  -H "Authorization: Bearer osk_..." \
  -H "Idempotency-Key: create-trip-42" \
  -H "Content-Type: application/json" \
  -d '{"groupId":"...","title":"Cotswolds","startDate":"2026-07-15","endDate":"2026-07-22"}'

clientRef field

Pass a clientRef when creating legs, action items, map pins, or stays. It is unique per trip (or per leg for stays). Passing the same value on a retry diff-merges into the existing row instead of inserting a duplicate. clientRef pairs naturally with the batch upsert endpoints when importing a full itinerary.

エラー

エラーはコードとメッセージを含むJSONオブジェクトで返されます。

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Missing required fields: title, startDate",
    "requestId": "req_0f9a8b7c-...",
    "details": [
      { "path": "title", "reason": "required" },
      { "path": "startDate", "reason": "required" }
    ]
  }
}

Every response carries an X-Request-Id header (mirrored in error.requestId for error responses). Include it when filing support issues so we can trace the request end-to-end.

ParameterTypeDescription
UNAUTHORIZED401無効または欠落しているAPIキー
FORBIDDEN403必要なスコープまたは旅行アクセスが不足
NOT_FOUND404リソースが存在しません
VALIDATION_ERROR400リクエストフィールドが欠落または無効
IDEMPOTENCY_CONFLICT409Same Idempotency-Key was replayed with a different request body
RATE_LIMITED429リクエストが多すぎます

エンドポイント

Me

GET/me

Return the authenticated user, their groups, and the default group ID. Call this once at startup to discover groupId values for trip creation.

curl https://keen-sturgeon-487.convex.site/api/v1/me \
  -H "Authorization: Bearer osk_..."

旅行

GET/trips

認証ユーザーがアクセスできるすべての旅行を一覧表示します。

curl https://keen-sturgeon-487.convex.site/api/v1/trips \
  -H "Authorization: Bearer osk_..."
POST/trips

新しい旅行を作成します。

ParameterTypeDescription
groupId*string旅行を作成するグループ
title*string旅行タイトル
startDate*string開始日(YYYY-MM-DD)
endDate*string終了日(YYYY-MM-DD)
curl -X POST https://keen-sturgeon-487.convex.site/api/v1/trips \
  -H "Authorization: Bearer osk_..." \
  -H "Content-Type: application/json" \
  -d '{"groupId":"...","title":"Summer in the Cotswolds","startDate":"2026-07-15","endDate":"2026-07-22"}'
GET/trips/{tripId}

旅行の詳細を取得します。

GET/trips/{tripId}/export

Canonical trip snapshot. Returns trip, legs, map pins, action items, commitments, and members in a single response. Use this to answer questions like "where am I staying on Tuesday" without issuing multiple reads.

curl https://keen-sturgeon-487.convex.site/api/v1/trips/TRIP_ID/export \
  -H "Authorization: Bearer osk_..."
POST/trips/{tripId}/sync

Diff-based snapshot import. Pass any combination of legs, actionItems, and mapPins; items with a matching clientRef are diff-merged, items without are created. Set dryRun=true to preview the change set without writing. Returns per-category created/updated/errors counts and per-item outcomes.

curl -X POST "https://keen-sturgeon-487.convex.site/api/v1/trips/TRIP_ID/sync?dryRun=true" \
  -H "Authorization: Bearer osk_..." \
  -H "Content-Type: application/json" \
  -d '{"legs":[{"order":0,"title":"Tokyo","destination":"Tokyo","startDate":"2026-07-15","endDate":"2026-07-20","timezone":"Asia/Tokyo","clientRef":"leg-tok-1"}],"mapPins":[{"name":"Sensoji","lat":35.7148,"lng":139.7967,"clientRef":"pin-sensoji"}]}'
PATCH/trips/{tripId}

旅行のメタデータを更新します。

ParameterTypeDescription
titlestring新しいタイトル
startDatestring新しい開始日
endDatestring新しい終了日
statusstringdraft、active、またはcompleted
DELETE/trips/{tripId}

旅行をアーカイブします(ステータスをcompletedに設定)。

旅程区間

GET/trips/{tripId}/legs

旅行の区間を順序で並べ替えて一覧表示します。

ParameterTypeDescription
limitintegerMax results (default 100, max 200)
cursorstringPagination cursor from previous response
POST/trips/{tripId}/legs

旅程区間を追加します。

ParameterTypeDescription
order*number並び順(0始まり)
title*string区間タイトル
destination*string目的地名
startDate*string開始日
endDate*string終了日
timezone*stringIANAタイムゾーン(例:Europe/London)
accommodationobject宿泊施設の詳細
flightsarrayフライトの詳細
rentalCarobjectレンタカーの詳細
clientRefstringCaller-supplied unique reference (per trip). Retries upsert instead of duplicating.
POST/trips/{tripId}/legs:batch

Batch upsert up to 50 legs in a single call. Items with a matching clientRef are diff-merged; items without are created. Partial success: a 207 response lists per-item results.

curl -X POST https://keen-sturgeon-487.convex.site/api/v1/trips/TRIP_ID/legs:batch \
  -H "Authorization: Bearer osk_..." \
  -H "Content-Type: application/json" \
  -d '{"items":[{"order":0,"title":"Tokyo","destination":"Tokyo","startDate":"2026-07-15","endDate":"2026-07-20","timezone":"Asia/Tokyo","clientRef":"leg-tok-1"}]}'
PATCH/trips/{tripId}/legs/{legId}

旅程区間を更新します。

DELETE/trips/{tripId}/legs/{legId}

旅程区間を削除します。

アクションアイテム

GET/trips/{tripId}/action-items

旅行のチェックリスト項目を一覧表示します。

POST/trips/{tripId}/action-items

チェックリスト項目を作成します。

ParameterTypeDescription
text*string項目テキスト
urgency*stringnow、before_trip、またはnice_to_have
ownerstring割り当てるユーザーID
clientRefstringCaller-supplied unique reference (per trip). Retries upsert instead of duplicating.
POST/trips/{tripId}/action-items:batch

Batch upsert up to 50 action items. Supports clientRef for retry-safe upserts.

PATCH/trips/{tripId}/action-items/{itemId}

アクションアイテムの更新または完了の切り替え。

DELETE/trips/{tripId}/action-items/{itemId}

アクションアイテムを削除します。

Commitments

GET/trips/{tripId}/commitments

List scheduled events on a trip: dinners, activities, birthdays, meetings. Paginated — default limit 100, max 200, ordered by startDate and startTime.

POST/trips/{tripId}/commitments

Create a scheduled event. Optionally link it to a leg or a map pin.

ParameterTypeDescription
title*stringEvent title
startDate*stringDate (YYYY-MM-DD)
category*stringdinner, activity, birthday, meeting, or other
startTimestringLocal time HH:mm (24-hour)
endTimestringLocal time HH:mm (24-hour)
isAllDaybooleanTrue for all-day events (startTime and endTime are ignored)
timezonestringIANA timezone (e.g., Europe/London)
legIdstringLink to an existing trip leg
mapPinIdstringLink to an existing map pin
notesstringFree-form notes about the event
PATCH/trips/{tripId}/commitments/{commitmentId}

Update a commitment.

DELETE/trips/{tripId}/commitments/{commitmentId}

Remove a commitment.

マップピン

GET/trips/{tripId}/map-pins

旅行のマップピンを一覧表示します。

POST/trips/{tripId}/map-pins

旅行マップに場所をピン留めします。

ParameterTypeDescription
name*string場所名
lat*number緯度
lng*number経度
categorystringカテゴリ(例:レストラン、ホテル)
notesstring場所に関するメモ
clientRefstringCaller-supplied unique reference (per trip). Retries upsert instead of duplicating.
POST/trips/{tripId}/map-pins:batch

Batch upsert up to 50 map pins. Supports clientRef for retry-safe upserts.

PATCH/trips/{tripId}/map-pins/{pinId}

マップピンを更新します。

DELETE/trips/{tripId}/map-pins/{pinId}

マップピンを削除します。

メッセージ

GET/trips/{tripId}/channels

旅行のチャンネルを一覧表示します。

GET/trips/{tripId}/channels/{channelId}/messages

チャンネルのメッセージを一覧表示します。ページネーション: 次のページにはcursorを渡してください。

ParameterTypeDescription
limitinteger最大結果数(デフォルト50、最大100)
cursorstring前回のレスポンスからのページネーションカーソル
POST/trips/{tripId}/channels/{channelId}/messages

チャンネルにメッセージを送信します。

ParameterTypeDescription
content*stringメッセージ内容
parentIdstring返信先メッセージID

旅行メンバー

GET/trips/{tripId}/members

旅行のメンバーとその役割・連絡先を一覧表示します。

Shared (no auth)

Generate a share token with POST /trips/{tripId}/share-token. The token grants unauthenticated read access to the safe projection of the trip. Sensitive fields like wifiPassword, doorCode, hostPhone, confirmationNumber, and check-in instructions are stripped. Revoke with DELETE /trips/{tripId}/share-token.

GET/shared/trips/{token}

Read-only share view. No Authorization header required.

curl https://keen-sturgeon-487.convex.site/api/v1/shared/trips/SHARE_TOKEN
GET/shared/trips/{token}/export

Canonical share snapshot with the same shape as /trips/{tripId}/export but using the safe-allowlist projection.