ドキュメント · リファレンス
プロジェクト API
プロジェクトごとに専用のアドレスがあり、supabase-js がそのまま接続します。下のルートはすべて、サーバーのルーターとテストで照合している一覧です。
アドレスとキー
プロジェクトのアドレスは https://<ref>.<zone> です。リクエストごとに apikey ヘッダー(または Authorization: Bearer)でキーを送ります。公開キー(publishable)はブラウザー用で、アクセスルール(RLS)に従います。シークレットキー(secret)はすべてのルールを迂回するため、サーバーでだけ使います。ログインしたユーザーのトークンを Authorization: Bearer で送ると、そのユーザーとして実行されます。キーはAPI キー画面にあります。
curl "https://abcdefghijklmnopqrst.end.blackall.ai/rest/v1/notes?select=id,title" \
-H "apikey: <publishable key>"
supabase-js との互換性
パス、クエリ、ヘッダー、レスポンスの形が Supabase と同じなので、@supabase/supabase-js をそのまま使えます。変えるのはアドレスとキーだけです。各表の supabase-js 列は、そのルートを呼び出す関数です。
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://abcdefghijklmnopqrst.end.blackall.ai', '<publishable key>')
データ(/rest/v1)
PostgREST と同じクエリ言語です。テーブル名がパスで、列名がクエリパラメーターです。すべてのリクエストは、呼び出した人のロールとアクセスルール(RLS)で実行されます。
| メソッド | パス | 内容 | supabase-js |
|---|---|---|---|
| GET | /rest/v1/{table} | 行を読む | from('t').select() |
| HEAD | /rest/v1/{table} | 件数だけ読む | select('*', { head: true, count: 'exact' }) |
| POST | /rest/v1/{table} | 行を挿入(Prefer: resolution=… なら upsert) | insert() / upsert() |
| PUT | /rest/v1/{table} | 1 行を upsert | |
| PATCH | /rest/v1/{table} | フィルターに合う行を更新 | update() |
| DELETE | /rest/v1/{table} | フィルターに合う行を削除 | delete() |
| GET | /rest/v1/rpc/{function} | 関数の呼び出し(読み取り) | rpc('f', args, { get: true }) |
| POST | /rest/v1/rpc/{function} | 関数の呼び出し | rpc('f', args) |
| POST | /graphql/v1 | GraphQL(pg_graphql、データベース → 拡張機能で有効にしたプロジェクトのみ、/rest/v1 と同じキーとアクセスルール) | fetch / Apollo / urql |
クエリパラメーター
| 名前 | 説明 |
|---|---|
select | 取得する列。別名(label:title)、型変換(id::text)、JSON パス(data->>name)、外部キーでつながった行(*,author(name)、!inner) |
order | 並び順。created_at.desc.nullslast、複数はカンマ区切り |
limit | 取得する行数。最大 1000 |
offset | スキップする行数 |
on_conflict | upsert で重複を判定する列 |
columns | 挿入する列を指定します |
<column> | 列=演算子.値 のフィルター |
or · and | or=(a.eq.1,b.gt.2)、and=(…)、入れ子と not.or=(…) |
フィルター演算子
次の演算子だけを受け付けます。知らない演算子は黙って無視せず、拒否します。先頭に not. を付けると否定になります。
| 演算子 | SQL |
|---|---|
eq | = |
neq | <> |
gt | > |
gte | >= |
lt | < |
lte | <= |
like | like |
ilike | ilike |
match | ~ |
imatch | ~* |
cs | @> |
cd | <@ |
ov | && |
sl | << |
sr | >> |
nxr | &< |
nxl | &> |
adj | -|- |
isdistinct | is distinct from |
is | is null | not null | true | false | unknown |
in | in (…) |
fts | @@ to_tsquery() |
plfts | @@ plainto_tsquery() |
phfts | @@ phraseto_tsquery() |
wfts | @@ websearch_to_tsquery() |
ヘッダー
| 名前 | 説明 |
|---|---|
Prefer | return=minimal|representation|headers-only、count=exact|planned|estimated、resolution=merge-duplicates|ignore-duplicates、missing=default |
Accept | Accept: application/vnd.pgrst.object+json は 1 行をオブジェクトとして返します(.single())。0 行や複数行なら 406 |
Accept-Profile | Accept-Profile と Content-Profile は public だけを受け付けます |
Content-Range | 総数(count=)はレスポンスの Content-Range ヘッダーで返ります |
関数の呼び出し(rpc)
/rest/v1/rpc/<関数> は、プロジェクトのスキーマにある SQL 関数を呼び出した人のロールで実行します。POST では本文が引数です。GET では関数の引数と同じ名前のクエリパラメーターが引数になり、残りは結果へのフィルターです。
const { data, error } = await supabase
.from('notes')
.select('id, title, author(name)')
.eq('done', false)
.order('created_at', { ascending: false })
.range(0, 19)
await supabase.from('notes').insert({ title: 'Hello' }).select().single()
await supabase.rpc('search_notes', { query: 'hello' })
curl "https://abcdefghijklmnopqrst.end.blackall.ai/rest/v1/notes?select=id,title&done=eq.false&order=created_at.desc&limit=20" \
-H "apikey: <publishable key>" \
-H "Prefer: count=exact"
未対応のもの
- 集計(
count()、sum()など)とスプレッド(...rel(*))の select public以外のスキーマ- 一度に 1000 行を超える読み取り(
limitは 1000 で切り詰められます)
認証(/auth/v1)
GoTrue と同じパスとレスポンスです。メールとパスワード、マジックリンク、匿名ログイン、ソーシャルログイン(PKCE を含む)、TOTP による二段階認証、シークレットキーによるユーザー管理に対応しています。
| メソッド | パス | 内容 | supabase-js |
|---|---|---|---|
| POST | /auth/v1/signup | サインアップ。メールとパスワードがなければ匿名ログイン | auth.signUp() / auth.signInAnonymously() |
| POST | /auth/v1/token?grant_type=password | メールとパスワードでログイン | auth.signInWithPassword() |
| POST | /auth/v1/token?grant_type=refresh_token | セッションの更新 | auth.refreshSession() |
| POST | /auth/v1/token?grant_type=pkce | PKCE のコードをセッションに交換 | auth.exchangeCodeForSession() |
| POST | /auth/v1/token?grant_type=web3 | ウォレットが署名した Sign-In with Ethereum メッセージでログイン | auth.signInWithWeb3() |
| POST | /auth/v1/token?grant_type=id_token | Google や Apple の ID トークンでログイン | auth.signInWithIdToken() |
| POST | /auth/v1/otp | マジックリンクまたは SMS の認証コードを送信 | auth.signInWithOtp({ email } | { phone }) |
| POST | /auth/v1/verify | メールのトークンまたは SMS の認証コードを確認(sms、phone_change、signup、magiclink、recovery、email_change) | auth.verifyOtp() |
| GET | /auth/v1/verify | メールのリンクを開いたとき。登録したアドレスへセッションとともに戻します | |
| POST | /auth/v1/resend | 確認メールを再送 | auth.resend() |
| POST | /auth/v1/recover | パスワード再設定メール | auth.resetPasswordForEmail() |
| POST | /auth/v1/reset | 再設定トークンで新しいパスワードを保存(戻り先がないときの画面が使用) | |
| GET | /auth/v1/user | ログイン中のユーザーと認証要素 | auth.getUser() |
| PUT | /auth/v1/user | メール、パスワード、メタデータの変更 | auth.updateUser() |
| GET | /auth/v1/reauthenticate | パスワード変更の前に確認コードをメールで送信 | auth.reauthenticate() |
| POST | /auth/v1/logout | ログアウト(scope=local|others|global) | auth.signOut({ scope }) |
| GET | /auth/v1/settings | 有効なログイン方法 | |
| GET | /auth/v1/authorize | ソーシャルログインの開始 | auth.signInWithOAuth() |
| GET | /auth/v1/callback | プロバイダーからの戻り先(Apple は POST) | |
| DELETE | /auth/v1/user/identities/{id} | 連携したソーシャルアカウントの解除 | auth.unlinkIdentity() |
| POST | /auth/v1/factors | TOTP の登録 | auth.mfa.enroll({ factorType: 'totp' }) |
| POST | /auth/v1/factors/{id}/challenge | チャレンジの開始 | auth.mfa.challenge() |
| POST | /auth/v1/factors/{id}/verify | コードの確認(aal2 セッション) | auth.mfa.verify() |
| DELETE | /auth/v1/factors/{id} | 認証要素の削除 | auth.mfa.unenroll() |
| GET | /auth/v1/admin/users | ユーザー一覧(シークレットキー、per_page は最大 1000) | auth.admin.listUsers({ page, perPage }) |
| POST | /auth/v1/admin/users | ユーザーの作成(シークレットキー) | auth.admin.createUser() |
| POST | /auth/v1/sso | SAML SSO の開始(IdP のアドレスを返す、PKCE 可) | auth.signInWithSSO({ domain } | { providerId }) |
| GET | /auth/v1/sso/saml/metadata | このプロジェクトの SP メタデータ(IdP に登録) | |
| POST | /auth/v1/sso/saml/acs | IdP が SAML レスポンスを送る先(署名・宛先・再利用を確認) | |
| GET | /auth/v1/admin/sso/providers | SSO プロバイダー一覧(シークレットキー) | auth.admin.sso.listProviders() |
| POST | /auth/v1/admin/sso/providers | SSO プロバイダーの追加(metadata_url または metadata_xml、domains) | auth.admin.sso.createProvider() |
| GET | /auth/v1/admin/sso/providers/{id} | SSO プロバイダー 1 つ | auth.admin.sso.getProvider() |
| PUT | /auth/v1/admin/sso/providers/{id} | SSO プロバイダーの変更(証明書の更新後はメタデータを再読込) | auth.admin.sso.updateProvider() |
| DELETE | /auth/v1/admin/sso/providers/{id} | SSO プロバイダーの削除 | auth.admin.sso.deleteProvider() |
| GET | /auth/v1/admin/users/{id} | ユーザー 1 人(シークレットキー) | auth.admin.getUserById() |
| PUT | /auth/v1/admin/users/{id} | ユーザーの更新(シークレットキー) | auth.admin.updateUserById() |
| DELETE | /auth/v1/admin/users/{id} | ユーザーの削除(シークレットキー) | auth.admin.deleteUser() |
| POST | /auth/v1/invite | 招待メールを送信: プロジェクトのSMTPとテンプレートで(シークレットキー) | auth.admin.inviteUserByEmail() |
| POST | /auth/v1/admin/generate_link | メールのリンクを作成: signup、invite、magiclink、recovery(シークレットキー) | auth.admin.generateLink() |
| GET | /auth/v1/.well-known/jwks.json | ユーザートークンを検証する公開キー(ES256) | |
| GET | /auth/v1/.well-known/openid-configuration | OpenID 設定(issuer、jwks_uri) | |
| GET | /auth/v1/.well-known/oauth-authorization-server | OAuth 認可サーバーのメタデータ(RFC 8414、MCP クライアント向け) | |
| GET | /.well-known/oauth-authorization-server/auth/v1 | 同じメタデータ、RFC 8414 が定めるアドレス |
トークンの発行(grant_type): password、refresh_token、pkce、id_token(Google と Apple の ID トークン)。
ソーシャルログインのプロバイダー: google, kakao, naver, apple, github, gitlab, microsoft, facebook, line, discord, x, bitbucket, figma, linkedin_oidc, notion, twitch, slack_oidc, spotify, zoom, azure, keycloak, workos, twitter, slack。設定はコンソールか、管理 API の set_auth_provider で行います。
await supabase.auth.signUp({ email: '[email protected]', password: 'a-long-passphrase' })
await supabase.auth.signInWithPassword({ email: '[email protected]', password: 'a-long-passphrase' })
await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: 'https://app.example.com' } })
const { data: { user } } = await supabase.auth.getUser()
未対応のもの
- TOTP 以外の二段階認証(WebAuthn、電話)
- 再認証(
reauthenticate)と ID の連携(linkIdentity)。連携の解除だけに対応しています auth.admin.inviteUserByEmail。代わりにgenerateLink({ type: 'invite' })を使います
ストレージ(/storage/v1)
Supabase Storage と同じパスです。ファイルの記録はプロジェクトのテーブルにあるため、誰がファイルを読み書きできるかは、そのテーブルのアクセスルールが決めます。
ファイル 1 つは既定で 50MB まで受け付けます(バケットごとにより低く設定できます)。署名付き URL は最長 7 日、アップロード用の署名付き URL は 2 時間有効です。バケット名には小文字、数字、.、_、- を使います。
| メソッド | パス | 内容 | supabase-js |
|---|---|---|---|
| GET | /storage/v1/bucket | バケット一覧 | storage.listBuckets() |
| POST | /storage/v1/bucket | バケットの作成(public、file_size_limit、allowed_mime_types) | storage.createBucket() |
| GET | /storage/v1/bucket/{bucket} | バケット 1 つ | storage.getBucket() |
| PUT | /storage/v1/bucket/{bucket} | バケットの設定変更 | storage.updateBucket() |
| DELETE | /storage/v1/bucket/{bucket} | 空のバケットを削除 | storage.deleteBucket() |
| POST | /storage/v1/bucket/{bucket}/empty | バケットを空にする | storage.emptyBucket() |
| POST | /storage/v1/object/{bucket}/{path} | アップロード(x-upsert) | from('b').upload() |
| PUT | /storage/v1/object/{bucket}/{path} | 上書き | from('b').update() |
| GET | /storage/v1/object/{bucket}/{path} | ダウンロード(呼び出した人の権限、HEAD も可) | from('b').download() |
| DELETE | /storage/v1/object/{bucket}/{path} | ファイル 1 つを削除 | |
| DELETE | /storage/v1/object/{bucket} | 複数ファイルの削除(prefixes、最大 1000) | from('b').remove([paths]) |
| GET | /storage/v1/object/public/{bucket}/{path} | 公開バケットのファイル | from('b').getPublicUrl() |
| GET | /storage/v1/object/authenticated/{bucket}/{path} | ログインユーザーとしてダウンロード | |
| POST | /storage/v1/object/list/{bucket} | フォルダー 1 階層の一覧(limit は最大 1000) | from('b').list(prefix, { limit, offset, sortBy, search }) |
| GET | /storage/v1/object/info/{bucket}/{path} | ファイルの情報 | from('b').info() |
| POST | /storage/v1/object/move | 移動 | from('b').move() |
| POST | /storage/v1/object/copy | コピー | from('b').copy() |
| POST | /storage/v1/object/sign/{bucket}/{path} | 署名付き URL の作成 | from('b').createSignedUrl(path, expiresIn, { transform }) |
| POST | /storage/v1/object/sign/{bucket} | 複数の署名付き URL(最大 100) | from('b').createSignedUrls(paths, expiresIn) |
| GET | /storage/v1/object/sign/{bucket}/{path} | 署名付き URL でダウンロード(?token=) | |
| POST | /storage/v1/object/upload/sign/{bucket}/{path} | アップロード用の署名付き URL の作成 | from('b').createSignedUploadUrl() |
| PUT | /storage/v1/object/upload/sign/{bucket}/{path} | 署名付き URL でアップロード(?token=) | from('b').uploadToSignedUrl() |
| GET | /storage/v1/render/image/public/{bucket}/{path} | 公開画像の変換 | from('b').getPublicUrl(path, { transform }) |
| GET | /storage/v1/render/image/authenticated/{bucket}/{path} | ログインユーザーとして画像を変換 | from('b').download(path, { transform }) |
| GET | /storage/v1/render/image/sign/{bucket}/{path} | 署名付き URL で画像を変換 | |
| POST | /storage/v1/upload/resumable | 再開可能なアップロードの開始(TUS 1.0、Upload-Length、Upload-Metadata に bucketName と objectName) | tus-js-client / Uppy |
| PATCH | /storage/v1/upload/resumable/{id} | 続きを送る(Upload-Offset、application/offset+octet-stream) | |
| HEAD | /storage/v1/upload/resumable/{id} | これまでに受け取ったサイズの確認 | |
| DELETE | /storage/v1/upload/resumable/{id} | 再開可能なアップロードの取り消し | |
| GET | /storage/v1/s3/{bucket}/{key} | S3 互換 API(コンソールで作った S3 キーによる SigV4 署名、path-style、既定のリージョン ap-northeast-2) | AWS SDK / rclone |
アップロードは、本文そのまま(Content-Type がファイルの形式)か multipart/form-data で送ります。POST は同じ名前があれば拒否し(x-upsert: true なら上書き)、PUT は上書きします。
画像の変換
/render/image/{public|authenticated|sign}/<バケット>/<パス> にクエリで指定します。画像変換サーバーがない環境では元の画像をそのまま返し、x-blackwall-transform ヘッダーで知らせます。
| 名前 | 説明 |
|---|---|
width | 1〜2500 ピクセル |
height | 1〜2500 ピクセル |
resize | cover(既定)、contain、fill |
quality | 20〜100(既定 80) |
format | origin(既定)、webp、avif、png、jpeg |
const bucket = supabase.storage.from('avatars')
await bucket.upload('me.png', file, { upsert: true })
const { data } = bucket.getPublicUrl('me.png', { transform: { width: 200, height: 200 } })
const { data: signed } = await bucket.createSignedUrl('me.png', 3600)
未対応のもの
- ファイルごとのキャッシュ設定(
cacheControlオプション)は保存しません
リアルタイム(/realtime/v1)
wss://<ref>.<zone>/realtime/v1/websocket?apikey=<キー>&vsn=1.0.0 は Phoenix チャネル(supabase-js が使うもの)です。vsn=2.0.0 は配列形式のメッセージとバイナリのブロードキャストです。/realtime/v1(websocket なし)は同じ機能のシンプルな JSON プロトコルです。
チャネルのトピックは realtime:<名前> です。同じ名前に参加したクライアント同士で、ブロードキャストとプレゼンスを共有します。
クライアントが送るイベント
| イベント | 説明 |
|---|---|
phx_join | チャネルに参加します。config.broadcast.self/ack、config.presence.key、config.postgres_changes、access_token |
phx_leave | チャネルから退出します |
heartbeat | phoenix トピックに送ると、サーバーがすぐに phx_reply で応答します。接続が生きているかの確認に使います |
access_token | ログインしたユーザーの新しいトークンに切り替えます |
broadcast | チャネルのほかの参加者に送ります(データベースを経由しません) |
presence | track で自分の状態を知らせ、untrack で消します |
サーバーが送るイベント
| イベント | 説明 |
|---|---|
phx_reply | 送ったメッセージへの返答(ok または error) |
presence_state | 参加したときにすでにいる人たち |
presence_diff | 参加した人と退出した人 |
broadcast | チャネルのほかの参加者に送ります(データベースを経由しません) |
postgres_changes | テーブルの行が変わった(INSERT、UPDATE、DELETE) |
phx_close | チャネルが閉じた |
system | トークン切り替えの失敗などの通知 |
postgres_changes は、コンソールか set_realtime でリアルタイムを有効にしたテーブルからだけ届きます。各行は受け取る人のアクセスルールで確認してから送られます。フィルターは 列=eq|neq|lt|lte|gt|gte|in.値 です。
supabase
.channel('room-1')
.on('broadcast', { event: 'cursor' }, ({ payload }) => console.log(payload))
.on('presence', { event: 'sync' }, () => console.log('online'))
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'notes', filter: 'done=eq.false' }, (change) => console.log(change.new))
.subscribe()
wss://abcdefghijklmnopqrst.end.blackall.ai/realtime/v1/websocket?apikey=<publishable key>&vsn=1.0.0
{"topic":"realtime:room-1","event":"phx_join","payload":{"config":{"broadcast":{"self":false},"presence":{"key":"me"},"postgres_changes":[{"event":"*","schema":"public","table":"notes"}]}},"ref":"1","join_ref":"1"}
{"topic":"realtime:room-1","event":"broadcast","payload":{"type":"broadcast","event":"cursor","payload":{"x":1}},"ref":"2","join_ref":"1"}
{"topic":"phoenix","event":"heartbeat","payload":{},"ref":"3"}
未対応のもの
- 非公開チャネル(
config.private: true) - UPDATE の変更前の値(
oldは空です)
関数(/functions/v1)
/functions/v1/<名前> はデプロイした関数を呼び出します。すべての HTTP メソッドをそのまま渡し、本文は 2MB までです。非公開(既定)の関数には、このプロジェクトのキーが必要です: 公開キー(anon)、ログインしたユーザーのトークン(authenticated)、シークレットキー(service_role)。公開としてデプロイした関数はキーなしで呼び出せます。関数にはトークンではなく、検証済みのクレームが渡されます。名前は小文字で始まり、小文字、数字、- を使います。
| メソッド | パス | 内容 | supabase-js |
|---|---|---|---|
| * | /functions/v1/{name} | 関数の呼び出し(すべてのメソッド) | functions.invoke('name', { body }) |
const { data, error } = await supabase.functions.invoke('hello', { body: { name: 'world' } })
curl -X POST "https://abcdefghijklmnopqrst.end.blackall.ai/functions/v1/hello" \
-H "Authorization: Bearer <user token or secret key>" \
-H "content-type: application/json" \
-d '{"name":"world"}'
そのほかのルート
| メソッド | パス | 内容 | supabase-js |
|---|---|---|---|
| POST | /kv/v1 | KV コマンド(Upstash 形式 ["SET", "k", "v"]、/kv/v1/pipeline、/kv/v1/keys、/kv/v1/usage も、シークレットキー) | @upstash/redis |
| * | /kv/v1/{key} | KV キー 1 つの読み書き・削除(GET・PUT・DELETE、/incr、/expire) | |
| GET | /config/v1 | エッジ設定の全体(シークレットキー) | @vercel/edge-config |
| GET | /config/v1/{key} | エッジ設定の値 1 つ | get('key') |
| POST | /ai/v1/{endpoint} | AI ゲートウェイ、OpenAI 互換(chat/completions、embeddings、images/generations、audio/speech、audio/transcriptions、models) | openai SDK (baseURL) |
| GET | /health | プロジェクトが応答するか({ project, ok }) | |
| GET | /realtime/v1/websocket | Phoenix チャネル(websocket) | channel('name').subscribe() |
| GET | /realtime/v1 | シンプルな JSON プロトコル(websocket) |
エラー
エラーは、ルートごとに Supabase のクライアントが読む形のままです。データは PostgREST と同じく code(PGRST…)、message、details、hint、認証は GoTrue と同じく code、error_code、msg(トークン発行では OAuth の error、error_description も)、ストレージは storage-js と同じく statusCode、error、message です。メッセージは Accept-Language(韓国語、英語、日本語)に従います。
{ "code": "PGRST116", "message": "…", "hint": null, "details": "…" }