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

# Quickstart

> Route your first priced, attributed LLM call through the collector in about five minutes.

Firedog sits in front of your existing LLM calls. You keep calling an OpenAI-compatible endpoint; the only change is the base URL (your in-VPC collector) and a little attribution context. The collector forwards the call to the upstream provider, prices it, writes the full record to Postgres in your VPC, and emits metadata to the dashboard.

<Info>
  This page assumes a collector is already reachable at a URL like `https://collector.internal`. For the split-plane picture — what stays in your VPC versus what reaches the cloud — see [How it works](/how-it-works) and [Security](/security).
</Info>

<Note>
  Your provider API key is forwarded by the collector to the **upstream provider** so the call can complete. It is used to authenticate to the provider and is never sent to Firedog cloud. See [/security](/security).
</Note>

## Prerequisites

<Steps>
  <Step title="A reachable collector">
    A collector running inside your VPC, exposing `POST /v1/chat/completions`. Note its URL.
  </Step>

  <Step title="An upstream provider key">
    The API key for whichever provider backs the models you call. The collector forwards it upstream; store it as an environment variable rather than inlining it.
  </Step>

  <Step title="A model string">
    One of the models Firedog prices — for example `opus`, `sonnet`, `haiku`, `gcp/gemini-2.5-pro`, `gcp/gemini-2.0-flash-lite`, or `cerebras/llama3.1-8b`.
  </Step>
</Steps>

## Choose a path

<Tabs>
  <Tab title="SDK (@firedog/sdk)">
    The SDK mirrors the OpenAI client surface. You create a client pointed at your collector, set attribution defaults once, and pass per-call context on each request.

    <Steps>
      <Step title="Install">
        <CodeGroup>
          ```bash npm theme={null}
          npm install @firedog/sdk
          ```

          ```bash pnpm theme={null}
          pnpm add @firedog/sdk
          ```

          ```bash yarn theme={null}
          yarn add @firedog/sdk
          ```
        </CodeGroup>
      </Step>

      <Step title="Create a client">
        Point `collectorUrl` at your in-VPC collector. `apiKey` is forwarded to the upstream provider. `defaultContext` is attribution applied to every call from this client.

        ```ts theme={null}
        import { createClient } from "@firedog/sdk";

        const firedog = createClient({
          collectorUrl: "https://collector.internal", // your in-VPC collector
          apiKey: process.env.PROVIDER_KEY,           // forwarded to the upstream provider
          defaultContext: { team: "macro-desk" },     // attribution on every call
        });
        ```
      </Step>

      <Step title="Make a priced, attributed call">
        Add per-call `context` to file this specific call under a workflow (and, optionally, a user).

        ```ts theme={null}
        const res = await firedog.chat.completions.create({
          model: "opus",
          messages: [{ role: "user", content: "Summarise today's macro prints." }],
          context: { workflow: "market-research", userId: "u_123" },
        });

        console.log(res.callId);                         // ULID correlating VPC record ↔ cloud metadata
        console.log(res.choices[0].message.content);
        console.log(res.usage.prompt_tokens, res.usage.completion_tokens);
        ```
      </Step>
    </Steps>

    <Check>
      A returned `callId` means the call was priced and recorded. It should appear on the dashboard **Home** view attributed to `macro-desk` / `market-research` shortly after.
    </Check>
  </Tab>

  <Tab title="Drop-in proxy (any OpenAI SDK)">
    No Firedog package required. Point any OpenAI-compatible client at the collector's base URL and carry attribution in `x-firedog-*` headers.

    <Steps>
      <Step title="Swap the base URL">
        Set `base_url` to the collector's `/v1` and pass your provider key as the API key — the collector forwards it upstream. Send attribution as default headers.

        <CodeGroup>
          ```python Python theme={null}
          from openai import OpenAI

          client = OpenAI(
              base_url="https://collector.internal/v1",  # your in-VPC collector
              api_key=os.environ["PROVIDER_KEY"],         # forwarded to the upstream provider
              default_headers={
                  "x-firedog-team": "macro-desk",
                  "x-firedog-workflow": "market-research",
                  "x-firedog-user": "u_123",
              },
          )

          res = client.chat.completions.create(
              model="opus",
              messages=[{"role": "user", "content": "Summarise today's macro prints."}],
          )
          print(res.choices[0].message.content)
          ```

          ```ts TypeScript theme={null}
          import OpenAI from "openai";

          const client = new OpenAI({
            baseURL: "https://collector.internal/v1", // your in-VPC collector
            apiKey: process.env.PROVIDER_KEY,          // forwarded to the upstream provider
            defaultHeaders: {
              "x-firedog-team": "macro-desk",
              "x-firedog-workflow": "market-research",
              "x-firedog-user": "u_123",
            },
          });

          const res = await client.chat.completions.create({
            model: "opus",
            messages: [{ role: "user", content: "Summarise today's macro prints." }],
          });
          console.log(res.choices[0].message.content);
          ```
        </CodeGroup>
      </Step>

      <Step title="Or call it directly with curl">
        The endpoint is OpenAI-compatible, so a raw request works too. Attribution rides on the same headers.

        ```bash theme={null}
        curl https://collector.internal/v1/chat/completions \
          -H "Authorization: Bearer $PROVIDER_KEY" \
          -H "Content-Type: application/json" \
          -H "x-firedog-team: macro-desk" \
          -H "x-firedog-workflow: market-research" \
          -H "x-firedog-user: u_123" \
          -d '{
            "model": "opus",
            "messages": [{"role": "user", "content": "Summarise today'\''s macro prints."}]
          }'
        ```
      </Step>
    </Steps>

    <Tip>
      Set `x-firedog-call-id` yourself (a client-minted ULID) if you want to correlate the call in your own logs before the response returns. Omit it and the collector mints one. Either way the id links the full VPC record to the cloud metadata.
    </Tip>
  </Tab>
</Tabs>

## What just happened

<CardGroup cols={2}>
  <Card title="Priced" icon="calculator">
    The collector priced the call from the shared pricing table using the model and token counts — no vendor invoice reverse-engineering required.
  </Card>

  <Card title="Attributed" icon="tags">
    Your `team` / `workflow` (and salted `userHash`) landed on the call, so it rolls up per desk and workflow on the dashboard.
  </Card>

  <Card title="Recorded in your VPC" icon="database">
    The full record — prompt messages, any RAG chunks, and the response — was written to Postgres inside your VPC and never left it.
  </Card>

  <Card title="Metadata to the cloud" icon="cloud">
    Only `CallMetadata` (ids, model, tokens, cost, latency, labels) reached the dashboard. No prompt or response content.
  </Card>
</CardGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Attribution" icon="tags" href="/attribution">
    Model the `team`, `workflow`, and `userId` context so every dollar files under the right desk and run.
  </Card>

  <Card title="Security" icon="shield-halved" href="/security">
    See exactly what stays in your VPC, what the metadata contains, and how `SensitivityProfile` controls it.
  </Card>
</CardGroup>
