---
title: API zapytań
description: Przesyłaj SQL przez HTTPS, odpytuj aż do powodzenia i pobieraj wyniki jako Parquet albo odczytuj je w odpowiedzi jako JSON.
species: reference
---

# API zapytań

Prześlij zapytanie SQL tylko do odczytu, odpytuj je według identyfikatora i odbierz wyniki — domyślnie jako podpisane adresy pobierania Parquet albo jako wiersze JSON w odpowiedzi, gdy jest to wygodniejsze. Wszystkie przykłady na tej stronie działają z `curl`.

Każde żądanie jest uwierzytelniane danymi bearer — osobistym tokenem dostępu (`pat_…`) utworzonym w dashboardzie i pokazanym raz podczas tworzenia:

```bash fragment
Authorization: Bearer pat_...
```

Przechowuj tokeny po stronie serwera; zapewniają dostęp do danych. Klucz usługi należący do organizacji (`nsk_…`) działa tak samo — zobacz [Uwierzytelnianie](/docs/api/authentication).

## Cykl życia

Zapytania działają asynchronicznie. Przesyłasz SQL i natychmiast otrzymujesz obiekt `query` ze stanem `"running"` oraz `id`. Odpytuj go co 1–2 sekundy (zwiększając odstęp dla długich zapytań — odpytywanie obciąża limit szybkości), aż `status` zmieni się na `succeeded` lub `failed`.

## Przesyłanie zapytania

```endpoint
POST /queries
```

Zwraca `202` z działającym zapytaniem; nagłówek `Location` wskazuje jego adres URL.

| Pole treści | Typ | |
|---|---|---|
| `sql` | string | Wymagane. Jedna instrukcja tylko do odczytu — ograniczenia poniżej. |

```bash
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"}'
```

```json
{
  "object": "query",
  "id": "qr_...",
  "status": "running",
  "created": 1751731200,
  "sql": "select currency, count(*) as n ...",
  "livemode": true
}
```

Ponawianie jest bezpieczne z nagłówkiem `Idempotency-Key`: powtórzenie tego samego klucza zwraca pierwotny obiekt zapytania zamiast uruchamiać je ponownie i jest oznaczone nagłówkiem `Idempotent-Replayed: true`. Klucz jest powiązany z dokładnym `sql` pierwszego uruchomienia — użycie go z innym SQL zostaje odrzucone przez `409 idempotency_key_reused`, więc zmieniona próba nigdy po cichu nie zwróci starego wyniku. Klucze wygasają po 24 godzinach.

## Pobieranie stanu i wyników

```endpoint
GET /queries/{id}
```

Zwraca stan zapytania, a po pomyślnym zakończeniu także wyniki.

| Parametr zapytania | Typ | |
|---|---|---|
| `format` | string | `files` (domyślnie) zwraca podpisane adresy pobierania Parquet; `inline` zwraca wiersze w odpowiedzi. |
| `limit` | integer | Tylko `inline`. Wiersze na stronę — domyślnie 100, maksymalnie 1000. |
| `starting_after` | string | Tylko `inline`. `next_cursor` z poprzedniej strony. |

```bash
curl https://api.supernova.ai/queries/qr_... \
  -H "Authorization: Bearer pat_..."
```

```json
{
  "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` jest czasem wykonania bez czasu oczekiwania przed rozpoczęciem. Dla `format=inline` wiersze wracają stronicowane w odpowiedzi, a `row_count` jest sumą wszystkich stron:

```json
{
  "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
}
```

Nieudane zapytanie zawiera ustrukturyzowany błąd zamiast wyników:

```json
{
  "object": "query",
  "id": "qr_...",
  "status": "failed",
  "created": 1751731200,
  "duration_ms": 64,
  "error": { "message": "Binder Error: Table \"custmers\" does not exist" }
}
```

## Pliki wyników

Podpisane adresy URL nie wymagają uwierzytelniania — każdy ich posiadacz może pobrać plik do czasu wygaśnięcia, dlatego traktuj je jak same dane. Adresy są ważne przez 1 godzinę; każde odpytanie wystawia nowe. Odczytuj `files` jako listę, choć obecnie wynik jest jednym plikiem — duże wyniki mogą w przyszłości zostać podzielone. Adresy obsługują żądania zakresów HTTP, dzięki czemu czytniki Parquet pobierają dane wybiórczo:

```sql fragment
-- DuckDB, in your own environment
select * from read_parquet('https://storage.googleapis.com/...')
```

```text
# pandas
df = pd.read_parquet("https://storage.googleapis.com/...")
```

Odpowiedzi tylko z plikami nie skanują Parquet, dlatego `row_count` ma w nich wartość `null`; dokładna liczba znajduje się w metadanych Parquet lub na dowolnej stronie inline.

Pobieraj wyniki szybko: zapytania i ich wyniki są przechowywane przez co najmniej 24 godziny od przesłania.

## Ograniczenia SQL

Zapytanie jest odrzucane przed wykonaniem (HTTP 400), jeśli zawiera więcej niż jedną instrukcję (`multiple_statements`), nie jest tylko do odczytu — słowa kluczowe zapisu, DDL i sesji są odrzucane, choć mogą występować w literałach tekstowych, więc `where type = 'DELETE'` działa (`write_not_allowed`) — wywołuje funkcję pliku lub magazynu, na przykład `read_parquet` albo `read_csv`, nawet w literale (`forbidden_function`), lub przekracza 100 000 znaków (`sql_too_long`). Identyfikatory URI magazynu (`gs://`, `s3://`, `file://`) są odrzucane wszędzie w tekście zapytania. Aby filtrować kolumnę zawierającą takie wartości, dopasuj podciąg bez schematu: `where path like '%bucket/x%'`.

## Uprawnienia do tabel

Organizacja może określić, które tabele mogą odczytywać poszczególne osoby, role i dane uwierzytelniające. Zapytanie wskazujące niedostępną tabelę jest odrzucane przed wykonaniem przez `403` z nazwą tabeli, a te same tabele są nieobecne w [katalogu](/docs/api/catalog).

```json
{
  "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_..."
  }
}
```

## Błędy

Błędy zwracają odpowiadający stan HTTP i treść JSON. Każda odpowiedź ma nagłówek `Request-Id`; podaj go podczas kontaktu z pomocą techniczną. Błędy powiązane z konkretnym polem wskazują je w `param`, a `doc_url` prowadzi do objaśnienia kodu:

```json
{
  "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_..."
  }
}
```

Kody zwracane przez ten zasób:

| Stan | Kod | Znaczenie |
|---|---|---|
| 400 | `parameter_missing` | Brak wymaganego parametru, na przykład `sql` |
| 400 | `write_not_allowed` | Zapytanie zawiera zapis, DDL lub słowo kluczowe sesji |
| 400 | `multiple_statements` | Więcej niż jedna instrukcja rozdzielona `;` |
| 400 | `forbidden_function` | Odwołanie do funkcji pliku lub magazynu |
| 400 | `sql_too_long` | `sql` przekracza 100 000 znaków |
| 400 | `invalid_format` | `format` nie jest `files` ani `inline` |
| 400 | `invalid_cursor` | `starting_after` nie jest kursorem z poprzedniej strony |
| 403 | `grant_table_denied` | Zapytanie wskazuje tabelę niedostępną dla tych danych uwierzytelniających |
| 403 | `service_key_permissions_off` | Prawidłowy klucz usługi w organizacji, która nie włączyła uprawnień do tabel |
| 403 | `grant_introspection_denied` | Zapytanie wyświetla tabele, czego ograniczone dane nie mogą robić |
| 404 | `query_not_found` | Brak zapytania o takim identyfikatorze na tym koncie |
| 409 | `idempotency_key_reused` | `Idempotency-Key` był już użyty z innym `sql` |
| 429 | `rate_limited` | Przekroczono limit szybkości żądań — przestrzegaj `Retry-After` |
| 429 | `too_many_queries` | Zbyt wiele zapytań w toku na koncie |

## Limity szybkości

Każdy wywołujący może wysłać do 120 żądań na minutę, a każde konto łącznie do 600 żądań na minutę dla wszystkich wywołujących. Po przekroczeniu żądania zwracają `429` z nagłówkiem `Retry-After` w sekundach. Istnieje też limit jednoczesnych zapytań w toku na konto (`too_many_queries`). Przy zalecanym odpytywaniu co 1–2 sekundy jeden wywołujący może wygodnie śledzić kilka zapytań jednocześnie — zwiększ odstęp przy większej liczbie równoległych zadań.
