사용량 집계
통화·문자·전사 사용량을 집계된 형태로 조회하는 API. 최종이용자별 정산과 청구 대조에 사용합니다.
사용량 집계
계정의 사용량을 집계된 형태로 돌려줍니다. 통화 목록(GET /v1/accounts/{accountId}/calls)을 받아 직접 합산하는 것과는 결과가 다릅니다.
통화 목록을 직접 합산하면 안 되는 이유
통화 목록을 주기적으로 받아 자체 DB에 누적하는 방식은 시간이 지날수록 청구서와 어긋납니다. 아래 세 가지가 반영되지 않기 때문입니다.
- 사후 정정 — 통화 시간은 종료 후에도 정정될 수 있습니다(지연 종료 처리, 운영 보정). 이미 받아간 건이 정정되면 자체 DB에는 반영할 방법이 없습니다. 이 API는 조회 시점에 다시 집계하므로 정정이 항상 반영됩니다.
- 청구 주기 경계 — 청구 주기의 시작은 매월 1일이 아니라 구독을 시작한 순간의 시각입니다. 달력 월로 합산하면 주기 앞뒤가 섞입니다.
- 통화 목록에 없는 미터 — 문자·전사·요약은 통화 기록에 들어 있지 않습니다.
미터
모든 통화 미터는 초 단위로 반환됩니다.
| 미터 | 단위 | 설명 |
|---|---|---|
outbound_seconds | second | 발신 통화 |
inbound_seconds | second | 수신 통화 |
transfer_seconds | second | 통화 전환으로 발생한 외부 구간. 청구는 발신에 합산되므로 billableMinutes 는 항상 null 입니다. |
sms / lms / mms | count | 발송 건수(실패 제외) |
transcription_seconds | second | 받아쓰기 |
summary_seconds | second | 요약 |
amd_invocations | count | 사람/기계 판별 수행 횟수 |
왜 분이 아니라 초인가 — 청구는 계정 합계에 올림을 한 번만 적용합니다(ceil((발신+전환)/60)). 축별로 나눈 값을 각각 올림해 더하면 합계가 청구서보다 커집니다. 그래서 쪼갠 값은 초로 주고, 청구와 같은 규칙으로 올림한 분은 totals[].billableMinutes 에만 담습니다.
meter=outbound_seconds 만 요청하셔도 전환 초는 billableMinutes 계산에 포함됩니다(요청하지 않으셨다면 records·totals 에는 나오지 않습니다). 필터를 어떻게 거시든 발신의 청구 분은 청구서와 같은 값입니다.
집계 축
groupBy 로 축을 지정합니다. 여러 축은 파라미터를 반복해 조합합니다(?groupBy=day&groupBy=linkId). 콤마 구분(?groupBy=day,linkId)은 지원하지 않습니다 — 오타를 조용히 넘기지 않기 위해 값 검증을 유지한 결과입니다.
| 축 | 의미 |
|---|---|
meter | 미터별 합계(기본값) |
day | 일자별(UTC) |
linkId | 관리번호 발급 링크별 — 최종이용자 단위 |
number | 전화번호별 |
정산에는 linkId 를 쓰십시오
linkId 는 assignment.completed Webhook 의 LinkId 와 같은 값입니다. 발급 링크를 만든 쪽이 이미 쥐고 있는 값이므로, 자체 시스템의 고객 레코드와 바로 연결할 수 있습니다. 관리번호로 발급되지 않은 번호(직접 발급분)는 linkId 가 null 로 묶입니다.
linkId 는 발급 링크 주소에 포함되는 값과 동일합니다. 정산서·CSV 등 외부로 나가는 문서에 그대로 싣지 마십시오. 자체 시스템에서 고객 레코드와 연결하는 용도로만 사용하시고, 외부 공유 시에는 자사 고객 ID 로 치환하시기 바랍니다.
전화번호를 정산 키로 사용하지 마십시오. 번호는 반납 후 다른 이용자에게 재배정됩니다. 이 API 는 배정 구간을 기준으로 잘라 집계하므로 응답에는 이전 이용자의 사용량이 섞이지 않지만, 수신한 값을 번호를 키로 누적하면 그 구분이 사라집니다.
기간
from/to 를 생략하면 현재 청구 주기 전체를 집계합니다. 지정할 때는 둘 다 주어야 하며, to 는 포함되지 않습니다. 최대 구간은 92일입니다.
모든 경계와 day 값은 UTC 기준입니다. 응답의 period 를 그대로 정산 근거로 사용하시면 청구서와 일치합니다.
| 필드 | 의미 |
|---|---|
confirmedThrough | 이 날짜까지는 정정이 반영된 확정값입니다. |
includesToday | 진행 중인 오늘 구간 포함 여부. includeToday=true 일 때만 참입니다. |
엔드포인트
| Method | Path | 설명 |
|---|---|---|
GET | /v1/accounts/{accountId}/usage | 사용량 집계 조회 |
쿼리 파라미터
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
from / to | date-time | 현재 청구 주기 | 둘 다 지정. to 미포함. 최대 92일 |
groupBy | string[] | meter | meter day linkId number. 반복 지정 |
meter | string[] | 전체 | 특정 미터만 조회. 반복 지정 |
includeToday | boolean | false | 오늘(UTC) 구간 포함 여부 |
pageSize / page | integer | 200 / 1 | page_size·limit 별칭 지원 |
기본 조회
curl "https://api.claw-ops.com/v1/accounts/AC.../usage" \
-H "Authorization: Bearer sk_..."응답 (200):
{
"period": {
"from": "2026-08-03T03:56:49.081Z",
"to": "2026-09-03T03:56:49.081Z",
"timezone": "UTC",
"confirmedThrough": "2026-08-20",
"includesToday": false
},
"records": [
{ "meter": "outbound_seconds", "unit": "second", "quantity": 24680 },
{ "meter": "transfer_seconds", "unit": "second", "quantity": 1820 },
{ "meter": "inbound_seconds", "unit": "second", "quantity": 512400 },
{ "meter": "sms", "unit": "count", "quantity": 88 }
],
"meta": { "page": 1, "pageSize": 200, "total": 4 },
"totals": [
{ "meter": "outbound_seconds", "unit": "second", "quantity": 24680,
"billableMinutes": 442, "unitPriceHint": null },
{ "meter": "inbound_seconds", "unit": "second", "quantity": 512400,
"billableMinutes": 8540, "unitPriceHint": null },
{ "meter": "sms", "unit": "count", "quantity": 88,
"billableMinutes": null, "unitPriceHint": null }
],
"amount": null
}최종이용자별 조회
curl "https://api.claw-ops.com/v1/accounts/AC.../usage?groupBy=linkId&meter=outbound_seconds&meter=sms" \
-H "Authorization: Bearer sk_..."{
"period": { "from": "2026-08-03T03:56:49.081Z", "to": "2026-09-03T03:56:49.081Z",
"timezone": "UTC", "confirmedThrough": "2026-08-20", "includesToday": false },
"records": [
{ "meter": "outbound_seconds", "unit": "second", "linkId": "AL7f2c9a1b", "quantity": 12400 },
{ "meter": "sms", "unit": "count", "linkId": "AL7f2c9a1b", "quantity": 40 },
{ "meter": "outbound_seconds", "unit": "second", "linkId": "AL0b31de77", "quantity": 9200 },
{ "meter": "outbound_seconds", "unit": "second", "linkId": null, "quantity": 3080 }
],
"totals": [
{ "meter": "outbound_seconds", "unit": "second", "quantity": 24680, "billableMinutes": 442 },
{ "meter": "sms", "unit": "count", "quantity": 88 }
],
"amount": null
}일자 × 번호 조회
curl "https://api.claw-ops.com/v1/accounts/AC.../usage?groupBy=day&groupBy=number&from=2026-08-01T00:00:00Z&to=2026-08-08T00:00:00Z" \
-H "Authorization: Bearer sk_..."{
"records": [
{ "meter": "inbound_seconds", "unit": "second",
"day": "2026-08-01", "phoneNumber": "07052753941", "quantity": 8210 }
]
}금액
records 에는 수량만 담깁니다. 통화 단가는 사용량 구간에 따라 달라지는 누진 구조라, 축별로 금액을 나눌 수 없습니다 — 금액은 합계에만 정의됩니다.
amount 와 totals[].unitPriceHint 는 현재 항상 null 입니다. 금액 계산은 플랜 포함량·누진 구간·애드온을 함께 봐야 하므로 후속 작업으로 남아 있습니다. 지금은 수량을 기준으로 연동하십시오 — 이후 값이 채워져도 필드 형식은 그대로입니다.
totals[].unitPriceHint— (예정) 조회 시점에 그 미터가 놓인 구간의 단가(원, 부가세 포함)입니다. 사용량이 늘어 다음 구간으로 넘어가면 달라지며, 플랜 포함량 안에 있으면null입니다. 이 값을 수량에 곱한 것은 청구액이 아닙니다.amount— (예정) 계정 전체의 종량 예상액입니다. 축을 지정한 조회(groupBy에linkId·number·day포함)에서는 채워진 뒤에도null입니다. 확정 청구액이 아니며, 플랜 기본료·애드온·일할 계산은 포함되지 않습니다.
최종이용자에게 재청구하실 때는 이 API 의 수량에 자사 단가를 적용하시는 것이 정확합니다.
월 정산 예시
- 청구 주기가 끝난 뒤
GET /usage?groupBy=linkId를 호출합니다(기간 생략 시 현재 주기이므로, 지난 주기는from/to로 지정). - 응답의
period를 정산서에 그대로 기재합니다 — 고객 문의 시 대조 근거가 됩니다. records의 초 단위 수량에 자사 정책으로 올림·단가를 적용합니다.totals[].billableMinutes합계가 ClawOps 청구서의 사용량과 일치하는지 확인합니다.
페이징
records 는 page/pageSize 로 나뉘며, meta.total 이 페이징 전 전체 행 수입니다. 마지막 페이지인지는 page * pageSize >= meta.total 로 판단하시면 됩니다 — 빈 페이지가 나올 때까지 요청하실 필요가 없습니다.
totals 와 meta.total 은 다른 값입니다. totals 는 미터별 사용량 합계, meta.total 은 행 개수입니다. totals 는 페이지와 무관하게 항상 전체 구간 기준이라 첫 페이지만 받아도 정산 대조에 쓸 수 있습니다.
MCP 도구
연결한 AI 에이전트에서도 같은 집계를 부를 수 있습니다 — 도구 이름은 get_usage, 필요한 권한은 read:usage 입니다. 인자는 이 API 의 쿼리 파라미터와 같습니다(from·to·groupBy·meter·includeToday·page·pageSize).
기존에 연결된 앱은 재연결해야 이 도구가 보입니다. 권한은 연결할 때 확정되므로, read:usage 가 추가되기 전에 연결한 앱은 이 도구를 목록에서 받지 못합니다(에러가 아니라 도구가 없는 상태로 동작합니다).
records 는 모델 컨텍스트를 고려해 기본 50행만 실립니다(REST 기본값은 200). 전체 행 수는 meta.total 로 확인하시고, 더 필요하면 pageSize·page 를 지정하십시오. totals 는 여기서도 페이지와 무관한 전체 구간 합계입니다.
제한
- 조회 구간 최대 92일
includeToday=true는 진행 중인 구간을 원본에서 직접 집계하므로 응답이 느립니다. 정산에는 확정 구간만 사용하시는 것을 권장합니다.