# 查询账务分录

`listLedger`

`GET /v1/ledger`

下面的接口说明为英文原文。

listLedger

## 鉴权

在请求头带上项目 API Key，例如 `Authorization: Bearer $VIZO_API_KEY`。API Key 只放在服务端。

## 查询参数

- `cursor` (string, 可选) 上一页返回的游标。 最多 19 个字符
- `limit` (integer, 可选) 每页条数。 最小 1 最大 100 默认 50

## 响应

### 200 OK

- `items` (object[], 必填, 可为 null)
  - `created_at` (date-time, 必填)
  - `credits` (string, 必填)
  - `from` (string, 必填)
  - `id` (string, 必填)
  - `reference` (string, 必填)
  - `task_id` (string, 可选) The generation this entry belongs to, for a hold, settlement, returned unused hold, release or refund of a task. Absent for entries that belong to no generation, such as top-ups.
  - `to` (string, 必填)
- `next_cursor` (string, 可选) 作为 cursor 传入以读取下一页。最后一页为空。
- `tasks` (object[], 可选, 可为 null) One total per generation named on this page, computed over all of its transfers, including those on other pages. Use it for a task's net change and state instead of summing the loaded entries.
  - `net` (string, 必填) The net change the task made to the available balance over all its transfers, as a signed decimal: negative when Credits left it.
  - `state` (string, 必填) Where the trail ended: held (still reserved), charged (some or all of the hold was charged), released (nothing charged; the hold came back) or refunded (the charge was reversed). 可选值: `held`, `charged`, `released`, `refunded`
  - `task_id` (string, 必填)
  - `transfers` (integer, 必填) How many transfers the task has in total. Fewer on the loaded pages means its trail continues on earlier pages.

```json
{
  "items": [
    {
      "created_at": "2026-11-02T08:01:43Z",
      "credits": "157.000",
      "from": "held",
      "id": "gen_01JD8Z5QW3XR",
      "reference": "settled:gen_01JD8Z5QW3XR",
      "task_id": "gen_01JD8Z5QW3XR",
      "to": "consumed"
    }
  ],
  "next_cursor": "",
  "tasks": [
    {
      "net": "string",
      "state": "held",
      "task_id": "gen_01JD8Z5QW3XR",
      "transfers": 1
    }
  ]
}
```

### 400 Bad Request

```json
{
  "error": {
    "code": "invalid_input",
    "message": "The request body could not be read as JSON.",
    "retryable": false,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 401 Unauthorized

```json
{
  "error": {
    "code": "invalid_credentials",
    "message": "API key is missing, malformed, expired or revoked.",
    "retryable": false,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 403 Forbidden

```json
{
  "error": {
    "code": "scope_denied",
    "message": "The key does not allow this operation for this project.",
    "retryable": false,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 404 Not Found

```json
{
  "error": {
    "code": "resource_not_found",
    "message": "The resource is not available to this project.",
    "retryable": false,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 409 Conflict

```json
{
  "error": {
    "code": "conflict",
    "message": "The request conflicts with the current state of the resource.",
    "retryable": false,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 422 Unprocessable Entity

```json
{
  "error": {
    "code": "invalid_input",
    "message": "Input does not match the published schema.",
    "retryable": false,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 429 Too Many Requests

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Check Retry-After.",
    "retryable": true,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 500 Internal Server Error

```json
{
  "error": {
    "code": "request_failed",
    "message": "The request failed. Check recent generations before submitting again.",
    "retryable": false,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

### 503 Service Unavailable

```json
{
  "error": {
    "code": "temporarily_unavailable",
    "message": "Service is temporarily unavailable.",
    "retryable": true,
    "request_id": "9f2c41d07ab3e5c8"
  }
}
```

## 错误

所有错误使用同一种响应体。联系支持时请附上 request_id。

### 错误响应体

- `error` (object, 必填) 错误详情。
  - `code` (string, 必填) Stable request error code. invalid_input rejects the request schema; invalid_credentials/scope_denied reject authentication/authorization; ip_not_allowed/model_not_allowed reject API key IP/model restrictions; resource_not_found hides missing or inaccessible resources; conflict rejects incompatible state; insufficient_balance/budget_exceeded/spending_blocked reject funding; balance_negative (402) refuses new tasks while the organization owes Credits from a charge above its hold, until a top-up repays them; rate_limited/concurrency_limited ask for a later retry; temporarily_unavailable is transient service capacity; request_failed covers other HTTP failures. tier_not_sold, draft_not_found, draft_expired and input_duration_out_of_range reject model-specific input. input_media_invalid rejects a detected format/type mismatch; input_media_too_large rejects a probed byte size above the model limit. storage_quota_exceeded rejects an upload when the organization's storage is full. See errors for field-level details. 可选值: `invalid_input`, `invalid_credentials`, `insufficient_balance`, `balance_negative`, `scope_denied`, `resource_not_found`, `conflict`, `rate_limited`, `concurrency_limited`, `temporarily_unavailable`, `request_failed`, `ip_not_allowed`, `model_not_allowed`, `tier_not_sold`, `draft_not_found`, `draft_expired`, `input_duration_out_of_range`, `input_media_invalid`, `input_media_too_large`, `budget_exceeded`, `spending_blocked`, `storage_quota_exceeded`
  - `errors` (object[], 可选, 可为 null)
    - `path` (string, 必填)
    - `rule` (string, 必填)
  - `message` (string, 必填) 可读的说明，不要解析它。
  - `request_id` (string, 必填) 联系支持时请附上。
  - `retryable` (boolean, 必填) 仅 429 和 503 为 true。即便如此，重发创建请求前也要先查看近期任务。
  - `task_id` (string, 可选) 错误所属的任务（如果有）。

| 状态码 | 含义与处理 |
| --- | --- |
| 400 | 请求无法解析。对照上面的表格检查查询参数的取值。 |
| 401 | API Key 缺失、格式错误、已过期或已撤销。在服务端更正 API Key 后继续。 |
| 403 | API Key 权限、邮箱验证、预算上限或账户限制阻止了操作。检查 API Key 类型、权限和项目预算。 |
| 404 | 模型或资源不存在，或不在当前项目范围内。确认项目、ID 和模型是否已开通。 |
| 409 | 请求与当前状态冲突。重新读取资源，再决定是否重新发送。 |
| 422 | 字段或取值无效。对照字段表和模型页修改请求。 |
| 429 | 请求过于频繁，没有创建任务。等到 Retry-After 指定的时间后再发送。 |
| 500 | 服务端出错，任务可能已经受理。不要直接重发，先查看近期任务。 |
| 503 | 服务暂时不可用。创建请求要先查看近期任务，确认没有受理，再重新提交。 |

### cURL

```bash
curl "https://api.vizoapi.com/v1/ledger?limit=20" \
  -H "Authorization: Bearer $VIZO_API_KEY"
```

### Python

```python
import os, requests

res = requests.get(
    "https://api.vizoapi.com/v1/ledger?limit=20",
    headers={"Authorization": f"Bearer {os.environ['VIZO_API_KEY']}"},
    timeout=60,
)
print(res.status_code, res.json())
```

### Node.js

```javascript
const res = await fetch("https://api.vizoapi.com/v1/ledger?limit=20", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.VIZO_API_KEY}`,
  },
});
console.log(res.status, await res.json());
```
