> ## 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.

# Billing aggregation

> How much I spent over a period and where it went: an interval
total plus a grouped breakdown by day, by data app or by
credential. Independent of /account — account is an identity
endpoint and carries no time series.

The time range shares vocabulary with the run list: `created_from`
/ `created_to` (ISO-8601 absolute timestamps, inclusive start,
exclusive end, attributed by run start time) — carry the same
parameters into GET /runs and you get exactly the runs behind any
group's numbers. `tz_offset` only affects which day a run falls
into for day buckets (so callers can reconcile by their local day)
and changes no amounts or range predicates. Only data fees are
aggregated. Day groups are ascending (read reconciliation front to
back); data app / credential groups are by amount descending
(where the money mainly goes / which key spends it).

The `credential` grouping answers "how much did each of my
credentials spend" (tracing which key a runaway script holds): the
key is the originating credential's non-secret stable identifier,
the same value as the `credential` filter on GET /runs — ownership
is always user-scoped; credentials are only a partition within it,
never a cross-user view.



## OpenAPI

````yaml /jp/datahub/api/openapi.json get /v1/billing
openapi: 3.1.0
info:
  title: DataHub API
  version: 0.2.0
  description: Public /v1 contract of Octoparse DataHub. Internal channels are excluded.
servers:
  - url: https://api-datahub.octoparse.com
security:
  - bearerAuth: []
tags:
  - name: Discovery
    description: >-
      Anonymous access: platform metadata (currency), data app search, detail
      and input contract, machine-readable manifest spec.
  - name: Publishing
    description: >-
      Self-service publishing channel (API Key auth), two-phase: validate first
      (validate / package, nothing persisted), then publish (POST /data-apps,
      the submission goes live as a new Release). api kind (declarative
      integration) becomes visible on publish; code kind (code package) returns
      202 and enters an async image build; once ready it is promoted to a
      Release, visible and runnable. Poll progress via GET
      /data-apps/{ref}/builds.
  - name: Runs & Results
    description: >-
      Start / query / cancel runs and read result records with pagination.
      Business inputs go in the request body; platform run options (wait,
      max_records) go in query parameters.
  - name: Datasets
    description: >-
      Metadata and record access for platform datasets (including seeded stock
      data).
  - name: Account
    description: Account info and cumulative usage for the current API Key.
  - name: Secrets
    description: >-
      CRUD for upstream credentials (environment entries referenced by manifest
      `runtime.env`). Plaintext is write-only: every read returns a mask.
paths:
  /v1/billing:
    get:
      tags:
        - Account
      summary: Billing aggregation
      description: |-
        How much I spent over a period and where it went: an interval
        total plus a grouped breakdown by day, by data app or by
        credential. Independent of /account — account is an identity
        endpoint and carries no time series.

        The time range shares vocabulary with the run list: `created_from`
        / `created_to` (ISO-8601 absolute timestamps, inclusive start,
        exclusive end, attributed by run start time) — carry the same
        parameters into GET /runs and you get exactly the runs behind any
        group's numbers. `tz_offset` only affects which day a run falls
        into for day buckets (so callers can reconcile by their local day)
        and changes no amounts or range predicates. Only data fees are
        aggregated. Day groups are ascending (read reconciliation front to
        back); data app / credential groups are by amount descending
        (where the money mainly goes / which key spends it).

        The `credential` grouping answers "how much did each of my
        credentials spend" (tracing which key a runaway script holds): the
        key is the originating credential's non-secret stable identifier,
        the same value as the `credential` filter on GET /runs — ownership
        is always user-scoped; credentials are only a partition within it,
        never a cross-user view.
      operationId: billing_report_v1_billing_get
      parameters:
        - name: group_by
          in: query
          required: false
          schema:
            type: string
            pattern: ^(day|data_app|credential)$
            default: day
            title: Group By
        - name: created_from
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Created From
        - name: created_to
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Created To
        - name: tz_offset
          in: query
          required: false
          schema:
            type: integer
            maximum: 840
            minimum: -720
            description: >-
              timezone offset for day buckets (minutes relative to UTC, e.g. 480
              for UTC+8); default 0 means UTC days. Fixed offset, no DST;
              drill-down boundaries must be converted with the same offset into
              UTC absolute timestamps and passed as created_from/to
            default: 0
            title: Tz Offset
          description: >-
            timezone offset for day buckets (minutes relative to UTC, e.g. 480
            for UTC+8); default 0 means UTC days. Fixed offset, no DST;
            drill-down boundaries must be converted with the same offset into
            UTC absolute timestamps and passed as created_from/to
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataEnvelope_BillingReport_'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    DataEnvelope_BillingReport_:
      properties:
        data:
          $ref: '#/components/schemas/BillingReport'
      type: object
      required:
        - data
      title: DataEnvelope[BillingReport]
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    BillingReport:
      properties:
        total:
          type: number
          title: Total
          default: 0
        currency:
          type: string
          title: Currency
        group_by:
          type: string
          title: Group By
          default: day
        groups:
          items:
            $ref: '#/components/schemas/BillingGroup'
          type: array
          title: Groups
      type: object
      title: BillingReport
      description: |-
        Spending aggregate from the caller's perspective (billing report):
        range total plus per-group breakdown. Data fees only.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    BillingGroup:
      properties:
        day:
          anyOf:
            - type: string
            - type: 'null'
          title: Day
        namespace:
          anyOf:
            - type: string
            - type: 'null'
          title: Namespace
        app_name:
          anyOf:
            - type: string
            - type: 'null'
          title: App Name
        credential:
          anyOf:
            - type: string
            - type: 'null'
          title: Credential
        credential_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Credential Name
        runs:
          type: integer
          title: Runs
          default: 0
        amount:
          type: number
          title: Amount
          default: 0
      type: object
      title: BillingGroup
      description: >-
        One group of the billing aggregate: group_by=day carries `day`,

        group_by=data_app carries the two-part app reference,
        group_by=credential

        carries `credential` (a non-secret stable identifier, same value as the

        GET /runs filter).
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: DataHub API Key

````