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

# Usage publisher

> Come sono state chiamate le tue app pubblicate in un periodo: totali più suddivisioni per giorno, ora, app, canale, stato, versione, codice errore o caller.

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

Autenticazione: API key obbligatoria (`Authorization: Bearer <API Key>`).

Come sono state chiamate le tue app in un periodo: totali dell'intervallo, più ripartizioni per giorno (o per ora negli intervalli brevi), app e canale di chiamata (due qualsiasi possono essere incrociati), oppure ripartizioni diagnostiche per stato terminale, versione o codice di errore. È la controparte lato publisher dell'aggregazione della fatturazione: stesso vocabolario (`created_from` / `created_to` riferiti all'ora di avvio del run, inizio incluso e fine esclusa; `tz_offset` sposta solo i confini dei giorni; `data_app` / `triggered_by` restringono l'ambito), con la proprietà invertita da “run che ho avviato” ad “app di mia proprietà” (incluse le app con zero release).

Le ripartizioni per giorno / ora / app / canale derivano da bucket orari accumulati al raggiungimento dello stato terminale, quindi qualsiasi intervallo e offset di ore intere restano esatti ed economici. Le ripartizioni per stato / versione / errore vengono calcolate su richiesta dai dettagli dei run, quindi entrambi i limiti sono obbligatori e l'intervallo può coprire al massimo 92 giorni (`400 range-too-wide`). I gruppi di errore coprono solo i run che hanno un errore; ogni gruppo include il messaggio di errore più recente come `sample_message`. I run di debug dell'autore sono esclusi per impostazione predefinita; le sonde di salute della piattaforma non vengono mai conteggiate. Il successo include il successo parziale; i run annullati restano fuori dal denominatore del tasso di successo; le metriche senza run terminati valgono `null`. `amount` è il costo dei dati pagato dai chiamanti per questi run, non il ricavo liquidato del publisher.

I gruppi per giorno / ora sono in ordine crescente (le chiavi `hour` sono orari locali `YYYY-MM-DDTHH:00` secondo `tz_offset`, senza suffisso di fuso orario). Gli altri gruppi sono in ordine decrescente per numero di run. App sconosciute o di altri utenti in `data_app` restituiscono `404`.

`totals.callers` è il numero di utenti chiamanti distinti nell'intervallo, ricavato dai dettagli dei run, ed è impostato solo quando l'intervallo è delimitato e copre al massimo 92 giorni. `group_by=caller` ripartisce per chiamante una **singola app privata o condivisa**: l'autore (`caller_kind=owner`) e gli utenti attualmente nella grant list (`grantee`) compaiono con il loro nome utente attuale; tutti gli altri (ex grantee, chiamanti di un periodo pubblico) confluiscono in un unico gruppo `other`. Le app pubbliche o più app restituiscono `400 caller-group-unavailable`: i chiamanti delle app pubbliche restano anonimi e vengono solo conteggiati.

## Richiesta

### Parametri di query

<ParamField query="group_by" type="string" default="day">
  Una o due dimensioni, separate da virgola: `day` / `hour` / `data_app` / `triggered_by` / `state` / `version` / `error` / `caller` (per esempio `day,data_app`). `day` e `hour` non si possono combinare; `state` / `version` / `error` / `caller` richiedono un intervallo delimitato di al massimo 92 giorni; `caller` richiede inoltre esattamente un'app privata o condivisa. Predefinito `day`.
</ParamField>

<ParamField query="data_app" type="string[]">
  Limita a queste app (`<username>/<app_name>`, ripetibile). Predefinito: tutte le tue app.
</ParamField>

<ParamField query="created_from" type="string">
  Inizio inclusivo.
</ParamField>

<ParamField query="created_to" type="string">
  Fine esclusiva.
</ParamField>

<ParamField query="tz_offset" type="integer" default="0">
  Offset di fuso orario in minuti per i bucket giornalieri / orari. Usa `480` per l'ora standard della Cina. I bucket hanno granularità oraria; gli offset di mezz'ora vengono arrotondati all'ora.

  Intervallo da -720 a 840.
</ParamField>

<ParamField query="triggered_by" type="string">
  Limita a un solo canale di chiamata (`api` / `sdk` / `mcp` / `web` e così via).
</ParamField>

<ParamField query="include_test" type="boolean" default="False">
  Se includere le run di debug dell’autore.
</ParamField>

<ParamField query="compare" type="boolean" default="False">
  Restituisce anche `previous_totals` per la finestra di pari durata immediatamente precedente a `created_from`. Richiede entrambi i limiti.
</ParamField>

### Esempio di richiesta

```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"
```

## Risposta

### 200 successo

```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
      }
    ]
  }
}
```

Il payload è wrappato in `data`. Campi:

<ResponseField name="range" type="object" required>
  L'intervallo e l'offset effettivamente usati.

  <Expandable title="fields">
    <ResponseField name="created_from" type="string">
      Inizio incluso effettivamente applicato.
    </ResponseField>

    <ResponseField name="created_to" type="string">
      Fine esclusa effettivamente applicata.
    </ResponseField>

    <ResponseField name="tz_offset" type="integer">
      Offset dei bucket giornalieri / orari in minuti.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="currency" type="string">
  Valuta.
</ResponseField>

<ResponseField name="totals" type="object" required>
  Totali dell'intervallo.

  <Expandable title="fields">
    <ResponseField name="runs" type="integer">
      Numero di run.
    </ResponseField>

    <ResponseField name="succeeded" type="integer">
      Numero di successi (incluso il successo parziale).
    </ResponseField>

    <ResponseField name="partial" type="integer">
      Numero di successi parziali.
    </ResponseField>

    <ResponseField name="failed" type="integer">
      Numero di fallimenti.
    </ResponseField>

    <ResponseField name="cancelled" type="integer">
      Numero di annullamenti.
    </ResponseField>

    <ResponseField name="success_rate" type="number">
      Tasso di successo; i run annullati restano fuori dal denominatore. `null` quando non ci sono run terminati.
    </ResponseField>

    <ResponseField name="records" type="integer">
      Totale dei record riscritti.
    </ResponseField>

    <ResponseField name="avg_duration_ms" type="integer">
      Durata media di esecuzione in millisecondi.
    </ResponseField>

    <ResponseField name="amount" type="number">
      Costo totale dei dati pagato dai chiamanti.
    </ResponseField>

    <ResponseField name="apps_active" type="integer">
      Numero di app con almeno un run.
    </ResponseField>

    <ResponseField name="callers" type="integer">
      Utenti chiamanti distinti. `null` quando l'intervallo non è delimitato o supera 92 giorni.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="previous_totals" type="object">
  Totali della finestra precedente di pari durata quando `compare=true`.

  <Expandable title="fields">
    <ResponseField name="runs" type="integer">
      Numero di run.
    </ResponseField>

    <ResponseField name="succeeded" type="integer">
      Numero di successi (incluso il successo parziale).
    </ResponseField>

    <ResponseField name="partial" type="integer">
      Numero di successi parziali.
    </ResponseField>

    <ResponseField name="failed" type="integer">
      Numero di fallimenti.
    </ResponseField>

    <ResponseField name="cancelled" type="integer">
      Numero di annullamenti.
    </ResponseField>

    <ResponseField name="success_rate" type="number">
      Tasso di successo; i run annullati restano fuori dal denominatore.
    </ResponseField>

    <ResponseField name="records" type="integer">
      Totale dei record riscritti.
    </ResponseField>

    <ResponseField name="avg_duration_ms" type="integer">
      Durata media di esecuzione in millisecondi.
    </ResponseField>

    <ResponseField name="amount" type="number">
      Costo totale dei dati pagato dai chiamanti.
    </ResponseField>

    <ResponseField name="apps_active" type="integer">
      Numero di app con almeno un run.
    </ResponseField>

    <ResponseField name="callers" type="integer">
      Chiamanti distinti (utenti) nell'intervallo; calcolato dai dettagli dei run, quindi `null` a meno che entrambi i limiti siano indicati e distino al massimo 92 giorni.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="group_by" type="string">
  Dimensione/i effettivamente usata/e.
</ResponseField>

<ResponseField name="groups" type="object[]">
  Righe di gruppo. Ogni riga riporta le stesse metriche di `totals` più le chiavi di dimensione (`day` / `hour` / `namespace` + `app_name` / `channel` / `state` / `version` / `error_code` + `error_category` + `sample_message` + `last_seen_at` / `username` + `caller_kind`). Le chiavi non usate valgono `null`.

  <Expandable title="fields">
    <ResponseField name="runs" type="integer">
      Conteggio run nel gruppo.
    </ResponseField>

    <ResponseField name="succeeded" type="integer">
      Numero di successi (incluso il successo parziale).
    </ResponseField>

    <ResponseField name="partial" type="integer">
      Numero di successi parziali.
    </ResponseField>

    <ResponseField name="failed" type="integer">
      Numero di fallimenti.
    </ResponseField>

    <ResponseField name="cancelled" type="integer">
      Numero di annullamenti.
    </ResponseField>

    <ResponseField name="success_rate" type="number">
      Tasso di successo del gruppo.
    </ResponseField>

    <ResponseField name="records" type="integer">
      Record riscritti nel gruppo.
    </ResponseField>

    <ResponseField name="avg_duration_ms" type="integer">
      Durata media di esecuzione in millisecondi.
    </ResponseField>

    <ResponseField name="amount" type="number">
      Costo dei dati pagato dai chiamanti nel gruppo.
    </ResponseField>

    <ResponseField name="day" type="string">
      Chiave del giorno quando si raggruppa per giorno, `YYYY-MM-DD`.
    </ResponseField>

    <ResponseField name="hour" type="string">
      Chiave dell'ora quando si raggruppa per ora: `YYYY-MM-DDTHH:00` locale secondo `tz_offset`.
    </ResponseField>

    <ResponseField name="namespace" type="string">
      Username publisher quando raggruppi per app.
    </ResponseField>

    <ResponseField name="app_name" type="string">
      Nome app quando raggruppi per app.
    </ResponseField>

    <ResponseField name="channel" type="string">
      Canale di chiamata quando si raggruppa per `triggered_by`.
    </ResponseField>

    <ResponseField name="state" type="string">
      Stato terminale quando si raggruppa per stato.
    </ResponseField>

    <ResponseField name="version" type="string">
      Dimensione versione: la versione di release a cui era vincolato il run; `null` per i run di debug (sono vincolati a uno snapshot della build).
    </ResponseField>

    <ResponseField name="error_code" type="string">
      Codice di errore quando si raggruppa per errore.
    </ResponseField>

    <ResponseField name="error_category" type="string">
      Categoria di errore quando si raggruppa per errore.
    </ResponseField>

    <ResponseField name="sample_message" type="string">
      Dimensione errore: messaggio del run più recente in questo gruppo.
    </ResponseField>

    <ResponseField name="last_seen_at" type="string">
      Timestamp del run più recente nel gruppo.
    </ResponseField>

    <ResponseField name="username" type="string">
      Dimensione chiamante: il nome utente attuale del chiamante; `null` per il gruppo unificato `other` o quando l'utente non ha un nome utente.
    </ResponseField>

    <ResponseField name="caller_kind" type="string">
      Dimensione chiamante: `owner` (i run del publisher stesso), `grantee` (un utente attualmente nella grant list dell'app) o `other` (tutti gli altri chiamanti riuniti in un unico gruppo).
    </ResponseField>
  </Expandable>
</ResponseField>

### Errori

| HTTP | `code`                     | `category`      | Descrizione                                                                                                 |
| ---- | -------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------- |
| 401  | `unauthorized`             | `forbidden`     | API key mancante o non valida.                                                                              |
| 400  | `invalid-group-by`         | `invalid_input` | `group_by` non è consentito oppure la combinazione non è valida.                                            |
| 400  | `range-too-wide`           | `invalid_input` | Questa dimensione richiede sia `created_from` sia `created_to`, a non più di 92 giorni di distanza.         |
| 400  | `caller-group-unavailable` | `invalid_input` | `group_by=caller` supporta esattamente un'app privata o condivisa.                                          |
| 404  | `app-not-found`            | `not_found`     | L’app non esiste, è stata rinominata o è invisibile alla credenziale corrente (fuori scope private/shared). |

Le risposte di errore usano `{"error": {code, category, message, retryable}}`. Vedi <a href="/docs/it/datahub/api/reference/introduction#errors">Errori</a>.

## Librerie client

Gli SDK Python e JavaScript non wrappano ancora questo endpoint. Chiama REST direttamente.
