クエリ API#
読み取り専用 SQL クエリを送信し、ID でポーリングして、結果を取得します。デフォルトでは署名付き Parquet ダウンロード URL として取得でき、必要に応じてインラインの JSON 行として取得できます。このページのすべての操作は curl で実行できます。
すべてのリクエストは、ベアラー認証情報で認証します。個人アクセストークン(pat_…)はダッシュボードで作成でき、作成時に一度だけ表示されます。
Authorization: Bearer pat_...トークンはデータへのアクセスを許可するため、サーバー側で保持してください。組織が所有するサービスキー(nsk_…)も同じように動作します。認証を参照してください。
ライフサイクル#
クエリは非同期で実行されます。SQL を送信すると、status: "running" と id を含む query オブジェクトがすぐに返されます。status が succeeded または failed になるまで、1~2 秒ごとにポーリングしてください。長時間のクエリでは間隔を延ばしてください。ポーリングもレート制限の対象です。
クエリを送信#
実行中のクエリとともに 202 を返します。Location ヘッダーは、そのクエリの URL を指します。
| 本文のフィールド | 型 | |
|---|---|---|
sql | string | 必須。読み取り専用の文を 1 つ指定します。制限は後述します。 |
curl https://api.supernova.ai/queries \
-H "Authorization: Bearer pat_..." \
-H "Content-Type: application/json" \
-d '{"sql": "select currency, count(*) as n from stripe.customers group by currency"}'{
"object": "query",
"id": "qr_...",
"status": "running",
"created": 1751731200,
"sql": "select currency, count(*) as n ...",
"livemode": true
}Idempotency-Key ヘッダーを使うと、安全に再試行できます。同じキーを再送した場合は再実行せず、元のクエリオブジェクトを返し、Idempotent-Replayed: true ヘッダーでそのことを示します。キーは、最初に実行した sql と完全一致で紐づきます。異なる SQL での再利用は 409 idempotency_key_reused で拒否されるため、内容を変更した再試行で、古いクエリ結果が黙って返されることはありません。キーは 24 時間後に期限切れになります。
ステータスと結果を取得#
クエリのステータスと、成功後にはその結果を取得します。
| クエリパラメーター | 型 | |
|---|---|---|
format | string | files(デフォルト)は署名付き Parquet ダウンロード URL を返し、inline はレスポンス内に行を返します。 |
limit | integer | inline のみ。1 ページあたりの行数。デフォルトは 100、最大は 1000。 |
starting_after | string | inline のみ。前のページから取得した next_cursor。 |
curl https://api.supernova.ai/queries/qr_... \
-H "Authorization: Bearer pat_..."{
"object": "query",
"id": "qr_...",
"status": "succeeded",
"created": 1751731200,
"duration_ms": 812,
"row_count": null,
"files": [
{ "url": "https://storage.googleapis.com/...", "bytes": 18734, "expires": 1751734800 }
]
}duration_ms は実行時間で、実行開始までの時間を含みません。format=inline を指定すると、レスポンス内にページ分割された行が返されます。row_count は全ページの合計です。
{
"object": "query",
"id": "qr_...",
"status": "succeeded",
"created": 1751731200,
"duration_ms": 812,
"columns": ["currency", "n"],
"row_count": 3,
"data": [
{ "currency": "usd", "n": 1230 },
{ "currency": "eur", "n": 88 },
{ "currency": "gbp", "n": 41 }
],
"has_more": false,
"next_cursor": null
}失敗したクエリには、結果の代わりに構造化エラーが含まれます。
{
"object": "query",
"id": "qr_...",
"status": "failed",
"created": 1751731200,
"duration_ms": 64,
"error": { "message": "Binder Error: Table \"custmers\" does not exist" }
}結果ファイル#
署名付き URL に認証は不要です。URL を持つ人は、有効期限までファイルをダウンロードできるため、データそのものと同様に扱ってください。URL の有効期間は 1 時間で、ポーリングのたびに新たに発行されます。現在の結果は単一ファイルですが、将来は大きな結果が分割される可能性があるため、files はリストとして読み取ってください。URL は HTTP Range リクエストに対応しており、Parquet リーダーは必要な範囲を選択して取得できます。
-- DuckDB, in your own environment
select * from read_parquet('https://storage.googleapis.com/...')# pandas
df = pd.read_parquet("https://storage.googleapis.com/...")ファイルのみのレスポンスでは Parquet を走査しないため、row_count は null になります。正確な件数は、Parquet のメタデータ、または任意のインラインページに含まれます。
結果は速やかに取得してください。クエリとその結果は、送信後少なくとも 24 時間保持されます。
SQL の制限#
次の場合、クエリは実行前に拒否されます(HTTP 400)。文が複数ある場合(multiple_statements)、読み取り専用でない場合(write_not_allowed)、read_parquet や read_csv などのファイルまたはストレージ関数を、文字列リテラル内も含めて呼び出す場合(forbidden_function)、100,000 文字を超える場合(sql_too_long)です。書き込み、DDL、セッションのキーワードは拒否されますが、文字列リテラル内では許可されるため、where type = 'DELETE' は使用できます。ストレージ URI(gs://、s3://、file://)は、クエリ本文のどこにあっても拒否されます。それらを含む列を絞り込むには、スキームを除いた部分文字列で照合してください: where path like '%bucket/x%'。
テーブル権限#
組織は、各ユーザー、ロール、認証情報が読み取れるテーブルを決定できます。設定済みの組織では、この認証情報で読み取れないテーブルを指定したクエリは、実行前に 403 とテーブル名を返して拒否されます。同じテーブルはカタログにも表示されません。
{
"error": {
"type": "permission_error",
"code": "grant_table_denied",
"message": "Table stripe.charges is not available to the API for your organization",
"doc_url": "https://api.supernova.ai/docs#grant_table_denied",
"request_id": "req_..."
}
}エラー#
エラーは、対応する HTTP ステータスと JSON 本文を返します。すべてのレスポンスに Request-Id ヘッダーが含まれるため、サポートへのお問い合わせ時にお知らせください。特定の入力に関するエラーは、その入力を param に示し、doc_url にコードの説明へのリンクを示します。
{
"error": {
"type": "invalid_request_error",
"code": "write_not_allowed",
"message": "Only read-only queries are allowed. ...",
"doc_url": "https://api.supernova.ai/docs#write_not_allowed",
"request_id": "req_..."
}
}このリソースが返すコード:
| ステータス | コード | 意味 |
|---|---|---|
| 400 | parameter_missing | 必須パラメーター(例: sql)がない |
| 400 | write_not_allowed | クエリに書き込み、DDL、またはセッションのキーワードが含まれている |
| 400 | multiple_statements | ; で区切られた文が複数ある |
| 400 | forbidden_function | ファイルまたはストレージ関数が参照されている |
| 400 | sql_too_long | sql が 100,000 文字を超えている |
| 400 | invalid_format | format が files でも inline でもない |
| 400 | invalid_cursor | starting_after が前のページのカーソルではない |
| 403 | grant_table_denied | この認証情報で読み取れないテーブルがクエリに指定されている |
| 403 | service_key_permissions_off | テーブル権限を有効にしていない組織で、有効なサービスキーが使用された |
| 403 | grant_introspection_denied | 制限付きの認証情報では許可されないテーブル一覧の取得を、クエリが行った |
| 404 | query_not_found | このアカウントに、その ID のクエリが存在しない |
| 409 | idempotency_key_reused | Idempotency-Key が、異なる sql ですでに使用されている |
| 429 | rate_limited | リクエストのレート制限を超過。Retry-After に従ってください |
| 429 | too_many_queries | アカウントの処理中クエリが多すぎる |
レート制限#
各呼び出し元は 1 分間に最大 120 件、各アカウントは呼び出し元全体で 1 分間に最大 600 件のリクエストを送信できます。いずれかを超えると、リクエストは 429 と、秒単位の Retry-After ヘッダーを返します。アカウントごとの同時処理中クエリ数にも上限があります(too_many_queries)。推奨の 1~2 秒間隔であれば、1 つの呼び出し元で数件のクエリを同時にポーリングできます。多数を並行実行する場合は、間隔を延ばしてください。