Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hpp-router/_MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ Content is grounded in the [`hpp-router`](https://github.com/hpp-io/hpp-router)

## Follow-ups

- **Portal sign-up & API keys:** docs currently mention [HPP Hub](https://hub.hpp.io) for key issuance. The Router Portal (`router.hpp.io`) will also support sign-up and key management — document once Portal sources are available.
- **Portal sign-up & API keys:** docs mention both the [HPP Router portal](https://router.hpp.io) and [HPP Hub](https://hub.hpp.io) for key issuance.
- **`audit` page:** not included yet; add when canonical audit/on-chain content is ready (see [hpp-router issue #93](https://github.com/hpp-io/hpp-router/issues/93)).
91 changes: 78 additions & 13 deletions hpp-router/api-reference/consumer-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ description: HPP Router Consumer API — OpenAI-compatible endpoints, schemas, a

# API Reference

HPP Router's request and response schemas are **OpenAI-compatible**, with HPP-specific extensions for smart routing headers and prepaid quota. At a high level, you use the same patterns as the OpenAI Chat API — point your client at `https://router.hpp.io` and authenticate with your API key.
HPP Router's request and response schemas are **OpenAI-compatible**, with HPP-specific extensions for smart routing headers and wallet payments (on-chain USDC.e). At a high level, you use the same patterns as the OpenAI Chat API — point your client at `https://router.hpp.io` and authenticate with your API key.

## OpenAPI Specification

The complete Consumer API is documented using **OpenAPI 3.1**. The spec is the single source of truth for request/response shapes and auth schemes:

| Format | Location |
| --- | --- |
| **YAML (bundled)** | [`consumer-v1.yaml`](./consumer-v1.yaml) in this repo |
| **YAML (source)** | [`hpp-router/openapi/consumer-v1.yaml`](https://github.com/hpp-io/hpp-router/blob/main/openapi/consumer-v1.yaml) |
| **OpenAPI YAML** | [`consumer-v1.yaml`](./consumer-v1.yaml) |

Import the spec into [Swagger UI](https://swagger.io/tools/swagger-ui/), [Postman](https://www.postman.com/), or an OpenAPI code generator to explore endpoints or produce client stubs.

Expand All @@ -23,7 +22,8 @@ For live requests, use the [Router Playground](https://router.hpp.io/playground/
## Base URL & auth

- **Base URL:** `https://router.hpp.io`
- **Auth:** `apikey` header **or** `Authorization: Bearer <key>`. See [Authentication](../authentication).
- **Auth:** `apikey` header **or** `Authorization: Bearer <key>` for billed endpoints. `GET /llm/v1/models` does not require a key.
Comment thread
croa-blocko marked this conversation as resolved.
- For x402 wallet payments, keep the API key and also set `X-Payment-Rail: wallet`. Sign and retry with `PAYMENT-SIGNATURE` / `X-PAYMENT` after a `402`. See [Authentication](../authentication).
- **Version:** Consumer API `0.1.0`.

## Endpoints
Expand All @@ -34,7 +34,8 @@ For live requests, use the [Router Playground](https://router.hpp.io/playground/
| `GET` | `/llm/v1/models` | [List available models](#get-llmv1models) |
| `POST` | `/v1/images/generations` | [Generate images](#post-v1imagesgenerations) |
| `GET` | `/api/usage` | [Get current consumer usage](#get-apiusage) |
| `GET` | `/api/quota-check` | [Check current consumer quota](#get-apiquota-check) |
| `GET` | `/api/quota-check` | [Check prepaid quota](#get-apiquotacheck) |
| `GET` | `/api/user/audit/:logId` | [Get user audit log](#get-apiuserauditlogid) |
Comment thread
croa-blocko marked this conversation as resolved.

---

Expand All @@ -56,20 +57,30 @@ OpenAI-compatible chat completion endpoint with HPP smart-routing headers.

Additional properties are allowed and passed through.

**Authentication:** Required. Use `apikey` header or `Authorization: Bearer <key>` for billing/usage tracking.

For x402 wallet payments, append the `X-Payment-Rail: wallet` header and sign payments using the x402 protocol.

**Responses:**

- `200` — `ChatCompletionResponse` (`application/json`) or an SSE stream (`text/event-stream`). Response headers include `X-HPP-Router-Resolved-Model`, `X-HPP-Router-Basket`, `X-HPP-Router-Rule-Id`, `X-HPP-Router-Rules-Version`, and `X-HPP-Router-Tier`.
- `400`, `401`, `429`, `500` — error envelope.
- `401` — Authentication required.
- `402` — Payment required (for wallet rail). Response includes `PAYMENT-REQUIRED` header with payment specifications.
- `429`, `500` — error envelope.

See [Chat Completions](../guides/chat-completions) and [Smart Routing](../smart-routing).

---

## `GET /llm/v1/models`

Lists available models (OpenAI-compatible). Each `Model` has `id`, `object` (`"model"`), `owned_by`, and an optional `pricing` object (`input`, `output`, `cache_write`, `cache_read`).
Lists available models (OpenAI-compatible). **Authentication is optional** — Kong serves this route without `key-auth`.

Each `Model` includes `id`, `object` (`"model"`), `owned_by`, optional catalog fields (`name`, `description`, `context`, `max_output`, `tool`, `structured`, `knowledge_cutoff`, `input_modalities`, `output_modalities`), and an optional `pricing` object.

**Responses:** `200` — `ModelListResponse`; `401`, `500` — error envelope.
`pricing.input` / `pricing.output` / `pricing.cache_write` / `pricing.cache_read` are **USD per token** (may be `null`). For `hpprouter/auto`, `pricing` is `null` — billing uses the resolved model.

**Responses:** `200` — `ModelListResponse`; `500` — error envelope.

See [Models & Pricing](../models-and-pricing).

Expand Down Expand Up @@ -99,23 +110,77 @@ See [Image Generation](../guides/image-generation).

## `GET /api/usage`

Usage and quota summary for the authenticated consumer.
Usage summary for the authenticated consumer.

**Query params:**
- `rail` — optional filter: `wallet` or `quota`. When `rail=wallet`, response includes settlement fields and scopes request/token/cost stats to the wallet rail.

**Response `200`** (`UsageResponse`): `consumer_id`, `username`, `custom_id`, `quota`, `used`, `remaining`, `requests`, `total_tokens`, `total_cost`.
**Response `200`** (`UsageResponse`): always `consumer_id`, `username`, `custom_id`, `quota`, `used`, `remaining`, `requests`, `total_tokens`, `total_cost`. With `?rail=wallet`, also `rail`, `spent_usdc_micro`, `settle_success_count`, `settle_failed_count`.

**Errors:** `401`, `404`, `500`.

See [Usage & Settlement](../guides/usage-and-settlement).

---

## `GET /api/quota-check`

Quota availability for the authenticated consumer.
Prepaid quota availability for the authenticated consumer (credit/quota rail). This is separate from on-chain wallet settlement.

**Response `200`** (`QuotaCheckResponse`): `has_quota`, `quota`, `used`, `remaining`.

**Errors:** `401`, `503`, `500`.
**Errors:** `401`, `503` (fail-closed when quota state cannot be verified), `500`.

See [Usage & Settlement](../guides/usage-and-settlement#check-quota).

---

## `GET /api/user/audit/:logId`

Get a single audit log entry for the authenticated consumer.

Access control:
- Personal consumers can only access their own logs
- Organization members can access any log from their organization's consumers

**Path params:**
- `logId` — The audit log ID (UUID)

**Query params:**
- `consumerId` — Filter by consumer (organization members only, must have access permission via `organization_members` table)

**Response `200`:**

```json
{
"id": "log-xyz",
"consumer_id": "cons-123",
"provider": "openai",
"model": "gpt-4",
"prompt_tokens": 100,
"completion_tokens": 50,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"total_tokens": 150,
"cost": 0.002,
"status": "success",
"blockchain_tx_hash": "0x...",
"payment_rail": "wallet",
"settle_status": "settled",
"settle_amount_micro": 25000,
"scope": "organization",
"organization": {
"id": "org-abc",
"name": "My Organization",
"consumerId": "cons-org-123",
"role": "admin"
}
}
```

**Errors:** `401` (not authenticated), `403` (no access to consumer), `404` (log not found), `500`.

See [Quota & Usage](../guides/quota-and-usage).
See [Usage & Settlement](../guides/usage-and-settlement) for more details.

---

Expand Down
80 changes: 78 additions & 2 deletions hpp-router/api-reference/consumer-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,17 @@ paths:
get:
operationId: listModels
summary: List available models
description: >
OpenAI-compatible model catalog with pricing and capability metadata.
Authentication is optional for this endpoint.
security: []
Comment thread
croa-blocko marked this conversation as resolved.
responses:
"200":
description: OpenAI-compatible model list.
content:
application/json:
schema:
$ref: "#/components/schemas/ModelListResponse"
"401":
$ref: "#/components/responses/ErrorResponse"
"500":
$ref: "#/components/responses/ErrorResponse"
/v1/images/generations:
Expand Down Expand Up @@ -105,6 +107,18 @@ paths:
get:
operationId: getUsage
summary: Get current consumer usage
description: >
Usage and prepaid quota summary for the authenticated consumer.
Pass `rail=wallet` to scope stats to the wallet payment rail and include
on-chain USDC.e settlement fields.
parameters:
- name: rail
in: query
required: false
schema:
type: string
enum: [wallet, quota]
description: Optional payment-rail filter. `wallet` adds settlement fields.
responses:
"200":
description: Usage and quota summary for the authenticated consumer.
Expand Down Expand Up @@ -280,25 +294,66 @@ components:
const: model
owned_by:
type: string
name:
oneOf:
- type: string
- type: "null"
description:
oneOf:
- type: string
- type: "null"
pricing:
oneOf:
- $ref: "#/components/schemas/ModelPricing"
- type: "null"
context:
oneOf:
- type: number
- type: "null"
max_output:
oneOf:
- type: number
- type: "null"
tool:
oneOf:
- type: boolean
- type: "null"
structured:
oneOf:
- type: boolean
- type: "null"
knowledge_cutoff:
oneOf:
- type: string
- type: "null"
input_modalities:
type: array
items:
type: string
output_modalities:
type: array
items:
type: string
ModelPricing:
type: object
description: USD rates per token (multiply by 1_000_000 for $/1M).
properties:
input:
type: number
description: USD per input token.
output:
type: number
description: USD per output token.
cache_write:
oneOf:
- type: number
- type: "null"
description: USD per cache-write token, when applicable.
cache_read:
oneOf:
- type: number
- type: "null"
description: USD per cache-read token, when applicable.
ImageGenerationRequest:
type: object
required:
Expand Down Expand Up @@ -375,16 +430,37 @@ components:
- type: "null"
quota:
type: number
description: Prepaid quota limit (credit/quota rail snapshot).
used:
type: number
description: Prepaid quota consumed.
remaining:
type: number
description: Prepaid quota remaining.
rail:
type: string
enum: [wallet, quota]
description: Present when the request filtered by `?rail=`.
spent_usdc_micro:
type: number
description: >
Total USDC.e settled on-chain in atomic/micro units.
Present when `rail=wallet`.
settle_success_count:
type: integer
description: Successful on-chain settlements. Present when `rail=wallet`.
settle_failed_count:
type: integer
description: Failed on-chain settlements. Present when `rail=wallet`.
requests:
type: integer
total_tokens:
type: integer
total_cost:
type: number
description: >
Dollar cost. For `rail=wallet`, reflects wallet-settled spend from
usage logs rather than prepaid `used`.
QuotaCheckResponse:
type: object
required:
Expand Down
51 changes: 34 additions & 17 deletions hpp-router/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import CodePanel from '@site/src/components/CodePanel';

# Authentication

Every request to HPP Router must be authenticated. The gateway uses the API key to identify the **consumer**, enforce per-consumer rate limits, and check the prepaid [quota](./guides/quota-and-usage) before forwarding the request to a provider.
HPP Router uses **on-chain USDC.e payments** via x402 wallet. All requests require authentication with an API key for consumer identification.

## Getting an API key

API keys are issued through **[HPP Hub](https://hub.hpp.io)**, the HPP developer portal. Treat the key like a password: keep it server-side and never commit it to source control.
API keys can be issued from the **[HPP Router portal](https://router.hpp.io)** and also through **[HPP Hub](https://hub.hpp.io)**. Treat the key like a password: keep it server-side and never commit it to source control.

## Supported schemes

Expand All @@ -23,11 +23,13 @@ HPP Router accepts two authentication schemes. Use whichever fits your client.

<CodePanel>
<Tabs groupId="auth-apikey" queryString>
<TabItem value="curl" label="cURL" default>
<TabItem value="curl" label="curl" default>

```bash showLineNumbers
curl https://router.hpp.io/llm/v1/models \
-H "apikey: $HPPROUTER_API_KEY"
curl https://router.hpp.io/llm/v1/chat/completions \
-H "apikey: $HPPROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"openai/gpt-5","messages":[{"role":"user","content":"Hello"}]}'
```

</TabItem>
Expand All @@ -38,11 +40,13 @@ curl https://router.hpp.io/llm/v1/models \

<CodePanel>
<Tabs groupId="auth-bearer" queryString>
<TabItem value="curl" label="cURL" default>
<TabItem value="curl" label="curl" default>

```bash showLineNumbers
curl https://router.hpp.io/llm/v1/models \
-H "Authorization: Bearer $HPPROUTER_API_KEY"
curl https://router.hpp.io/llm/v1/chat/completions \
-H "Authorization: Bearer $HPPROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"openai/gpt-5","messages":[{"role":"user","content":"Hello"}]}'
```

</TabItem>
Expand All @@ -53,15 +57,28 @@ The Bearer scheme is what most OpenAI-compatible SDKs send by default, which is

## Which endpoints require auth

All consumer endpoints are authenticated:
| Endpoint | Auth | Purpose |
| --- | --- | --- |
| `GET /llm/v1/models` | Optional | [List models](./models-and-pricing) |
Comment thread
croa-blocko marked this conversation as resolved.
| `POST /llm/v1/chat/completions` | Required (wallet: also `X-Payment-Rail: wallet`) | [Chat completions](./guides/chat-completions) |
| `POST /v1/images/generations` | Required (wallet: also `X-Payment-Rail: wallet`) | [Image generation](./guides/image-generation) |
| `GET /api/usage` | Required | [Usage summary](./guides/usage-and-settlement) |
| `GET /api/quota-check` | Required | [Check prepaid quota](./guides/usage-and-settlement#check-quota) |
| `GET /api/user/audit/:logId` | Required | [Get user audit log](./api-reference/consumer-api#get-apiuserauditlogid) |

| Endpoint | Purpose |
| --- | --- |
| `POST /llm/v1/chat/completions` | [Chat completions](./guides/chat-completions) |
| `GET /llm/v1/models` | [List models](./models-and-pricing) |
| `POST /v1/images/generations` | [Image generation](./guides/image-generation) |
| `GET /api/usage` | [Usage summary](./guides/quota-and-usage) |
| `GET /api/quota-check` | [Quota check](./guides/quota-and-usage) |
Billed endpoints require an API key so Kong can identify the consumer. Wallet payments still need the key; they additionally use the payment-rail header and x402 payment signature.

For wallet payments, also include the `X-Payment-Rail: wallet` header. See [Chat Completions](./guides/chat-completions) for examples.

## x402 Wallet

HPP Router supports **x402 Wallet** for on-chain USDC.e payments.

When you send a request with `X-Payment-Rail: wallet`, the gateway prompts your client to sign payment authorization using the x402 protocol. If no payment signature is present, the server responds with **`402`** and a `PAYMENT-REQUIRED` header (base64-encoded JSON) whose body includes an x402 `accepts` entry — typically `asset` (USDC.e contract), `amount` (atomic/micro units), `payTo`, network, and scheme metadata.

For detailed information about the x402 payment flow, see:
- [x402 on HPP](/x402)
- [Wallet Payments Guide](./guides/chat-completions#wallet)

## Errors

Expand All @@ -74,5 +91,5 @@ A missing or invalid key returns **`401`**. See [Errors](./guides/errors) for th
## Security tips

- Store the key in an environment variable or secret manager, never in client-side code.
- Rotate keys through HPP Hub if a key may have been exposed.
- Rotate keys through the HPP Router portal or HPP Hub if a key may have been exposed.
- Prefer calling HPP Router from your backend so the key is never shipped to browsers or mobile apps.
Loading