# 사용 내역

> **GET** `/v3/account/usage/history`

호출한 API 키로 지정한 기간 안에 생성되어 **성공한** 작업과 각 작업이 소비한 크레딧을 생성 시간 역순으로 반환합니다. 자동 정산용 API로, 프롬프트·입력·결과물·다운로드 링크는 반환하지 않습니다.

- 조회 범위는 호출한 API 키입니다. 여러 키를 정산하려면 키마다 조회하세요.
- 성공한 작업만 반환합니다. 실패·만료·심사 거부된 작업(대부분 크레딧 환불됨)은 포함되지 않으므로 청구 내역과 한 줄씩 대조할 수 없습니다.
- 작업 생성 시간으로 필터링합니다. 조회 시점에 실행 중인 작업은 아직 성공 상태가 아니므로, 종료 시각이 현재보다 30분 이상 지난 기간을 조회하세요.
- 속도 제한: API 키당 분당 60회. 초과하면 `Retry-After` 헤더와 함께 `429`를 반환합니다.

## 요청 매개변수

### 요청 헤더

| 매개변수 | 유형 | 필수 | 기본값 | 설명 |
| :-: | :-: | :-: | :-: | :-: |
| Authorization | 문자열 | 예 | — | `Bearer {api_key}` |

### 쿼리 매개변수

| 매개변수 | 유형 | 필수 | 기본값 | 설명 |
| :-: | :-: | :-: | :-: | :-: |
| start_time | 문자열 | 예 | — | 기간 시작(포함). 시간대 오프셋이 있는 RFC 3339 형식, 예: `2026-10-01T00:00:00Z` |
| end_time | 문자열 | 예 | — | 기간 끝(미포함). 같은 형식이며 `start_time`보다 늦고 31일 이내여야 합니다 |
| page_size | 정수 | 아니요 | `100` | 페이지당 항목 수, 1–100 |
| cursor | 문자열 | 아니요 | — | 이전 페이지의 `next_cursor`. 첫 페이지에서는 생략합니다. 페이지를 넘기는 동안 `start_time`과 `end_time`을 바꾸지 마세요 |

## 요청 예시

### curl

```bash
curl -G https://openapi.tripo3d.ai/v3/account/usage/history \
  -H "Authorization: Bearer {api_key}" \
  --data-urlencode "start_time=2026-10-01T00:00:00Z" \
  --data-urlencode "end_time=2026-11-01T00:00:00Z" \
  --data-urlencode "page_size=100"
```

### Python (전체 페이지)

```python
import time
import requests

url = "https://openapi.tripo3d.ai/v3/account/usage/history"
headers = {"Authorization": "Bearer {api_key}"}
params = {
    "start_time": "2026-10-01T00:00:00Z",
    "end_time": "2026-11-01T00:00:00Z",
    "page_size": 100,
}
total = 0.0
while True:
    r = requests.get(url, params=params, headers=headers)
    if r.status_code in (429, 503):
        time.sleep(int(r.headers.get("Retry-After", "5")))
        continue
    r.raise_for_status()
    data = r.json()["data"]
    for item in data["items"]:
        total += item["credits_consumed"]
    if not data["has_more"]:
        break
    params["cursor"] = data["next_cursor"]
print(f"credits consumed: {total:.2f}")
```

## 응답

### 성공적인 대응

```json
{
  "code": 0,
  "status": "success",
  "data": {
    "items": [
      {
        "task_id": "123e4567-e89b-42d3-a456-426614174000",
        "type": "text_to_model",
        "model_version": "v3.0-20250812",
        "status": "success",
        "created_at": "2026-10-31T15:59:58.123456Z",
        "completed_at": "2026-10-31T16:01:12.654321Z",
        "credits_consumed": 30.00
      }
    ],
    "has_more": true,
    "next_cursor": "djE6MTc2MTkyNjM5ODEyMzQ1NjoxMjNlNDU2Ny1lODliLTQyZDMtYTQ1Ni00MjY2MTQxNzQwMDA"
  }
}
```

### 응답 필드

| 매개변수 | 유형 | 설명 |
| :-: | :-: | :-: |
| code | 정수 | 상태 코드. `0`는 성공을 나타냅니다. |
| data.items | 배열 | 이 페이지의 작업(최신순) |
| data.items[].task_id | 문자열 | 작업 ID |
| data.items[].type | 문자열 | 작업 유형(작업 조회와 같은 값) |
| data.items[].model_version | 문자열 | 생성 시 기록된 모델 버전. 작업 유형에 버전이 없으면 반환하지 않습니다 |
| data.items[].status | 문자열 | 항상 `success` |
| data.items[].created_at | 문자열 | 생성 시간(UTC, ISO 8601) |
| data.items[].completed_at | 문자열 | 완료 시간(UTC, ISO 8601). 기록이 없으면 반환하지 않습니다 |
| data.items[].credits_consumed | number | 청구된 크레딧. 작업 조회의 `credits_consumed`와 같으며 청구가 없으면 `0` |
| data.has_more | 부울 | 다음 페이지가 있는지 여부 |
| data.next_cursor | 문자열 | `cursor`로 전달하면 다음 페이지를 가져옵니다. 마지막 페이지에서는 `null` |

## 오류 코드

| HTTP 상태 코드 | 오류 코드 | 설명 | 추천 |
| :-: | :-: | :-: | :-: |
| 400 | 1004 | 잘못된 매개변수(시간 누락 또는 형식 오류, 31일 초과 기간, 잘못된 `page_size` 또는 `cursor`) | `message`에 표시된 매개변수를 수정하세요 |
| 429 | 1007 | 속도 제한 초과 | `Retry-After`초 기다린 후 다시 시도하세요 |
| 503 | 1008 | 일시적으로 사용할 수 없음 | `Retry-After`초 기다린 후 같은 요청을 다시 보내세요 |
