# Agent: Models & Providers

**Page:** api/agent/models

[Download Raw Markdown](./api/agent/models.md)

---

{/* AUTO-GENERATED — Do not edit manually. Regenerate with: npm run docs:api:generate */}



# Agent: Models & Providers

Browse the merged model catalogue, inspect LLM providers, and manage provider credentials — stored API keys, OAuth logins, and pooled OAuth accounts. All endpoints return secret-free summaries; stored credentials are never echoed back.


These routes are global / no-realm. A per-request `X-Hoody-Realm` header or `?realm` query parameter returns `400 realm_scope_unsupported`.


---

## Models

### `GET /api/v1/agent/models`

List models.

Lists the merged model catalogue: every catalogued provider model (spec, display name, context window, output limit, reasoning flag, display prices) AND every selectable fusion composite (`spec` beginning with `fusion/<slug>`). Each entry carries `source:"provider"` or `source:"fusion"` so a caller can tell them apart. A composite's `context_window` is the minimum across its catalogued members and it carries no per-token price. Only selectable composites appear (a broken one is excluded). Fusion composites are cwd/config_dir scoped; `X-Hoody-Cwd` and `X-Hoody-Config-Dir` are honored to resolve them.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `page` | query | integer | No | 1-based page number for pagination. |
| `limit` | query | integer | No | Maximum items per page (0 = no pagination). |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope: the `.hoody` project layer / record cwd / tool+workflow cwd. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override selecting which on-disk `.hoody` install a stateless read/write resolves. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector: `"global"` or a 24-hex id. |
| `realm` | query | string | No | Per-request realm selector — the query alias of the `X-Hoody-Realm` header (read only when the header is absent). |



```bash
curl -sS https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/models
```


```ts
await client.agent.models.listModelsIterator()
```


```json
{
  "items": [
    {
      "spec": "anthropic/claude-opus-4-8",
      "source": "provider",
      "display_name": "Claude Opus 4.8",
      "context_window": 200000,
      "output_limit": 32000,
      "reasoning": true,
      "input_price_usd_per_million": 15.0,
      "output_price_usd_per_million": 75.0
    },
    {
      "spec": "fusion/opus-with-sonnet-arbiter",
      "source": "fusion",
      "method": "router",
      "context_window": 200000,
      "members": [
        "anthropic/claude-opus-4-8",
        "anthropic/claude-sonnet-4-5"
      ]
    }
  ],
  "meta": {
    "total": 312,
    "page": 1,
    "limit": 50
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`, not by connecting to the container directly. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `GET /api/v1/agent/models/{spec}`

Get a model by spec.

Returns one catalogued model by its full spec (for example `anthropic/claude-opus-4-8`), OR a fusion composite by its `fusion/<slug>` spec. The spec contains a slash; pass it URL-encoded or use the SDK helper.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `spec` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/models/anthropic%2Fclaude-opus-4-8
```


```ts
await client.agent.models.getModel("anthropic/claude-opus-4-8")
```


```json
{
  "spec": "anthropic/claude-opus-4-8",
  "source": "provider",
  "display_name": "Claude Opus 4.8",
  "context_window": 200000,
  "output_limit": 32000,
  "reasoning": true,
  "input_price_usd_per_million": 15.0,
  "output_price_usd_per_million": 75.0,
  "provider": "anthropic"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the spec. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

## Providers

### `GET /api/v1/agent/providers`

List LLM providers.

Lists every catalogued LLM provider (id, display name, model prefix, wire format, model count) from the merged `providers.json` catalogue.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `page` | query | integer | No | 1-based page number for pagination. |
| `limit` | query | integer | No | Maximum items per page (0 = no pagination). |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers
```


```ts
await client.agent.models.listProvidersIterator()
```


```json
{
  "items": [
    {
      "id": "anthropic",
      "display_name": "Anthropic",
      "model_prefix": "anthropic/",
      "wire_format": "anthropic_messages",
      "model_count": 12
    },
    {
      "id": "openai",
      "display_name": "OpenAI",
      "model_prefix": "openai/",
      "wire_format": "openai_chat",
      "model_count": 28
    }
  ],
  "meta": {
    "total": 18,
    "page": 1,
    "limit": 50
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `GET /api/v1/agent/providers/{id}`

Get a provider.

Returns one provider's metadata plus its full catalogued model list.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/anthropic
```


```ts
await client.agent.models.getProvider("anthropic")
```


```json
{
  "id": "anthropic",
  "display_name": "Anthropic",
  "model_prefix": "anthropic/",
  "wire_format": "anthropic_messages",
  "model_count": 12,
  "models": [
    {
      "spec": "anthropic/claude-opus-4-8",
      "display_name": "Claude Opus 4.8",
      "context_window": 200000,
      "output_limit": 32000,
      "reasoning": true
    }
  ]
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `GET /api/v1/agent/providers/{id}/auth`

Get a provider's auth status.

Reports a provider's stored-credential state — whether an API key or OAuth login is stored, the effective default method, the passwordless (no-auth) flag, and the secret-free OAuth account pool. Any stored API key is surfaced as a 10-character prefix only; the full key is never returned.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/anthropic/auth
```


```ts
await client.agent.models.getProviderAuth("anthropic")
```


```json
{
  "id": "anthropic",
  "passwordless": false,
  "default": "api_key",
  "api_key_stored": true,
  "api_key_prefix": "sk-ant-api3",
  "oauth_stored": false,
  "oauth_account_count": 0
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

## OAuth login flow

### `POST /api/v1/agent/providers/{id}/auth/oauth`

Start a provider OAuth login.

Begins an interactive OAuth login and returns `{job_id, verification_uri, user_code?}`. Drive the flow with `GET .../oauth/{job}` (poll) and, for a manual or PKCE code, `POST .../oauth/{job}/code` (submit). The job carries only the non-secret verification URL and user code — never a token.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `add_account` | boolean | No | When `true`, the login ADDS to the provider's OAuth account pool instead of replacing the primary login. |



```bash
curl -sS -X POST https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/oauth \
  -H "Content-Type: application/json" \
  -d '{}'
```


```ts
await client.agent.models.startProviderOAuth("github", {})
```


```json
{
  "job_id": "oaj_3f4b1c9d7e2a8f60",
  "verification_uri": "https://github.com/login/device",
  "user_code": "WDJB-MJHT"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability so its own gate allows forwarded HTTP requests. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |
| `job_not_found` | Job not found | The referenced OAuth login job does not exist or has expired. | Restart the flow with `POST /providers/{id}/auth/oauth` and drive the new job id. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `GET /api/v1/agent/providers/{id}/auth/oauth/{job}`

Poll a provider OAuth login.

Polls an in-flight OAuth login job. Reports `state:"pending"` until the user authorizes, then `state:"complete"` (with the now-current secret-free auth status) or `state:"error"` (with a scrubbed error message).


A failed login is reported under the `200` body's `state:"error"`, NOT as an HTTP error. Clients MUST inspect `state` (`pending` | `complete` | `error`), never the HTTP status, to decide success.


### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `job` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/oauth/oaj_3f4b1c9d7e2a8f60
```


```ts
await client.agent.models.pollProviderOAuth("github", "oaj_3f4b1c9d7e2a8f60")
```


```json
{
  "state": "pending",
  "verification_uri": "https://github.com/login/device",
  "user_code": "WDJB-MJHT",
  "needs_code": false
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "job_not_found",
  "message": "no such OAuth job (it may have expired)"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |
| `job_not_found` | Job not found | The referenced OAuth login job does not exist or has expired. | Restart the flow with `POST /providers/{id}/auth/oauth`. |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `POST /api/v1/agent/providers/{id}/auth/oauth/{job}/code`

Submit a provider OAuth authorization code.

Supplies the authorization code (or full redirect URL) a blocked OAuth flow is waiting for. Idempotent-safe: a second submit on an already-fed job is a no-op (`submitted:false`).

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `job` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `code` | string | Yes | The authorization code (or the full redirect URL) to complete the exchange. |



```bash
curl -sS -X POST https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/oauth/oaj_3f4b1c9d7e2a8f60/code \
  -H "Content-Type: application/json" \
  -d '{"code":"https://github.com/callback?code=abc123&state=xyz"}'
```


```ts
await client.agent.models.submitProviderOAuthCode("github", "oaj_3f4b1c9d7e2a8f60", {
  code: "https://github.com/callback?code=abc123&state=xyz"
})
```


```json
{
  "submitted": true,
  "message": "code accepted; exchange in progress"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "job_not_found",
  "message": "no such OAuth job (it may have expired)"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |
| `job_not_found` | Job not found | The referenced OAuth login job does not exist or has expired. | Restart the flow with `POST /providers/{id}/auth/oauth`. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `DELETE /api/v1/agent/providers/{id}/auth/oauth`

Remove a provider's OAuth login.

Removes a provider's stored OAuth credentials. Idempotent. Returns the resulting secret-free auth status.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS -X DELETE https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/oauth
```


```ts
await client.agent.models.logoutProviderOAuth("github")
```


```json
{
  "auth": {
    "id": "github",
    "passwordless": false,
    "api_key_stored": false,
    "oauth_stored": false,
    "oauth_account_count": 0
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |
| `job_not_found` | Job not found | The referenced OAuth login job does not exist or has expired. | Restart the flow with `POST /providers/{id}/auth/oauth`. |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

## OAuth account pool

### `GET /api/v1/agent/providers/{id}/auth/accounts`

List a provider's OAuth account pool.

Lists the secret-free OAuth account pool for a provider: key, label, active flag, cooldown — never a token.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `page` | query | integer | No | 1-based page number for pagination. |
| `limit` | query | integer | No | Maximum items per page (0 = no pagination). |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/accounts
```


```ts
await client.agent.models.listProviderAccountsIterator("github")
```


```json
{
  "items": [
    {
      "key": "person-a",
      "label": "Personal GitHub",
      "active": true,
      "cooldown_until": null
    },
    {
      "key": "work-b",
      "label": "Work GitHub",
      "active": false,
      "cooldown_until": "2025-01-15T12:00:00Z"
    }
  ],
  "meta": {
    "total": 2,
    "page": 1,
    "limit": 50
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |



### `POST /api/v1/agent/providers/{id}/auth/accounts`

Add an OAuth account to a provider's pool.

Begins an OAuth login that ADDS to the provider's account pool. Returns a `{job_id}`; drive it with the same poll/submit endpoints as `startProviderOAuth`.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS -X POST https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/accounts \
  -H "Content-Type: application/json" \
  -d '{}'
```


```ts
await client.agent.models.addProviderAccount("github", {})
```


```json
{
  "job_id": "oaj_8a2c4d6e1f90b375",
  "verification_uri": "https://github.com/login/device",
  "user_code": "BKRV-PLQW"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |
| `job_not_found` | Job not found | The referenced OAuth login job does not exist or has expired. | Restart the flow with `POST /providers/{id}/auth/oauth`. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `PUT /api/v1/agent/providers/{id}/auth/accounts/{key}/active`

Make a pooled OAuth account active.

Makes one pooled OAuth account active for a provider. The `{key}` path value names the account; the trailing `/active` sub-resource names the activation verb. Returns the resulting secret-free account pool.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `key` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS -X PUT https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/accounts/work-b/active \
  -H "Content-Type: application/json" \
  -d '{}'
```


```ts
await client.agent.models.setProviderAccountActive("github", "work-b", {})
```


```json
{
  "accounts": [
    {
      "key": "person-a",
      "label": "Personal GitHub",
      "active": false,
      "cooldown_until": null
    },
    {
      "key": "work-b",
      "label": "Work GitHub",
      "active": true,
      "cooldown_until": null
    }
  ]
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id and account key. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `DELETE /api/v1/agent/providers/{id}/auth/accounts/{key}`

Remove a pooled OAuth account.

Drops one pooled OAuth account for a provider. The `{key}` path value names the account. Returns the resulting secret-free account pool.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `key` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS -X DELETE https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/github/auth/accounts/work-b
```


```ts
await client.agent.models.removeProviderAccount("github", "work-b")
```


```json
{
  "accounts": [
    {
      "key": "person-a",
      "label": "Personal GitHub",
      "active": true,
      "cooldown_until": null
    }
  ]
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id and account key. |


```json
{
  "code": "oauth_unsupported",
  "message": "provider does not support OAuth login"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

## API keys

### `PUT /api/v1/agent/providers/{id}/auth/api-key`

Store a provider API key.

Stores a provider's API key in the 0600-atomic `~/.hoody/.env` keychainless store. The reply carries only the secret-free auth status (10-character prefix); the full key is never returned.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `api_key` | string | Yes | The provider API key. Stored in the 0600 `~/.hoody/.env` store; the reply echoes only a prefix. |



```bash
curl -sS -X PUT https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/anthropic/auth/api-key \
  -H "Content-Type: application/json" \
  -d '{"api_key":"sk-ant-api03-XXXXX-REDACTED-XXXXX"}'
```


```ts
await client.agent.models.setProviderAPIKey("anthropic", {
  api_key: "sk-ant-api03-XXXXX-REDACTED-XXXXX"
})
```


```json
{
  "auth": {
    "id": "anthropic",
    "passwordless": false,
    "default": "api_key",
    "api_key_stored": true,
    "api_key_prefix": "sk-ant-api3",
    "oauth_stored": false,
    "oauth_account_count": 0
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "auth_method_unsupported",
  "message": "provider is passwordless (no API key method)"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |
| `auth_method_unsupported` | Auth method unsupported | The requested credential method is not available for this provider. | Pick a method the provider supports; a passwordless provider needs no default. |
| `credential_not_stored` | Credential not stored | The default method cannot be promoted because no credential of that kind is stored. | Store the credential first, then set the default. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



### `DELETE /api/v1/agent/providers/{id}/auth/api-key`

Delete a provider API key.

Removes a provider's stored API key and its default-method marker. Idempotent. Returns the resulting secret-free auth status.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |



```bash
curl -sS -X DELETE https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/anthropic/auth/api-key
```


```ts
await client.agent.models.deleteProviderAPIKey("anthropic")
```


```json
{
  "auth": {
    "id": "anthropic",
    "passwordless": false,
    "api_key_stored": false,
    "oauth_stored": false,
    "oauth_account_count": 0
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |


```json
{
  "code": "auth_method_unsupported",
  "message": "provider is passwordless (no API key method)"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |
| `auth_method_unsupported` | Auth method unsupported | The requested credential method is not available for this provider. | Pick a method the provider supports; a passwordless provider needs no default. |
| `credential_not_stored` | Credential not stored | The default method cannot be promoted because no credential of that kind is stored. | Store the credential first, then set the default. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

## Default credential method

### `PUT /api/v1/agent/providers/{id}/auth/default`

Set a provider's default credential method.

Sets the effective default credential method for a provider — `api_key` or `oauth`. The daemon validates the method against the provider's capabilities AND that a credential of that kind is actually stored.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Path identifier. |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. |
| `realm` | query | string | No | Per-request realm selector (query alias). |

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `default` | string | Yes | The default method: `"api_key"` or `"oauth"`. Must be a method the provider supports AND has a stored credential for. |



```bash
curl -sS -X PUT https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.icu/api/v1/agent/providers/anthropic/auth/default \
  -H "Content-Type: application/json" \
  -d '{"default":"api_key"}'
```


```ts
await client.agent.models.setProviderDefault("anthropic", {
  default: "api_key"
})
```


```json
{
  "auth": {
    "id": "anthropic",
    "passwordless": false,
    "default": "api_key",
    "api_key_stored": true,
    "api_key_prefix": "sk-ant-api3",
    "oauth_stored": false,
    "oauth_account_count": 0
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a no-realm RPC. | Omit the realm header on this route. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The request was refused by the server's admin gate. | Run the daemon with socket auth and no separate admin capability. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not reach the service through the public endpoint. | Reach the agent through `hoody-proxy`. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the provider id. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`). | Reduce the request body below the configured limit (default 8 MiB). |


```json
{
  "code": "credential_not_stored",
  "message": "no API key is stored for this provider"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `oauth_unsupported` | OAuth not supported | The provider has no OAuth login flow. | Use an API key for this provider, or pick a provider that supports OAuth. |
| `auth_method_unsupported` | Auth method unsupported | The requested credential method is not available for this provider. | Pick a method the provider supports; a passwordless provider needs no default. |
| `credential_not_stored` | Credential not stored | The default method cannot be promoted because no credential of that kind is stored. | Store the credential first, then set the default. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor `Retry-After` and retry. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```
| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |