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

# Quickstart

> Install the SDK and wrap your first OpenAI call with Pikarc in 5 minutes.

<Steps>
  <Step title="Install the SDK">
    ```bash theme={null}
    pip install pikarc
    ```
  </Step>

  <Step title="Get your API key">
    Sign up at [app.pikarc.dev](https://app.pikarc.dev/auth) and copy your API key from **Settings > API Key**. The key format is `lg_<prefix>_<secret>`.
  </Step>

  <Step title="Wrap your model call">
    ```python theme={null}
    from pikarc import AsyncPikarc, PikarcBlockedError
    from openai import AsyncOpenAI

    openai = AsyncOpenAI()
    guard = AsyncPikarc(
        api_key="lg_xxxx_your_api_key",
        base_url="http://localhost:8000",
    )

    async def chat(user_id: str, message: str) -> str:
        try:
            async with guard.run(user_id=user_id) as run:
                response = await run.model_call(
                    fn=lambda: openai.chat.completions.create(
                        model="gpt-4o",
                        messages=[{"role": "user", "content": message}],
                    ),
                    model="gpt-4o",
                    input_data={"messages": [{"role": "user", "content": message}]},
                    token_extractor=lambda r: (
                        r.usage.prompt_tokens,
                        r.usage.completion_tokens,
                    ),
                )
                return response.choices[0].message.content or ""

        except PikarcBlockedError as e:
            return f"Blocked: {e.reason}"

        finally:
            await guard.close()
    ```
  </Step>

  <Step title="See it in the dashboard">
    Open your [dashboard](https://app.pikarc.dev/dashboard) to see the run, step timeline, token usage, and cost breakdown.
  </Step>
</Steps>

## What just happened?

1. `guard.run()` called `POST /v1/runs/` — Pikarc checked the kill switch, budgets, and concurrency limits. The run was **ALLOWED**.
2. `run.model_call()` called `POST /v1/runs/{id}/steps` — Pikarc evaluated guardrails again before the model call.
3. After OpenAI responded, the SDK called `PATCH /v1/runs/{id}/steps/{step_id}` to report token usage and duration.
4. When the `async with` block exited, the SDK called `POST /v1/runs/{id}/end` to mark the run as **COMPLETED**.

If any guardrail check had failed (budget exceeded, kill switch active, etc.), `PikarcBlockedError` would have been raised **before** the model call executed.

## Next steps

* [Add tool call guardrails](/sdk/guarded-run#tool-calls) — wrap tool executions too
* [Configure budgets](/guides/cost-tracking) — set workspace and per-user daily limits
* [Understand deny reasons](/sdk/error-handling) — handle all 7 deny reason codes
