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

# Quickstart

> From a fresh account to a working call, in three steps.

You need an account on the [console](https://compute.prentis.ai) and about two minutes.

## 1. Create an API key

Keys live in the console, under **API Keys**. The plaintext key is shown **once, at
creation** — we store only a hash, so there is no screen anywhere that can show it to you
again. Lose it and you revoke it and make another.

<Card title="Create a key" icon="key" href="https://compute.prentis.ai">
  Opens the console in a new tab.
</Card>

## 2. Put it in your environment

Every snippet on this site reads the key from the environment. None of them contain one.

```bash theme={null}
export PRENTIS_API_KEY="mk-prod-…"
```

## 3. Make the call

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl https://compute.prentis.ai/v1/chat/completions \
      -H "Authorization: Bearer $PRENTIS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "deepseek-v4.1-flash",
        "messages": [
          {"role": "system", "content": "You are a concise assistant."},
          {"role": "user", "content": "Summarise the CAP theorem in two sentences."}
        ],
        "max_tokens": 200
      }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os
    from openai import OpenAI

    client = OpenAI(
        base_url="https://compute.prentis.ai/v1",
        api_key=os.environ["PRENTIS_API_KEY"],
    )

    resp = client.chat.completions.create(
        model="deepseek-v4.1-flash",
        messages=[
            {"role": "system", "content": "You are a concise assistant."},
            {"role": "user", "content": "Summarise the CAP theorem in two sentences."},
        ],
        max_tokens=200,
    )
    print(resp.choices[0].message.content)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={null}
    import OpenAI from "openai";

    const client = new OpenAI({
      baseURL: "https://compute.prentis.ai/v1",
      apiKey: process.env.PRENTIS_API_KEY,
    });

    const resp = await client.chat.completions.create({
      model: "deepseek-v4.1-flash",
      messages: [
        { role: "system", content: "You are a concise assistant." },
        { role: "user", content: "Summarise the CAP theorem in two sentences." },
      ],
      max_tokens: 200,
    });
    console.log(resp.choices[0]?.message.content);
    ```
  </Tab>
</Tabs>

<Note>
  Already using an OpenAI SDK? `base_url` and `api_key` are the only two lines that change.
  Already using an Anthropic SDK? Point it at `https://compute.prentis.ai` and call
  [`/v1/messages`](/api-reference/messages) instead — your `x-api-key` header works as-is.
</Note>

## Read the response

Three things in every answer are worth knowing about:

<CardGroup cols={3}>
  <Card title="x-request-id" icon="fingerprint">
    A header on **every** response, successes and errors alike. It is the handle that
    reaches the whole path your request took. Quote it when you ask us anything about a
    call.
  </Card>

  <Card title="usage" icon="calculator">
    The token counts you were billed for — not an estimate of them. When streaming, it
    arrives on the last data event.
  </Card>

  <Card title="x-provider-class" icon="route">
    `primary` or `fallback`: whether your call was served by the first choice or a standby.
    It never names who served it.
  </Card>
</CardGroup>

## Stream it

Set `stream: true` and the same call answers `text/event-stream`, one chunk per event,
ending with `data: [DONE]`. The last data event carries `usage` whether or not you asked
for it, so streaming never costs you the billing numbers.

```python theme={null}
stream = client.chat.completions.create(
    model="deepseek-v4.1-flash",
    messages=[{"role": "user", "content": "Count to five."}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
```

## What a failed call costs

Nearly always: nothing. Of the 28 errors this API can return, only two still produce a
usage record, and both are cases where the model had already generated output when the
call came apart. The full table is on [Errors](/errors).

## Next

<CardGroup cols={2}>
  <Card title="Authentication" icon="lock" href="/authentication">
    Bearer keys, the `x-api-key` alias, and what happens when a key is revoked.
  </Card>

  <Card title="Models and resource names" icon="boxes" href="/models-and-resource-names">
    When to write `deepseek-v4.1-flash` and when to write `accounts/acme/models/…`.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/introduction">
    Every endpoint, parameter and status code.
  </Card>

  <Card title="Rate limits and quotas" icon="gauge" href="/rate-limits-and-quotas">
    What throttles you, and which of the three 429s you are looking at.
  </Card>
</CardGroup>
