---
title: SDKs
description: Use the official OpenAI, Anthropic and Google Gen AI SDKs with Half Off Dev at half the official price by setting two client options.
---

Because Half Off Dev speaks each vendor's API in its own format, you don't need a special client library. Install the official SDK, give the client constructor Half Off Dev's base URL and your key, and follow the vendor's documentation for everything after that. Create an [API key](/app/keys) first.

> [!TIP]
> Under **Use in tools** on [API keys](/app/keys), the **cURL / SDK** tab has these samples with your key already inserted.

## Anthropic SDK {#anthropic}

Base URL `https://halfoff.dev`, without `/v1`: the SDK adds the version itself.

```python title="Python"
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://halfoff.dev",
    api_key=os.environ["HALFOFF_API_KEY"],
)
message = client.messages.create(
    model="claude-sonnet-5.5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Suggest a name for a CLI that renames files."}],
)
print(message.content[0].text)
```

```js title="Node.js"
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({
  baseURL: 'https://halfoff.dev',
  apiKey: process.env.HALFOFF_API_KEY,
});
const message = await client.messages.create({
  model: 'claude-sonnet-5.5',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Suggest a name for a CLI that renames files.' }],
});
console.log(message.content[0].text);
```

## OpenAI SDK {#openai}

Base URL `https://halfoff.dev/v1`.

```python title="Python"
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://halfoff.dev/v1",
    api_key=os.environ["HALFOFF_API_KEY"],
)
completion = client.chat.completions.create(
    model="gpt-6.1-sol",
    messages=[{"role": "user", "content": "Write a regex that matches ISO dates."}],
)
print(completion.choices[0].message.content)
```

```js title="Node.js"
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://halfoff.dev/v1',
  apiKey: process.env.HALFOFF_API_KEY,
});
const completion = await client.chat.completions.create({
  model: 'gpt-6.1-sol',
  messages: [{ role: 'user', content: 'Write a regex that matches ISO dates.' }],
});
console.log(completion.choices[0].message.content);
```

Chat Completions accepts every text model, so this one client can also call `claude-sonnet-5.5` or `gemini-3.1-pro` by changing `model`.

## Google Gen AI SDK {#google-genai}

Base URL `https://halfoff.dev`, passed through the HTTP options.

```python title="Python"
import os
from google import genai
from google.genai import types

client = genai.Client(
    api_key=os.environ["HALFOFF_API_KEY"],
    http_options=types.HttpOptions(base_url="https://halfoff.dev"),
)
response = client.models.generate_content(
    model="gemini-3.1-pro",
    contents="Summarise the CAP theorem in one paragraph.",
)
print(response.text)
```

```js title="Node.js"
import { GoogleGenAI } from '@google/genai';

const ai = new GoogleGenAI({
  apiKey: process.env.HALFOFF_API_KEY,
  httpOptions: { baseUrl: 'https://halfoff.dev' },
});
const response = await ai.models.generateContent({
  model: 'gemini-3.1-pro',
  contents: 'Summarise the CAP theorem in one paragraph.',
});
console.log(response.text);
```

Format-specific details: [Anthropic Messages](/docs/models/anthropic), [OpenAI Chat Completions](/docs/models/openai), [Gemini](/docs/models/gemini).

## Fixing errors {#troubleshooting}

| What you see | What to do |
| --- | --- |
| `401` `Missing API key` | The client sent no key. Check that `HALFOFF_API_KEY` is set where your code runs. |
| `401` `Invalid or revoked API key` | The key was mistyped, cut short or revoked. Paste it again or make a new one. |
| `404` `Model '...' is not available` | That id doesn't exist. Copy one from `GET /v1/models` or the [model list](/models). |
| `404` with `/v1/v1/` in the path | You gave the Anthropic SDK `https://halfoff.dev/v1`. It adds `/v1` itself, so pass `https://halfoff.dev`; only the OpenAI SDK takes the `/v1` form. |
| `402` | The balance is empty or the key has hit its spend cap. See [Billing](/docs/account/billing). |

Any other status is explained in [Errors](/docs/api/errors).
