새로운 문서를 작성 중입니다.새 문서로 이동
ClawOps Docs
API Reference

사용량 집계 조회

GET
/v1/accounts/{accountId}/usage

계정의 사용량을 집계된 형태로 돌려줍니다. 통화 목록을 받아 직접 합산하는 것과 다릅니다 —

  • 사후 정정이 반영됩니다. 통화 시간은 종료 후에도 정정될 수 있고(durationOverride, 늦은 finalize, 운영 보정), 이 API 는 호출 시점에 원장을 다시 집계하므로 그 정정이 항상 반영됩니다. 목록을 긁어 직접 쌓으면 이미 받아간 건의 정정이 반영되지 않아 청구서와 계속 어긋납니다.
  • 청구 주기 경계가 맞습니다. 주기 시작은 일 경계가 아니라 가입 순간의 시각입니다. 달력 월로 합산하면 어긋납니다.
  • 통화 목록에 없는 미터도 포함됩니다. 문자·전사·요약은 call_logs 에 없습니다.

정산에 쓰는 축

groupBy=linkId 가 관리번호 파트너의 정산 단위입니다. 이 값은 assignment.completed webhook 의 LinkId 와 같아서 파트너가 자기 사용자와 바로 조인할 수 있습니다. 관리번호로 발급되지 않은 번호는 linkIdnull 로 묶입니다.

⚠️ 번호(groupBy=number)를 정산 단위로 쓰지 마십시오. 번호는 반납 후 재배정됩니다. 같은 번호에 이전 이용자의 사용량이 섞이지 않도록 이 API 는 배정 구간으로 잘라 집계하지만, 수신측에서 번호를 키로 누적하면 그 구분이 사라집니다.

단위 — 초로 돌려줍니다

통화·전사·요약은 입니다. 청구는 계정 합계에 올림을 한 번만 겁니다 (ceil((발신+전환)/60)). 축을 쪼갠 값을 각각 올림해 더하면 합계가 청구서보다 커지므로, 올림한 분은 totals[].billableMinutes 에만 담습니다.

금액

records 에는 수량만 담깁니다. 단가가 누진 구간(발신 60 → 45 → 25원)이라 축별로 금액을 나눌 수 없습니다 — 합계에만 정의됩니다.

⚠️ 현재 amounttotals[].unitPriceHint 는 항상 null 입니다. 금액 계산은 플랜 포함량·누진 구간·애드온을 함께 봐야 해서 청구 경로를 재사용하는 후속 작업으로 남았습니다. 지금은 수량에 자사 단가를 적용해 사용하십시오.

Authorization

BearerAuth
AuthorizationBearer <token>

API Key를 Bearer 토큰으로 전달

In: header

Path Parameters

accountId*string

계정 ID

Query Parameters

from?string

집계 시작(UTC, 포함). to함께 주어야 합니다 — 한쪽만 주면 400. 생략하면 현재 청구 주기 전체를 집계합니다.

Formatdate-time
to?string

집계 끝(UTC, 미포함). 구간 최대 92일.

Formatdate-time
groupBy?array<>

쪼갤 축. 반복 지정으로 조합합니다(?groupBy=day&groupBy=linkId). ⚠️ 콤마 구분(?groupBy=day,linkId)은 받지 않습니다 — 값 검증을 유지하기 위한 선택이라, 오타는 조용히 무시되지 않고 400 이 됩니다. 생략하면 미터별 합계만 돌려줍니다.

meter?array<>

특정 미터만 조회. 반복 지정(?meter=a&meter=b). 생략 시 전체.

includeToday?boolean

진행 중인 오늘(UTC) 구간을 포함할지. 오늘 구간은 다시 조회할 때마다 값이 달라지고 스캔 구간도 그만큼 늘어납니다. 정산은 확정 구간만 쓰는 것이 정상이므로 기본은 false 입니다.

Defaultfalse
pageSize?integer

페이지당 항목 수(기본 200, 최대 1000).

Range1 <= value <= 1000
page_size?integerDeprecated

pageSize 의 별칭(하위호환). 신규 연동은 pageSize 를 사용하세요.

Range1 <= value <= 1000
limit?integerDeprecated

pageSize 의 별칭(하위호환). 신규 연동은 pageSize 를 사용하세요.

Range1 <= value <= 1000
page?integer

1-based 페이지 번호.

Default1
Range1 <= value

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/accounts/AC1a2b3c4d/usage?from=2026-08-01T00%3A00%3A00Z&to=2026-09-01T00%3A00%3A00Z&groupBy=day&groupBy=linkId&meter=outbound_seconds&meter=sms&includeToday=false&pageSize=200&page_size=200&limit=200&page=1"
{
  "meta": {
    "page": 1,
    "pageSize": 200,
    "total": 39
  },
  "period": {
    "from": "2026-08-03T03:56:49.081Z",
    "to": "2026-09-03T03:56:49.081Z",
    "timezone": "UTC",
    "confirmedThrough": "2026-08-20",
    "includesToday": true
  },
  "records": [
    {
      "meter": "outbound_seconds",
      "unit": "second",
      "quantity": 24680,
      "day": "2019-08-24",
      "linkId": "AL7f2c9a1b",
      "phoneNumber": "07052753941"
    }
  ],
  "totals": [
    {
      "meter": "outbound_seconds",
      "unit": "second",
      "quantity": 0,
      "billableMinutes": 442,
      "unitPriceHint": 60
    }
  ],
  "amount": {
    "currency": "KRW",
    "vatIncluded": true,
    "meteredTotal": 24700,
    "breakdown": [
      {
        "meter": "outbound_seconds",
        "quantity": 0,
        "amount": 0
      }
    ]
  }
}
{
  "error": "string",
  "code": "recipient_blocked"
}
{
  "error": "string",
  "code": "recipient_blocked"
}
{
  "error": "string",
  "code": "recipient_blocked"
}
{
  "error": "string",
  "code": "recipient_blocked"
}