> ## Documentation Index
> Fetch the complete documentation index at: https://docs.priorlabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API quickstart

> Authenticate, upload data, fit a model, and predict using the TabPFN REST API.

<Note>
  **Prefer the Python SDK:** [`tabpfn-client`](https://github.com/PriorLabs/tabpfn-client) wraps the full upload → fit → predict flow behind the familiar scikit-learn interface. Use this REST guide when you need the raw HTTP contract or are integrating from a non-Python environment.
</Note>

New integrations should target the **`/tabpfn/*` JSON endpoints**. The legacy `/v1/fit` and `/v1/predict` multipart routes will remain available for a short period of time — see the [TabPFN-3 changelog](/changelog/tabpfn-3).

***

## 1. Get your API key

1. Visit [ux.priorlabs.ai](https://ux.priorlabs.ai) and sign in.
2. Complete account setup.
3. Navigate to the **API Keys** page.
4. Copy your key.

<Warning>
  Your API key grants full API access. Store it in a secret manager or environment variable — never commit it to source control.
</Warning>

If you use `tabpfn-client`, you can authenticate programmatically with `set_access_token(api_key)` or interactively with `init()`, which opens a browser-based login flow.

***

## 2. Check model limits

Before uploading, call `GET /tabpfn/get_model_limits` to retrieve the current per-version constraints (max rows, features, classes, dataset size). This lets you validate data locally before upload.

```python theme={null}
import httpx

TOKEN = "<YOUR_TOKEN>"
BASE = "https://api.priorlabs.ai"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}

res = httpx.get(f"{BASE}/tabpfn/get_model_limits", headers=HEADERS)
res.raise_for_status()
limits = res.json()
```

Key v3 limits: up to **1M train rows**, **100M train cells**, **200K test rows**, **160 classes**, **2,000 columns**, and **5 GB** max upload size.

***

## 3. Upload the training set

Request signed upload URLs, then PUT your data files directly to cloud storage. Both CSV and Parquet formats are supported.

```python theme={null}
from pathlib import Path

res = httpx.post(
    f"{BASE}/tabpfn/prepare_train_set_upload",
    headers=HEADERS,
    json={
        "x_train_info": {"format": "csv"},
        "y_train_info": {"format": "csv"},
    },
)
res.raise_for_status()
prep = res.json()

train_set_upload_id = prep["train_set_upload_id"]

for path, info in [
    (Path("x_train.csv"), prep["x_train_info"]),
    (Path("y_train.csv"), prep["y_train_info"]),
]:
    httpx.put(
        info["signed_urls"][0],
        content=path.read_bytes(),
        headers=info["required_headers"],
    ).raise_for_status()
```

***

## 4. Fit the model

Reference the uploaded training set and specify the task. The response returns a `fitted_train_set_id` for use in predictions.

```python theme={null}
res = httpx.post(
    f"{BASE}/tabpfn/fit",
    headers=HEADERS,
    json={
        "train_set_upload_id": train_set_upload_id,
        "task": "classification",
    },
)
res.raise_for_status()

fitted_train_set_id = res.json()["fitted_train_set_id"]
```

To enable [thinking mode](/capabilities/thinking-mode), add the thinking parameters:

```python theme={null}
res = httpx.post(
    f"{BASE}/tabpfn/fit",
    headers=HEADERS,
    json={
        "train_set_upload_id": train_set_upload_id,
        "task": "classification",
        "thinking_effort": "high",
        "thinking_timeout_s": 300,
        "thinking_effort_metric": "log_loss",
    },
)
```

<Note>
  Thinking fits can take minutes. If the fit exceeds 2 seconds, the server streams keepalive whitespace before sending the final JSON payload. Your HTTP client must handle chunked responses.
</Note>

***

## 5. Upload the test set

Same signed-URL flow as the training set, but linked to the fitted model.

```python theme={null}
res = httpx.post(
    f"{BASE}/tabpfn/prepare_test_set_upload",
    headers=HEADERS,
    json={
        "fitted_train_set_id": fitted_train_set_id,
        "x_test_info": {"format": "csv"},
    },
)
res.raise_for_status()
prep = res.json()

test_set_upload_id = prep["test_set_upload_id"]
info = prep["x_test_info"]

httpx.put(
    info["signed_urls"][0],
    content=Path("x_test.csv").read_bytes(),
    headers=info["required_headers"],
).raise_for_status()
```

***

## 6. Predict

Run predictions using the fitted model and the uploaded test set.

```python theme={null}
res = httpx.post(
    f"{BASE}/tabpfn/predict",
    headers=HEADERS,
    json={
        "test_set_upload_id": test_set_upload_id,
        "fitted_train_set_id": fitted_train_set_id,
        "task_config": {
            "task": "classification",
            "predict_params": {"output_type": "probas"},
        },
    },
)
res.raise_for_status()
result = res.json()

prediction = result["prediction"]
metadata = result["metadata"]
```

**Classification output types:** `"probas"` (default) returns class probabilities, `"preds"` returns predicted labels.

**Regression output types:** `"mean"` (default), `"median"`, `"mode"`, `"quantiles"` (pass a `quantiles` list), or `"full"` (full predictive distribution, limited to 400 test rows).

***

## 7. Metering and limits

Predictions consume tokens from daily and monthly pools. Thinking fits have a separate monthly quota. Read [API metering](/api-reference/metering) before running load tests or production workloads.

***

## Error handling

All error responses follow a consistent envelope:

```json theme={null}
{
  "message": "Human-readable error description",
  "error_code": "NOT_FOUND",
  "trace_id": "abc123"
}
```

| Status | Meaning                                                     |
| ------ | ----------------------------------------------------------- |
| 401    | Missing or invalid authentication token                     |
| 404    | Resource not found (upload, fitted model)                   |
| 409    | Duplicate upload — reuse the returned ID                    |
| 422    | Validation error (invalid parameters, data issues)          |
| 429    | Rate limit — daily, monthly, or thinking fit quota exceeded |

***

<CardGroup cols={2}>
  <Card title="API metering" icon="gauge" href="/api-reference/metering">
    Token budgets, usage pools, and thinking fit limits.
  </Card>

  <Card title="Security" icon="shield" href="/api-reference/security">
    Encryption, data isolation, and access controls.
  </Card>

  <Card title="Thinking mode" icon="brain" href="/capabilities/thinking-mode">
    Fit-time optimization for better predictions.
  </Card>

  <Card title="FAQ" icon="question-circle" href="/faq">
    GPUs, limits, and product questions.
  </Card>
</CardGroup>
