Files
codex-proxy-rs/docs/api.md
T
2026-06-11 20:52:47 +08:00

88 lines
1.9 KiB
Markdown

# API Contract
`codex-proxy-rs` exposes two API families.
## `/v1/*`
These endpoints are OpenAI-compatible and are authenticated only by client API keys using `Authorization: Bearer cpr_...`.
Responses include an `X-Request-Id` header for tracing, but the body stays OpenAI-compatible and does not include a custom `requestId` field.
Error body:
```json
{
"error": {
"message": "Invalid client API key",
"type": "invalid_request_error",
"param": null,
"code": "invalid_api_key"
}
}
```
Streaming errors after SSE has started use:
```text
event: error
data: {"error":{"message":"Upstream failed","type":"server_error","param":null,"code":"upstream_error"}}
```
## `/admin/*`
Admin endpoints are authenticated only by HttpOnly admin session cookies.
Admin JSON uses lower camelCase field names. Every admin response includes an `X-Request-Id` header, and every JSON body includes `requestId`.
Use real HTTP status codes and body-level frontend codes together. Do not return HTTP `200` for failed requests. The body `code` exists for frontend branching; the HTTP status remains the transport truth.
Success body:
```json
{
"code": 200,
"message": "OK",
"data": {},
"requestId": "req_01"
}
```
List body:
```json
{
"code": 200,
"message": "OK",
"data": [],
"page": {
"limit": 50,
"nextCursor": null
},
"requestId": "req_01"
}
```
Error body:
```json
{
"code": 40101,
"message": "Admin login required",
"data": null,
"requestId": "req_01"
}
```
Pagination uses cursor ordering by `(created_at desc, id desc)`, default `limit=50`, max `limit=200`.
Rust structs use `PascalCase` type names and `snake_case` fields internally, then expose lower camelCase through serde:
```rust
#[derive(serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiEnvelope<T> {
pub code: u32,
pub message: String,
pub data: T,
pub request_id: String,
}
```