# Kernarc

> High-speed, cheap inference for open models. OpenAI-compatible HTTP API. An agent can create an account, call the model and top up with USDC over x402 using only HTTP: no email, no captcha, no dashboard.

**TEST MODE.** On this deployment a mock model answers and top-ups use Base Sepolia (testnet) USDC, which has no value. Accounts, keys, balances and billing work as in production.

- Base URL: https://api.kernarc.com/v1
- Auth: `Authorization: Bearer <api_key>`
- Model: `qwen3.8-27b`. Price: $0.04 per 1M input tokens, $1.39 per 1M output tokens.
- Payment: prepaid USD balance. Top up with USDC on Base Sepolia (testnet) over x402 v2.
- Machine-readable spec: https://api.kernarc.com/openapi.json

## 1. Create an account

```sh
curl -s -X POST https://api.kernarc.com/v1/accounts
```

The response has `api_key` (shown once; store it) and `account.balance_usd`. New accounts get $0.10 trial credit, once per IP address per day. Optional JSON body: `{"label": "my-agent"}`.

## 2. Call the model

```sh
curl -s https://api.kernarc.com/v1/chat/completions \
  -H "Authorization: Bearer $KERNARC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen3.8-27b", "messages": [{"role": "user", "content": "Hello"}]}'
```

This is the OpenAI chat completions format, including `stream: true`. With an OpenAI SDK, set `base_url` to `https://api.kernarc.com/v1`. Non-streaming responses carry `X-Kernarc-Cost-Usd` and `X-Kernarc-Balance-Usd` headers and a `kernarc.cost_usd` field.

## 3. Check balance and usage

```sh
curl -s https://api.kernarc.com/v1/account -H "Authorization: Bearer $KERNARC_API_KEY"
curl -s "https://api.kernarc.com/v1/usage?limit=20" -H "Authorization: Bearer $KERNARC_API_KEY"
```

## Top up

`POST https://api.kernarc.com/v1/topup?amount=<usd>` with your API key. `amount` is 0.10 to 500.00 USD (default 1.00).

1. The first call returns `402 Payment Required` with a `PAYMENT-REQUIRED` header (base64 JSON: scheme `exact`, network `eip155:84532`, USDC amount, recipient).
2. Your x402 client signs a USDC transfer authorization (EIP-3009) and repeats the same request with a `PAYMENT-SIGNATURE` header. You pay no gas.
3. The server settles the transfer and adds the same USD amount to your balance. The response is `200` with `balance_usd`, the transaction hash and a `PAYMENT-RESPONSE` header.

Node example with the x402 fetch wrapper:

```js
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const pay = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:84532", client: new ExactEvmScheme(privateKeyToAccount(process.env.WALLET_KEY)) }],
  spendControls: { maxAmountPerPayment: "$500" }, // clients cap payments at $1 by default
});
const res = await pay("https://api.kernarc.com/v1/topup?amount=5", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.KERNARC_API_KEY}` },
});
console.log(await res.json());
```

## Billing rules

- Each request reserves its worst-case cost first: estimated prompt tokens plus `max_tokens` at the output price. When the request ends, you pay for the real tokens and the rest goes back to your balance.
- `max_tokens` defaults to 4096; the maximum is 32768. A lower `max_tokens` needs a smaller balance.
- If the balance cannot cover the reservation, the API returns `402` with code `insufficient_balance`, your balance and the amount needed.
- Requests that fail at the model server are not charged.
- Every request is listed in `GET /v1/usage` with its tokens and cost.

## Endpoints

| Method | Path | Auth | Purpose |
|---|---|---|---|
| POST | /v1/accounts | none | Create an account and its first API key |
| GET | /v1/models | none | Models, context length, prices |
| POST | /v1/chat/completions | key | OpenAI-compatible chat, streaming or not |
| GET | /v1/account | key | Balance, totals |
| GET | /v1/usage | key | Recent requests with cost |
| POST | /v1/topup?amount=N | key | Add credit with USDC over x402 |
| GET | /v1/topups | key | Top-up history |
| GET | /v1/keys | key | List keys |
| POST | /v1/keys | key | Create another key |
| DELETE | /v1/keys/{id} | key | Revoke a key |

## Errors

Errors use the OpenAI shape: `{"error": {"message", "type", "code", "hint"}}`. Codes: `missing_api_key`, `invalid_api_key` (401); `insufficient_balance`, `payment_required` (402); `model_not_found` (404); `rate_limited` (429); `upstream_unavailable` (502).

## Limits

- Sign-up: a few accounts per IP address per minute.
- API: 120 requests per minute per key.

Contact: hello@kernarc.com. Operated by Bernoulli Corporation.
