> ## Documentation Index
> Fetch the complete documentation index at: https://www.octoparse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 게시자 사용량

> 기간 내 게시 App 호출: 합계와 일·시간·App·채널 등 내역.

**`GET`** `https://api-datahub.octoparse.com/v1/publisher/usage`

인증: API 키 필요(`Authorization: Bearer <API Key>`).

기간 동안 내 App이 어떻게 호출되었는지: 기간 합계와 함께 일별(짧은 기간은 시간별), App별, 호출 채널별 분석(임의의 두 가지를 교차 가능), 또는 최종 상태·버전·오류 코드별 진단 분석을 제공합니다. 청구 집계의 게시자 측 대응 기능으로, 용어가 같습니다(`created_from` / `created_to`는 실행 시작 시각 기준이며 시작은 포함, 끝은 제외. `tz_offset`은 날짜 경계만 옮김. `data_app` / `triggered_by`로 범위를 좁힘). 다만 소유 기준이 “내가 시작한 실행”에서 “내가 소유한 App”(Release가 0개인 App 포함)으로 바뀝니다.

일/시간/App/채널별 분석은 최종 상태에 도달할 때 누적되는 시간 단위 버킷에서 나오므로, 어떤 기간과 정시 단위 오프셋이든 정확하고 저렴하게 계산됩니다. 상태/버전/오류별 분석은 실행 상세에서 필요할 때 계산되므로 시작과 끝 경계가 모두 필요하며 기간은 최대 92일입니다(`400 range-too-wide`). 오류 그룹은 오류가 있는 실행만 포함하며, 각 그룹에는 최신 오류 메시지가 `sample_message`로 들어갑니다. 작성자의 디버그 실행은 기본적으로 제외되며, 플랫폼 상태 점검(probe)은 절대 집계되지 않습니다. 성공에는 부분 성공이 포함되고, 취소된 실행은 성공률 분모에서 제외되며, 최종 상태 실행이 없는 지표는 `null`입니다. `amount`는 호출자가 이 실행들에 지불한 데이터 요금이며, 게시자의 정산 수익이 아닙니다.

일/시간 그룹은 오름차순입니다(`hour` 키는 `tz_offset` 기준 현지 시각 `YYYY-MM-DDTHH:00`이며 시간대 접미사가 없음). 다른 그룹은 실행 수 내림차순입니다. `data_app`에 알 수 없는 App이나 다른 사람의 App을 지정하면 `404`를 반환합니다.

`totals.callers`는 기간 내 고유 호출 사용자 수로, 실행 상세에서 계산되며 기간이 제한되고 최대 92일일 때만 설정됩니다. `group_by=caller`는 **단일 private 또는 shared App**을 호출자별로 나눕니다: 작성자(`caller_kind=owner`)와 현재 grant 목록에 있는 사용자(`grantee`)는 현재 사용자 이름으로 표시되고, 나머지(이전 grantee, 공개 기간의 호출자)는 모두 하나의 `other` 그룹으로 합쳐집니다. 공개 App이나 여러 App은 `400 caller-group-unavailable`을 반환합니다: 공개 App의 호출자는 익명으로 유지되며 수만 집계됩니다.

## 요청

### 쿼리 파라미터

<ParamField query="group_by" type="string" default="day">
  하나 또는 두 개의 차원을 쉼표로 구분해 지정: `day` / `hour` / `data_app` / `triggered_by` / `state` / `version` / `error` / `caller`(예: `day,data_app`). `day`와 `hour`는 함께 쓸 수 없습니다. `state` / `version` / `error` / `caller`는 최대 92일의 제한된 기간이 필요합니다. `caller`는 추가로 private 또는 shared App을 정확히 하나 지정해야 합니다. 기본값은 `day`입니다.
</ParamField>

<ParamField query="data_app" type="string[]">
  이 App들로 제한합니다(`<username>/<app_name>`, 반복 지정 가능). 기본값: 내 모든 App.
</ParamField>

<ParamField query="created_from" type="string">
  시작(포함).
</ParamField>

<ParamField query="created_to" type="string">
  끝(제외).
</ParamField>

<ParamField query="tz_offset" type="integer" default="0">
  일/시간 버킷의 시간대 오프셋(분). 중국 표준시는 `480`을 사용합니다. 버킷은 시간 단위이므로 30분 단위 오프셋은 시간 단위로 반올림됩니다.

  범위는 -720\~840입니다.
</ParamField>

<ParamField query="triggered_by" type="string">
  하나의 호출 채널로 제한합니다(`api` / `sdk` / `mcp` / `web` 등).
</ParamField>

<ParamField query="include_test" type="boolean" default="False">
  작성자의 디버그 실행을 포함할지 여부.
</ParamField>

<ParamField query="compare" type="boolean" default="False">
  `created_from` 바로 앞의 같은 길이 기간에 대한 `previous_totals`도 반환합니다. 시작과 끝 경계가 모두 필요합니다.
</ParamField>

### 요청 예시

```bash theme={null}
curl \
  -H "Authorization: Bearer $OCTOPARSE_API_KEY" \
  "https://api-datahub.octoparse.com/v1/publisher/usage?group_by=day,data_app&created_from=2026-09-01T00:00:00%2B08:00&created_to=2026-10-01T00:00:00%2B08:00&tz_offset=480"
```

## 응답

### 200 성공

```json theme={null}
{
  "data": {
    "range": {
      "created_from": null,
      "created_to": null,
      "tz_offset": 480
    },
    "currency": "CNY",
    "totals": {
      "runs": 2,
      "succeeded": 2,
      "partial": 0,
      "failed": 0,
      "cancelled": 0,
      "success_rate": 1.0,
      "records": 40,
      "avg_duration_ms": 422,
      "amount": 0.04,
      "apps_active": 1,
      "callers": null
    },
    "previous_totals": null,
    "group_by": "day",
    "groups": [
      {
        "runs": 2,
        "succeeded": 2,
        "partial": 0,
        "failed": 0,
        "cancelled": 0,
        "success_rate": 1.0,
        "records": 40,
        "avg_duration_ms": 422,
        "amount": 0.04,
        "day": "2026-09-15",
        "hour": null,
        "namespace": null,
        "app_name": null,
        "channel": null,
        "state": null,
        "version": null,
        "error_code": null,
        "error_category": null,
        "sample_message": null,
        "last_seen_at": null,
        "username": null,
        "caller_kind": null
      }
    ]
  }
}
```

페이로드는 `data`로 감쌉니다. 필드:

<ResponseField name="range" type="object" required>
  실제로 사용된 범위와 오프셋.

  <Expandable title="fields">
    <ResponseField name="created_from" type="string">
      실제로 적용된 시작(포함).
    </ResponseField>

    <ResponseField name="created_to" type="string">
      실제로 적용된 끝(제외).
    </ResponseField>

    <ResponseField name="tz_offset" type="integer">
      일/시간 버킷 오프셋(분).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="currency" type="string">
  통화.
</ResponseField>

<ResponseField name="totals" type="object" required>
  기간 합계.

  <Expandable title="fields">
    <ResponseField name="runs" type="integer">
      실행 수.
    </ResponseField>

    <ResponseField name="succeeded" type="integer">
      성공 수(부분 성공 포함).
    </ResponseField>

    <ResponseField name="partial" type="integer">
      부분 성공 수.
    </ResponseField>

    <ResponseField name="failed" type="integer">
      실패 수.
    </ResponseField>

    <ResponseField name="cancelled" type="integer">
      취소 수.
    </ResponseField>

    <ResponseField name="success_rate" type="number">
      성공률. 취소된 실행은 분모에서 제외됩니다. 최종 상태 실행이 없으면 `null`.
    </ResponseField>

    <ResponseField name="records" type="integer">
      다시 기록된 레코드 합계.
    </ResponseField>

    <ResponseField name="avg_duration_ms" type="integer">
      평균 실행 소요 시간(밀리초).
    </ResponseField>

    <ResponseField name="amount" type="number">
      호출자가 지불한 데이터 요금 합계.
    </ResponseField>

    <ResponseField name="apps_active" type="integer">
      실행이 한 번 이상 있는 App 수.
    </ResponseField>

    <ResponseField name="callers" type="integer">
      고유 호출 사용자 수. 기간이 제한되지 않았거나 92일을 넘으면 `null`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="previous_totals" type="object">
  `compare=true`일 때 직전 같은 길이 기간의 합계.

  <Expandable title="fields">
    <ResponseField name="runs" type="integer">
      실행 수.
    </ResponseField>

    <ResponseField name="succeeded" type="integer">
      성공 수(부분 성공 포함).
    </ResponseField>

    <ResponseField name="partial" type="integer">
      부분 성공 수.
    </ResponseField>

    <ResponseField name="failed" type="integer">
      실패 수.
    </ResponseField>

    <ResponseField name="cancelled" type="integer">
      취소 수.
    </ResponseField>

    <ResponseField name="success_rate" type="number">
      성공률. 취소된 실행은 분모에서 제외됩니다.
    </ResponseField>

    <ResponseField name="records" type="integer">
      다시 기록된 레코드 합계.
    </ResponseField>

    <ResponseField name="avg_duration_ms" type="integer">
      평균 실행 소요 시간(밀리초).
    </ResponseField>

    <ResponseField name="amount" type="number">
      호출자가 지불한 데이터 요금 합계.
    </ResponseField>

    <ResponseField name="apps_active" type="integer">
      실행이 한 번 이상 있는 App 수.
    </ResponseField>

    <ResponseField name="callers" type="integer">
      기간 내 고유 호출자(사용자) 수. 실행 상세에서 계산되므로 두 경계가 모두 주어지고 간격이 최대 92일이 아니면 `null`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="group_by" type="string">
  실제로 사용된 차원.
</ResponseField>

<ResponseField name="groups" type="object[]">
  그룹 행. 각 행은 `totals`와 같은 지표에 차원 키(`day` / `hour` / `namespace` + `app_name` / `channel` / `state` / `version` / `error_code` + `error_category` + `sample_message` + `last_seen_at` / `username` + `caller_kind`)가 더해집니다. 사용되지 않는 키는 `null`입니다.

  <Expandable title="fields">
    <ResponseField name="runs" type="integer">
      그룹 내 실행 수.
    </ResponseField>

    <ResponseField name="succeeded" type="integer">
      성공 수(부분 성공 포함).
    </ResponseField>

    <ResponseField name="partial" type="integer">
      부분 성공 수.
    </ResponseField>

    <ResponseField name="failed" type="integer">
      실패 수.
    </ResponseField>

    <ResponseField name="cancelled" type="integer">
      취소 수.
    </ResponseField>

    <ResponseField name="success_rate" type="number">
      그룹의 성공률.
    </ResponseField>

    <ResponseField name="records" type="integer">
      그룹에서 다시 기록된 레코드 수.
    </ResponseField>

    <ResponseField name="avg_duration_ms" type="integer">
      평균 실행 소요 시간(밀리초).
    </ResponseField>

    <ResponseField name="amount" type="number">
      그룹에서 호출자가 지불한 데이터 요금.
    </ResponseField>

    <ResponseField name="day" type="string">
      일별로 그룹화할 때의 날짜 키(`YYYY-MM-DD`).
    </ResponseField>

    <ResponseField name="hour" type="string">
      시간별로 그룹화할 때의 시간 키: `tz_offset` 기준 현지 `YYYY-MM-DDTHH:00`.
    </ResponseField>

    <ResponseField name="namespace" type="string">
      App별로 그룹화할 때의 게시자 사용자 이름.
    </ResponseField>

    <ResponseField name="app_name" type="string">
      App별로 그룹화할 때의 App 이름.
    </ResponseField>

    <ResponseField name="channel" type="string">
      `triggered_by`로 그룹화할 때의 호출 채널.
    </ResponseField>

    <ResponseField name="state" type="string">
      상태별로 그룹화할 때의 최종 상태.
    </ResponseField>

    <ResponseField name="version" type="string">
      버전 차원: 실행이 고정된 Release 버전. 디버그 실행은 `null`(Build 스냅샷에 고정되므로).
    </ResponseField>

    <ResponseField name="error_code" type="string">
      오류별로 그룹화할 때의 오류 코드.
    </ResponseField>

    <ResponseField name="error_category" type="string">
      오류별로 그룹화할 때의 오류 카테고리.
    </ResponseField>

    <ResponseField name="sample_message" type="string">
      오류 차원: 이 그룹에서 가장 최근 실행의 메시지.
    </ResponseField>

    <ResponseField name="last_seen_at" type="string">
      그룹에서 가장 최근 실행의 타임스탬프.
    </ResponseField>

    <ResponseField name="username" type="string">
      호출자 차원: 호출자의 현재 사용자 이름. 합쳐진 `other` 그룹이거나 사용자 이름이 없는 사용자는 `null`.
    </ResponseField>

    <ResponseField name="caller_kind" type="string">
      호출자 차원: `owner`(게시자 본인의 실행), `grantee`(현재 App의 grant 목록에 있는 사용자) 또는 `other`(나머지 모든 호출자를 하나로 합친 그룹).
    </ResponseField>
  </Expandable>
</ResponseField>

### 오류

| HTTP | `code`                     | `category`      | 설명                                                                      |
| ---- | -------------------------- | --------------- | ----------------------------------------------------------------------- |
| 401  | `unauthorized`             | `forbidden`     | API 키 누락 또는 무효.                                                         |
| 400  | `invalid-group-by`         | `invalid_input` | `group_by`가 허용되지 않거나 조합이 잘못되었습니다.                                       |
| 400  | `range-too-wide`           | `invalid_input` | 이 차원에는 `created_from`과 `created_to`가 모두 필요하며, 간격은 최대 92일입니다.            |
| 400  | `caller-group-unavailable` | `invalid_input` | `group_by=caller`는 private 또는 shared App을 정확히 하나만 지원합니다.                |
| 404  | `app-not-found`            | `not_found`     | App이 존재하지 않거나, 이름이 변경되었거나, 현재 자격 증명으로는 보이지 않습니다(private / shared 범위 밖). |

오류 응답은 `{"error": {code, category, message, retryable}}`입니다. <a href="/docs/ko/datahub/api/reference/introduction#errors">오류</a> 참고.

## 클라이언트 라이브러리

Python / JavaScript SDK는 아직 이 엔드포인트를 감싸지 않습니다. REST를 직접 호출하세요.
