APIリファレンス API reference
管理者ポータルが使うインターフェースは大きく 4 種類:
Cloudflare Workers BFF(/v1/*、OpenAPI 3.1 契約)、
Supabase Auth(SDK 直接)、Supabase Realtime(WebSocket)、外部 API(Mapbox 等)。
詳細な契約は parky/api/openapi.json を参照してください。
The portal talks to four kinds of interfaces:
the Cloudflare Workers BFF (/v1/*, OpenAPI 3.1 contract),
Supabase Auth (direct SDK), Supabase Realtime (WebSocket), and external APIs (Mapbox etc.).
See parky/api/openapi.json for the full contracts.
/v1/admin/*) 経由へ移行完了。supabase.from() 直叩きは 0 件。Supabase SDK は Auth / Realtime のみ使用。
Admin portal data access is 100% via the BFF (/v1/admin/*) as of 2026-04-19. Zero direct supabase.from() calls. The Supabase SDK is used for Auth and Realtime only.
完全な一覧と試し打ちは Swagger UI / Redoc を参照。 ここでは「画面とエンドポイントの対応」を把握するためのハイライトを掲載します。
For the full list and interactive tryouts use Swagger UI / Redoc. This page highlights the endpoints whose shape lines up 1-to-1 with admin screens.
1. PostgreSQL RPC(Workers から呼び出し)PostgreSQL RPC (invoked from Workers)
| 関数名Function | 入力Inputs | 用途Purpose |
|---|---|---|
nearby_parking_lots |
p_lng, p_lat, p_radius_m |
GPS 周辺駐車場検索 (PostGIS)GPS proximity search (PostGIS) |
parking_lot_engagement_stats |
— | 駐車場別エンゲージメント集計 (保存/セッション/検索)Engagement per lot (saves / sessions / searches) |
backfill_badge_progress |
target_badge_id |
指定バッジの進捗を全ユーザーで再計算Recompute one badge's progress for every user |
backfill_all_badge_progress |
— | 全バッジの進捗を再計算Recompute every badge's progress |
gift_theme_to_user |
p_theme_id, p_admin_id, p_user_id, p_message? |
テーマギフト送信 → theme_gifts + user_themesSend a theme gift; writes theme_gifts + user_themes |
recalculate_all_user_levels |
— | 全ユーザーのレベルを再計算Recalculate every user's level |
evaluate_badge_conditions |
metadata, conditions |
(内部) 条件式を JSONB に適用(internal) applies a condition set against JSONB |
vault_read_secret |
secret_id |
(内部) Vault からシークレットを復号。service_role 専用(internal) Decrypts a Vault secret. service_role only |
vault_insert_secret |
new_secret, new_name |
(内部) Vault にシークレットを新規登録。service_role 専用(internal) Creates a new Vault secret. service_role only |
2. Cloudflare Workers BFF(管理ポータルが主に叩く経路)Cloudflare Workers BFF (the main admin-portal path)
| エンドポイントEndpoint | リクエストRequest | レスポンスResponse | 用途Purpose |
|---|---|---|---|
POST /v1/admin/user-notifications/{id}/send |
{ id } |
202 { notification_id, enqueued, batches } |
FCM 配信を parky-fcm-dispatch キューに投入。consumer が 500 件/バッチで fan-out し、user_notifications.success_count を原子的加算Enqueues FCM fan-out into parky-fcm-dispatch; the consumer dispatches 500 tokens/batch and atomically increments user_notifications.success_count |
POST /v1/storage/upload-url |
{ file_name, file_size, mime_type, category, entity_type?, entity_id?, is_public? } |
{ upload_url, asset_id, s3_key, public_url, expires_in } |
R2 への署名 PUT URL 発行+assets INSERT。クライアントは署名 URL に直接 PUT。公開 GET は cdn.parky.co.jpMints an R2 presigned PUT URL and inserts into assets. Client PUTs directly; public GET via cdn.parky.co.jp |
POST /v1/search/ai |
{ action: "parse", message } | { action: "register_key", provider_id, api_key } |
{ status: "parsed", query, reply } | { status: "need_info", reply } | { status: "error", reply } |
AI 自然言語検索。AI Gateway 経由でマルチプロバイダー・フォールバック。register_key で API キーを Vault に暗号化登録AI natural-language search via AI Gateway with multi-provider fallback. register_key encrypts and stores API keys in Supabase Vault |
POST /v1/admin/store-sync/trigger |
{ store: "play_store"|"app_store"|"all", task: "sales"|"metrics"|"reviews"|"all" } |
202 { sync_run_ids, count, status: "queued" } |
ストア同期を parky-store-sync キューに直積分 enqueue。consumer が Google Play / App Store Connect API から取得して store_reviews / store_sales_daily に upsertEnqueues the cartesian product into parky-store-sync; the consumer pulls from Google Play / App Store Connect APIs and upserts store_reviews / store_sales_daily |
3. Realtime (WebSocket)
| チャネルChannel | 監視対象Watched table | イベントEvents | 用途Purpose |
|---|---|---|---|
live-user-activity |
user_activity_logs |
INSERT | アクティビティフィードに即時追加Streams into the activity feed |
admin-notifications-sidebar |
admin_notifications |
* | サイドバー通知バッジの自動更新Auto-refreshes sidebar notification badge |
4. Supabase Auth Admin
管理者アカウントの作成・パスワード変更・削除は service_role キーが必須です。
この鍵はクライアントに露出させず、バックオフィス専用の別クライアント (supabaseAdmin) から呼びます。
Creating, updating, or deleting admin accounts requires the service_role key.
It must never ship to non-admin clients — call it from the dedicated supabaseAdmin client instead.
| Operation | Endpoint |
|---|---|
| ログインLogin | POST /auth/v1/token?grant_type=password |
| ログアウトLogout | POST /auth/v1/logout |
| 現在のユーザーCurrent user | GET /auth/v1/user |
| 管理者作成Create admin | POST /auth/v1/admin/users service_role |
| パスワード更新Update password | PUT /auth/v1/admin/users/{id} service_role |
| 管理者削除Delete admin | DELETE /auth/v1/admin/users/{id} service_role |
5. 外部 APIExternal APIs
| API | エンドポイントEndpoint | 用途Use |
|---|---|---|
| Mapbox Geocoding | https://api.mapbox.com/geocoding/v5/mapbox.places/{query}.json |
住所 → 座標、逆ジオコードForward / reverse geocoding |
| Mapbox GL JS | https://api.mapbox.com/styles/v1/... |
駐車場一覧のマップビジュアライザーMap visualizer for the parking list |
| Cloudflare R2 | S3 compatible | 画像・アセットのアップロードImage / asset upload |
典型的な使用例 Common usage patterns
1. ページング付き一覧取得Paged list
const { rows, total } = await fetchTablePage({
table: 'app_users',
search: { display_name: 'ilike.%john%' },
order: { column: 'created_at', ascending: false },
offset: 0,
limit: 500,
});
2. 駐車場詳細の複数フェッチParking-detail fanout
const [lot, sessions, reviews, reports, engagement] = await Promise.all([
fetchParkingLot(id),
fetchParkingSessions({ parkingLotId: id }),
fetchParkingReviews({ parkingLotId: id }),
fetchErrorReports({ parkingLotId: id }),
fetchParkingLotEngagementForLot(id),
]);
3. アセットアップロードAsset upload
// 1. Ask the Workers BFF for a presigned R2 URL
const { upload_url, asset_id, s3_key } = await bff.storage.uploadUrl({
file_name, file_size, mime_type, category: 'badge_icon', is_public: true,
});
// 2. PUT the file directly to R2
await fetch(upload_url, { method: 'PUT', body: file });
// 3. Link the asset_id on the target row
await updateBadgeDefinition(badge.id, { asset_id });
4. Realtime 購読Subscribe to realtime
const channel = supabase
.channel('live-user-activity')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'user_activity_logs' },
(payload) => setLogs(prev => [payload.new, ...prev]))
.subscribe();