REST API
コンソールは https://zenavo.app/api の JSON REST API の上に作られています。コンソールでできることは、すべて API でもできます。
認証
API キーを Bearer トークンとして送ります。
sh
curl -H "Authorization: Bearer $ZENAVO_API_KEY" https://zenavo.app/api/auth/meキーの権限とプロジェクトの制限で、呼び出せるエンドポイントが決まり、それ以外は 403 を返します。請求、購入、チームのメンバー、/api/account/* はブラウザーのセッション専用です。
ブラウザーのセッションからのリクエストは、GET 以外のすべてで X-Zenavo-Request: 1 ヘッダーも必要です。Bearer トークンのリクエストには不要です。
リクエストに必要なのは、有効なセッションか適切なロールの API キーだけで、二重の確認を求める操作はありません。メールアドレスを確認していないアカウントは、自分のアカウント以外の変更で 403 と {"email_unverified": true} を受け取ります。
規約
- ボディは JSON です。時刻は Unix 秒です。
- ID にはプレフィックスが付きます:
team_、srv_、proj_、job_、bak_、tok_。 - エラーはステータスコードと
{"detail": …}を返します。検証エラー(422)は項目ごとに列挙します。 - 時間のかかる操作(デプロイ、再起動、バックアップ)はジョブを返します:
{"id": "job_…"}。GET /api/jobs/{id}をポーリングし、status(queued、running、succeeded、failed)、log、サービスごとのprogressを取得します。
エンドポイント
アカウント
| メソッド | パス | |
|---|---|---|
GET | /api/auth/me | サインイン中のユーザー、所属チーム、email_verified |
PATCH | /api/account | 名前とアバター |
GET POST | /api/account/tokens | API キーの一覧・作成(ブラウザーのセッションのみ)。作成は {name, days, scope, project_ids}:scope は read、deploy、full(デフォルト)。project_ids でキーをそのプロジェクトに制限します(省略か null ですべて) |
DELETE | /api/account/tokens/{id} | API キーの削除 |
GET | /api/account/sessions | サインイン中のセッション |
POST | /api/auth/2fa | サインインの第 2 段階:/api/auth/login が {two_factor: true} を返したあとに {code} |
POST | /api/account/verify | 本人確認:二要素認証があれば {code}、なければ {password}。現在これを必要とする操作はありません |
POST | /api/auth/verify-email | メール確認のリンクを開く:{token}(1 回限り、24 時間有効) |
POST | /api/account/email/verify | 新しい確認リンクを送る。確認済みなら {verified: true} |
GET | /api/account/2fa | 二要素認証の状態:enabled(アプリかパスキー)、totp、残りのリカバリーコード数、パスキーの数 |
POST | /api/account/2fa/setup /enable /disable /recovery-codes | 二要素認証の管理(ブラウザーのセッションのみ) |
POST | /api/auth/2fa/passkey/options のあと /api/auth/2fa/passkey | パスキーによるサインインの第 2 段階:WebAuthn のリクエストオプション(パスキーがなければ {options: null})と、アカウントに認証アプリがあるか(totp)、そのあと {credential} |
GET | /api/account/passkeys | パスキーの一覧:名前、AAGUID、同期、作成日時、最終使用日時 |
POST | /api/account/passkeys/options のあと /api/account/passkeys | パスキーの登録:作成オプション、そのあと {name, credential}(アカウントで最初の 2 つ目の要素なら recovery_codes も返します) |
DELETE | /api/account/passkeys/{id} | パスキーの削除(最後の 2 つ目の要素を削除すると二要素認証はオフになります) |
GET | /api/account/audit?before=&limit= | 自分のセキュリティのアクティビティ |
POST | /api/auth/device/code | CLI のサインイン(デバイスフロー)を開始:{client_name, scope, client} → {device_code, user_code, verification_uri, expires_in, interval}。scope のデフォルトは full。client は cli(デフォルト)か mcp で、キーの名前は「CLI on …」か「MCP on …」になります |
POST | /api/auth/device/token | {device_code} でポーリング:待機中は 202、interval より速いと 429、承認されると 200 {token, scope, project_ids}(承認者がスコープを狭めている場合があります) |
チーム
| メソッド | パス | |
|---|---|---|
GET POST | /api/teams | チームの一覧・作成 |
PATCH | /api/teams/{tid} | 名前の変更 |
GET | /api/teams/{tid}/members | メンバー |
PATCH DELETE | /api/teams/{tid}/members/{uid} | ロールの変更、メンバーの削除 |
GET POST | /api/teams/{tid}/invites | 招待 |
GET | /api/teams/{tid}/audit?before=&limit= | 監査ログ(管理者) |
GET POST | /api/teams/{tid}/notification-channels | 通知チャンネル(管理者)。作成は {kind, name, events, url}(Slack、Discord、Webhook)か {kind: "telegram", name, events, bot_token, chat_id}。Webhook の secret は一度だけ返ります |
PATCH DELETE | /api/teams/{tid}/notification-channels/{cid} | name、events、enabled、送信先の変更、削除 |
POST | /api/teams/{tid}/notification-channels/{cid}/test | テストメッセージをすぐに送る |
POST | /api/teams/{tid}/notification-channels/{cid}/secret | Webhook の新しい署名シークレット(一度だけ返ります) |
GET POST | /api/teams/{tid}/log-drains | ログドレイン(管理者。作成には Pro 以上のプランが必要)。作成は {kind: "http", name, url}、{kind: "datadog", name, site, api_key}、{kind: "loki", name, url, username, password, tenant_id} に projects(空ならすべて)を加えます。HTTP ドレインの secret は一度だけ返ります |
PATCH DELETE | /api/teams/{tid}/log-drains/{did} | name、projects、enabled、送信先の変更、削除 |
POST | /api/teams/{tid}/log-drains/{did}/test | テストの行をすぐに送る |
POST | /api/teams/{tid}/log-drains/{did}/secret | HTTP ドレインの新しい署名シークレット(一度だけ返ります) |
使用量と請求
| メソッド | パス | |
|---|---|---|
GET | /api/teams/{tid}/usage?period=YYYY-MM | プランの上限、サーバー、メンバー、プロジェクト・サービス・日ごとのビルド時間 |
GET | /api/teams/{tid}/usage/builds.csv?period= | ある月の計測対象のビルドすべて(CSV) |
GET | /api/teams/{tid}/transfer | この期間のイメージ転送:bytes、included_bytes、overage_cents、limit_cents、blocked、percent、期間の開始と終了 |
GET | /api/teams/{tid}/billing | プラン、申し込みの状態、シート、プランの一覧(管理者) |
GET | /api/teams/{tid}/billing/invoices | 最近の請求書と、Stripe のページおよび PDF へのリンク(管理者) |
GET | /api/teams/{tid}/server-billing | 購入したサーバーとその支払い済みの月・自動更新、最近のサーバーの請求(管理者) |
POST | /api/teams/{tid}/billing/checkout | 申し込みを開始:{plan} → Stripe Checkout の {url}(オーナー) |
POST | /api/teams/{tid}/billing/change | 申し込みを別のプランに切り替え:{plan}(オーナー) |
POST | /api/teams/{tid}/billing/cancel /resume | 期間の終わりに解約、またはその取り消し(オーナー) |
PUT | /api/teams/{tid}/billing/spend-limit | 利用上限の設定:{cents}、0〜1,000,000(オーナー) |
POST | /api/teams/{tid}/billing/portal | カード、請求先情報、請求書のための Stripe カスタマーポータルの {url}(オーナー) |
サーバー
| メソッド | パス | |
|---|---|---|
GET | /api/servers?team_id= | サーバーの一覧 |
POST | /api/servers?team_id= | サーバーの追加:{name, host, port, user, password | private_key} |
GET PATCH | /api/servers/{sid} | 読み取り、名前の変更 |
POST | /api/servers/{sid}/bootstrap | セットアップを再実行:{password | private_key}。セットアップの失敗から 1 日以内なら、空のボディで保持された認証情報を再利用します |
PATCH | /api/servers/{sid}/billing | 購入したサーバーの自動更新:{auto_renew}(管理者)。GET /api/servers/{sid} の bought に paid_until とともに表示されます |
POST | /api/servers/{sid}/renew | 購入したサーバーの翌月分を今すぐ支払う(管理者) |
GET | /api/servers/{sid}/usage?hours= | CPU、メモリ、ディスクの履歴 |
GET | /api/servers/{sid}/system | プラットフォームのコンポーネント |
GET | /api/servers/{sid}/ports | ポートの確認 |
GET | /api/servers/{sid}/jobs | セットアップなどのジョブ |
POST | /api/servers/{sid}/delete | 削除:{confirmation: "<server name>"} |
POST | /api/servers/{sid}/reinstall | K3s をアンインストールしてサーバーを最初からセットアップ:{confirmation: "<server name>", password | private_key}(管理者。サーバーにプロジェクトがないこと)。サーバーを返し、セットアップはキューに入ります |
POST | /api/servers/{sid}/reinstall-os | 購入したサーバーの OS を再インストールし、SSH の認証情報なしで最初からセットアップ。新しいログインパスワードが呼び出したユーザーにメールで届きます:{confirmation: "<server name>"}(管理者。サーバーにプロジェクトがなく、bought.reinstall_os が true であること)。サーバーを返し、再インストールはキューに入ります |
GET | /api/servers/{sid}/ssh-logins?hours=&failed= | SSH ログイン履歴(メンバー) |
POST | /api/servers/{sid}/agent | エージェント導入前に追加したサーバーをエージェントに移行(管理者) |
POST | /api/servers/{sid}/agent/update | エージェントを更新(管理者。ジョブを返します) |
GET | /api/servers/{sid}/firewall | サーバーのファイアウォール(メンバー)。購入したサーバー:Zenavo の固定ルール(Web、HTTPS、ping、セットアップ用 SSH)とチームのルール(プロバイダーで適用)。接続したサーバー:そちらで開けるべきポート |
POST | /api/servers/{sid}/firewall/rules | 購入したサーバーに許可ルールを追加:{protocol, ports, sources, note}。protocol は tcp、udp、icmp、ports は 8080 や 30000-30100、sources はアドレスか CIDR のリスト(管理者。最大 30 ルール) |
PUT DELETE | /api/servers/{sid}/firewall/rules/{rid} | ルールの変更(同じボディ)または削除(管理者) |
POST | /api/servers/{sid}/firewall/apply | プロバイダーでの適用に失敗したあと、ルールを再適用(管理者) |
プロジェクト
| メソッド | パス | |
|---|---|---|
GET | /api/projects?team_id= | プロジェクトの一覧 |
POST | /api/projects | 作成:{team_id, server_id, manifest} |
GET | /api/projects/{pid} | 概要、サービス、状態 |
GET | /api/projects/{pid}/manifest | 変数を含む設定全体 |
PUT | /api/projects/{pid} | 設定の保存:{manifest, server_id, revision} |
POST | /api/projects/{pid}/deploy | すべてのサービスをデプロイ(ジョブを返します) |
POST | /api/projects/{pid}/rollback | {target_job} |
POST | /api/projects/{pid}/services/{service}/rollback | {target_job}:1 つのサービスをそのデプロイに戻し、他はデプロイ済みのまま(ジョブを返します) |
POST | /api/projects/{pid}/restart /stop | すべてのサービスの再起動・停止 |
GET | /api/projects/{pid}/runtime | 各サービスのライブの状態 |
POST | /api/projects/{pid}/clone /transfer | 複製:{name, team_id, server_id}。または一度もデプロイしていないプロジェクトを別のチームへ移管:{team_id, server_id}(両方のチームの管理者) |
GET | /api/projects/{pid}/move | 最新の別のサーバーへの移行 |
GET | /api/projects/{pid}/move/preflight?server_id= | 何も変えずに移行を確認(管理者) |
POST | /api/projects/{pid}/move | データとともにチームの別のサーバーへ移行:{server_id, confirmation: "<project name>"}(管理者。ジョブを返します) |
POST | /api/projects/{pid}/move/finish /move/rollback | 古いコピーの削除、または古いサーバーへ戻す(管理者。ジョブを返します) |
POST | /api/projects/{pid}/delete | {confirmation: "<project name>"} |
PUT | /api/projects/{pid}/checklist | 移行チェックリスト:{source_backup, data_restored, application_verified, dns_switched, rollback_ready}、それぞれ true か false(メンバー) |
サービス
{service} はサービス ID です。現在の名前でも構いません。プロジェクトの設定では各サービスに id と任意の hostname があります。新しいサービスで両方を省くと、Zenavo がランダムな svc-… の ID と名前から作ったホスト名を付けます。
| メソッド | パス | |
|---|---|---|
POST | /api/projects/{pid}/services/{service}/deploy | このサービスだけをデプロイし、他はデプロイ済みのまま(ジョブを返します) |
PUT | /api/projects/{pid}/services/{service}/source?create=&port=&deploy=&acknowledge_init= | ディレクトリの gzip 圧縮 tar(最大 500 MB)をサービスのソースとしてアップロードしてデプロイ({upload_id, service, created, job} を返します)。create=1 でないサービスを追加し、deploy=0 で保存だけします |
POST | /api/projects/{pid}/services/{service}/restart /suspend /resume | |
POST | /api/projects/{pid}/services/{service}/exec | コンテナでコマンドを実行 |
GET | /api/projects/{pid}/services/{service}/terminal | WebSocket:対話型のターミナル(メンバー)。バイナリフレームが入出力を、テキストフレームが JSON を運びます:クライアントからは {"type":"resize","cols","rows"}、サーバーからは {"type":"exit","code"} か {"type":"error","message"}。ブラウザーはコンソールの Origin を送る必要があります |
GET | /api/projects/{pid}/services/{service}/files?path= | コンテナ内のフォルダーの一覧(メンバー) |
GET | /api/projects/{pid}/services/{service}/files/content?path= | ファイルの先頭 256 KB をテキストで |
GET | /api/projects/{pid}/services/{service}/files/download?path= | ファイルのダウンロード(500 MB まで) |
PUT | /api/projects/{pid}/services/{service}/files/upload?dir=&name= | 生のボディをアップロード(50 MB まで、Content-Length が必要)。&overwrite=1 で置き換え |
POST | /api/projects/{pid}/services/{service}/files/mkdir | フォルダーの作成:{"path"} |
POST | /api/projects/{pid}/services/{service}/files/rename | その場で名前を変更:{"path", "name"} |
POST | /api/projects/{pid}/services/{service}/files/delete | ファイルかフォルダーの削除:{"path"} |
GET | /api/projects/{pid}/services/{service}/usage?hours= | CPU とメモリの履歴 |
GET | /api/projects/{pid}/logs/{service} | 最近の実行時ログ |
GET | /api/projects/{pid}/logs/{service}/stream | ライブの実行時ログ(Server-Sent Events) |
GET | /api/projects/{pid}/logs/{service}/history?from=&to=&q=&cursor=&limit= | 保存された実行時ログを古い順に:from から to(RFC 3339 か Unix 秒。デフォルトは過去 1 時間)までの、q を含む行(大文字小文字は区別しません)。続きは next を cursor に渡します |
GET | /api/projects/{pid}/logs/{service}/download?from=&to=&q= | ある範囲の保存された実行時ログをテキストファイルで |
POST | /api/projects/{pid}/services/{service}/domains | ドメインを生成 |
DELETE | /api/projects/{pid}/domains/{domain} | 生成ドメインを削除 |
データベースビュー
データベースサービスのデータベースビューです。メンバーは読み取りができ、書き込みにはチームの管理者が必要です。各リクエストはデータベースコンテナ内で実行され、SQL、キー、値、ドキュメントを含めずに監査ログに記録されます。 … は /api/projects/{pid}/services/{service} です。
| メソッド | パス | |
|---|---|---|
GET | …/database/tables | PostgreSQL、MySQL、MariaDB:テーブルとビュー、推定行数、列 |
GET | …/database/rows?schema=&table=&offset=&limit= | テーブルの行の 1 ページ |
POST | …/database/query | SQL 文を 1 つ実行:{sql, allow_writes, max_rows}。allow_writes(管理者)でなければ読み取り専用 |
POST | …/database/keys | Redis、Valkey:SCAN でキーを一覧:{db, match, cursor, count} |
POST | …/database/key | 1 つのキーの値:{db, key, cursor, count}。UTF-8 でないキーは key_b64 |
POST | …/database/command | コマンドを 1 つ実行:{db, command, allow_writes}。allow_writes(管理者)でなければ読み取りコマンドのみ |
GET | …/database/collections | MongoDB:データベースとコレクション、推定ドキュメント数 |
POST | …/database/find | ドキュメントを検索:{db, collection, filter, sort, projection, skip, limit}(すべて JSON 文字列)。デフォルトは 1 ページ 50 件 |
POST | …/database/document | ドキュメントを 1 つ変更:{op, db, collection, filter, update, document}。op は insert、update、delete(管理者) |
バックアップ
| メソッド | パス | |
|---|---|---|
GET | /api/backups?project_id= | バックアップの一覧 |
POST | /api/projects/{pid}/backups | サービスのバックアップ:{service, engine} |
GET | /api/backups/{bid}/download | ダウンロード |
POST | /api/backups/{bid}/restore | 復元:{confirmation}(コンソールで入力するものと同じ) |
Git と GitHub
| メソッド | パス | |
|---|---|---|
POST | /api/git/refs | 公開リポジトリのブランチとタグ:{url} |
POST | /api/git/plan | ビルドプランのプレビュー:{team_id, url, ref, context} |
GET | /api/github/repos?team_id= | チームの GitHub インストールが読めるリポジトリ |
GET | /api/github/branches?team_id=&repo= | そのうちの 1 つのブランチ |
イメージとドメイン
| メソッド | パス | |
|---|---|---|
GET | /api/images/ports?team_id=&image= | 公開イメージが EXPOSE するポート(pull せずにレジストリから読み取ります) |
GET | /api/images/mirror?image= | Zenavo の中国本土向けミラーにイメージがあるかと、ミラーでのアドレス |
GET | /api/images/mirror/search?q= | ミラーにある、名前に q を含むイメージ |
GET | /api/domains/available?name= | 生成ドメインの名前が空いているか:{available, reason} |
テンプレート
| メソッド | パス | |
|---|---|---|
GET | /api/templates | テンプレートギャラリー(公開。キー不要) |
GET | /api/templates/{code} | 1 つのテンプレートとそのマニフェスト(公開) |
POST | /api/imports/preview | Zeabur テンプレートか Zenavo のエクスポートを確認:{text, team_id, variables}。ギャラリーのテンプレートなら {template, team_id, variables} |
POST | /api/imports/{did}/commit | プロジェクトを作成:{server_id} |
例:デプロイして待つ
sh
JOB=$(curl -s -X POST -H "Authorization: Bearer $ZENAVO_API_KEY" \
-H "Content-Type: application/json" -d '{}' \
https://zenavo.app/api/projects/$PROJECT/deploy | jq -r .id)
until curl -s -H "Authorization: Bearer $ZENAVO_API_KEY" https://zenavo.app/api/jobs/$JOB \
| jq -e '.status == "succeeded" or .status == "failed"' >/dev/null; do sleep 5; done