# Anthropic integration

## Base URL

```
https://www.spendline.ai
```

**Without `/v1`.** The Anthropic SDK appends `/v1/messages` itself. If you add
`/v1` here you will get requests to `/v1/v1/messages` and a 404.

This is the single most common Spendline integration mistake. The OpenAI SDK
needs `/v1`; the Anthropic SDK does not. Both are correct.

## Auth

| Header | Value |
|---|---|
| `x-api-key` | The application's **own Anthropic key**. Forwarded upstream. |
| `x-spendline-key` | The **Spendline** key. Consumed by Spendline. |

The Anthropic SDK sets the provider key for you from `apiKey` / `api_key`:
version 0.x sends it in `x-api-key`, version 1.x sends it as
`Authorization: Bearer`. Spendline accepts either on `/v1/messages` and forwards
it to Anthropic in `x-api-key`. If both are sent, `x-api-key` is used.

Because Anthropic already owns `x-api-key`, the Spendline key **must** travel in
`x-spendline-key`. A Spendline key placed in `x-api-key` on `/v1/messages` is
refused with 401 and is never forwarded to Anthropic.

## Python

```python
import os
import uuid
from anthropic import Anthropic

client = Anthropic(
    base_url="https://www.spendline.ai",            # no /v1
    api_key=os.environ["ANTHROPIC_API_KEY"],
    default_headers={
        "x-spendline-key": os.environ["SPENDLINE_API_KEY"],
        "x-agent-id": "support-bot",
        "x-spendline-tags": '{"team":"support"}',
    },
)

msg = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Draft a reply."}],
    extra_headers={
        "x-customer-id": customer_id,                # per request
        "Idempotency-Key": str(uuid.uuid4()),        # per logical request
    },
)
```

## TypeScript

```ts
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  baseURL: "https://www.spendline.ai",              // no /v1
  apiKey: process.env.ANTHROPIC_API_KEY!,
  defaultHeaders: {
    "x-spendline-key": process.env.SPENDLINE_API_KEY!,
    "x-agent-id": "support-bot",
    "x-spendline-tags": '{"team":"support"}',
  },
});

await client.messages.create(
  {
    model: "claude-sonnet-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Draft a reply." }],
  },
  { headers: { "x-customer-id": customerId, "Idempotency-Key": crypto.randomUUID() } },
);
```

**`Idempotency-Key` is required** on every proxied request to the hosted
service (a request without one is refused with `400 idempotency_key_required`
before anything is sent to the provider). Generate one value (a UUID) per
logical request **before the first attempt** and reuse it on every retry of
that request. The SDK's own automatic retries reuse the headers of the call, so
generating it in the call, as below, is correct. If you write your own retry
loop, create the key outside the loop: a fresh key per attempt makes each retry
a separate purchase.


## curl

```bash
curl https://www.spendline.ai/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-spendline-key: $SPENDLINE_API_KEY" \
  -H "x-agent-id: smoke-test" \
  -H "x-customer-id: cus_123" \
  -H 'x-spendline-tags: {"team":"platform"}' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-5","max_tokens":64,"messages":[{"role":"user","content":"hello"}]}'
```

## Streaming

Supported. Pass `stream: true` as normal.

## LangChain / Vercel AI SDK

`ChatAnthropic` and `createAnthropic({ baseURL: "https://www.spendline.ai" })`, 
same rule, no `/v1`.
