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

# Usage statistics and credits

> Read the number of sent and received documents per day, week or month, and compare the usage with the credit balance of your company.

## Overview

The API reports how many documents your company sent and received in a period. Use these numbers for cost control, for internal reports, or to re-invoice usage to your own customers. The same response contains an estimate of the number of days that the credit balance covers.

Two endpoints give the data:

* `GET /api/stats` returns the usage counts and the estimate.
* `GET /api/me/` returns the plan and the credit balance of the company.

Both endpoints use the API key of the company. Each API key belongs to one company, so the numbers are always those of one company.

## What counts as usage

One sent document is one action. One received document is one action. The response reports the two types of action separately:

| Action | Counted documents |
| - | - |
| `DOCUMENT_SENT` | Outbound documents in the `SENT` state |
| `DOCUMENT_RECEIVED` | Inbound documents in the `RECEIVED` state |

These rules apply to the counts:

* Documents in the `DRAFT`, `TRANSIT` or `FAILED` state are not counted. A send that fails is not usage.
* Deleted documents are not counted. If you delete a document, the counts of earlier periods can become lower.
* A document belongs to the day on which it was created in e-invoice.be, not to its `invoice_date`. An invoice with an invoice date in a previous month is counted in the period in which you created it.

<Note>
  The API keeps each response for 5 minutes. A document that you sent a moment ago can be absent from the counts until that time has passed.
</Note>

## Get usage statistics

Send a `GET` request to `/api/stats`. All query parameters are optional.

<ParamField query="start_date" type="string">
  First day of the period, in `yyyy-mm-dd` format. If you omit it, the period starts on the day of the first counted document.
</ParamField>

<ParamField query="end_date" type="string">
  Last day of the period, in `yyyy-mm-dd` format. The full day is included. If you omit it, the period ends on the day of the last counted document.
</ParamField>

<ParamField query="aggregation" type="string" default="DAY">
  Size of the periods in `actions`: `DAY`, `WEEK` or `MONTH`.
</ParamField>

### Usage per day

<CodeGroup>
  ```bash cURL theme={null}
  curl -G "https://api.e-invoice.be/api/stats" \
    -H "Authorization: Bearer $E_INVOICE_API_KEY" \
    -d "start_date=2026-09-01" \
    -d "end_date=2026-09-07" \
    -d "aggregation=DAY"
  ```

  ```javascript Node.js theme={null}
  const params = new URLSearchParams({
    start_date: "2026-09-01",
    end_date: "2026-09-07",
    aggregation: "DAY",
  });

  const response = await fetch(`https://api.e-invoice.be/api/stats?${params}`, {
    headers: { Authorization: `Bearer ${process.env.E_INVOICE_API_KEY}` },
  });

  if (!response.ok) {
    throw new Error(`Request failed: ${response.status} ${await response.text()}`);
  }

  const stats = await response.json();
  console.log(stats);
  ```

  ```python Python theme={null}
  import os

  import requests

  response = requests.get(
      "https://api.e-invoice.be/api/stats",
      headers={"Authorization": f"Bearer {os.environ['E_INVOICE_API_KEY']}"},
      params={
          "start_date": "2026-09-01",
          "end_date": "2026-09-07",
          "aggregation": "DAY",
      },
      timeout=30,
  )
  response.raise_for_status()

  stats = response.json()
  print(stats)
  ```

  ```php PHP theme={null}
  <?php
  $query = http_build_query([
      'start_date' => '2026-09-01',
      'end_date' => '2026-09-07',
      'aggregation' => 'DAY',
  ]);

  $ch = curl_init("https://api.e-invoice.be/api/stats?$query");
  curl_setopt_array($ch, [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => [
          'Authorization: Bearer ' . getenv('E_INVOICE_API_KEY'),
      ],
  ]);

  $body = curl_exec($ch);
  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($status !== 200) {
      throw new RuntimeException("Request failed: $status $body");
  }

  $stats = json_decode($body, true);
  print_r($stats);
  ```

  ```csharp C# theme={null}
  using System.Net.Http.Headers;

  using var client = new HttpClient { BaseAddress = new Uri("https://api.e-invoice.be") };
  client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
      "Bearer", Environment.GetEnvironmentVariable("E_INVOICE_API_KEY"));

  var response = await client.GetAsync(
      "/api/stats?start_date=2026-09-01&end_date=2026-09-07&aggregation=DAY");
  response.EnsureSuccessStatusCode();

  var stats = await response.Content.ReadAsStringAsync();
  Console.WriteLine(stats);
  ```
</CodeGroup>

```json Response theme={null}
{
  "tenant_id": "ten-9k2m4p7q3w5x8r1t",
  "period_start": "2026-09-01",
  "period_end": "2026-09-07",
  "aggregation": "DAY",
  "actions": [
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-01", "count": 3 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-01", "count": 12 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-02", "count": 9 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-03", "count": 5 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-03", "count": 14 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-04", "count": 2 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-04", "count": 8 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-07", "count": 10 }
  ],
  "total_days": 7,
  "average_daily_usage": 9.0,
  "budget_estimation_days": 555.6
}
```

A day without documents has no entry in `actions`. In this example there are no entries for 5 and 6 September, and no `DOCUMENT_RECEIVED` entry for 2 September. The company in the examples on this page has a credit balance of 5000.

### Usage per week

```bash cURL theme={null}
curl -G "https://api.e-invoice.be/api/stats" \
  -H "Authorization: Bearer $E_INVOICE_API_KEY" \
  -d "start_date=2026-09-01" \
  -d "end_date=2026-09-30" \
  -d "aggregation=WEEK"
```

```json Response theme={null}
{
  "tenant_id": "ten-9k2m4p7q3w5x8r1t",
  "period_start": "2026-09-01",
  "period_end": "2026-09-30",
  "aggregation": "WEEK",
  "actions": [
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-08-31", "count": 10 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-08-31", "count": 43 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-07", "count": 12 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-07", "count": 51 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-14", "count": 8 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-14", "count": 47 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-21", "count": 15 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-21", "count": 55 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-28", "count": 4 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-28", "count": 25 }
  ],
  "total_days": 30,
  "average_daily_usage": 9.0,
  "budget_estimation_days": 555.6
}
```

The first `stat_date` is `2026-08-31`, the Monday of the week that contains 1 September. The count of that week contains only the documents from 1 September, because documents before `start_date` are not in the period.

### Usage per month

```bash cURL theme={null}
curl -G "https://api.e-invoice.be/api/stats" \
  -H "Authorization: Bearer $E_INVOICE_API_KEY" \
  -d "start_date=2026-07-01" \
  -d "end_date=2026-09-30" \
  -d "aggregation=MONTH"
```

```json Response theme={null}
{
  "tenant_id": "ten-9k2m4p7q3w5x8r1t",
  "period_start": "2026-07-01",
  "period_end": "2026-09-30",
  "aggregation": "MONTH",
  "actions": [
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-07-01", "count": 35 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-07-01", "count": 190 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-08-01", "count": 28 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-08-01", "count": 160 },
    { "action": "DOCUMENT_RECEIVED", "stat_date": "2026-09-01", "count": 49 },
    { "action": "DOCUMENT_SENT", "stat_date": "2026-09-01", "count": 221 }
  ],
  "total_days": 92,
  "average_daily_usage": 7.4,
  "budget_estimation_days": 675.7
}
```

<Tip>
  The [command-line tool](/cli) gives the same data with `peppol stats --from 2026-07-01 --to 2026-09-30 --aggregation MONTH`. Add `--json` to get the response as JSON.
</Tip>

## Response fields

<ResponseField name="tenant_id" type="string" required>
  Identifier of the company that owns the API key.
</ResponseField>

<ResponseField name="period_start" type="string" required>
  First day of the period (`yyyy-mm-dd`). Equal to `start_date` when you gave it. Otherwise the day of the first counted document.
</ResponseField>

<ResponseField name="period_end" type="string" required>
  Last day of the period (`yyyy-mm-dd`). Equal to `end_date` when you gave it. Otherwise the day of the last counted document.
</ResponseField>

<ResponseField name="aggregation" type="string" required>
  The aggregation that the API used: `DAY`, `WEEK` or `MONTH`.
</ResponseField>

<ResponseField name="actions" type="object[]" required>
  One entry for each combination of period and action that has a minimum of one document. The entries are sorted by `stat_date`, then by `action`. The list is empty when the period has no counted documents.

  <Expandable title="Properties of an entry">
    <ResponseField name="action" type="string" required>
      `DOCUMENT_SENT` or `DOCUMENT_RECEIVED`.
    </ResponseField>

    <ResponseField name="stat_date" type="string" required>
      The date that identifies the period (`yyyy-mm-dd`). See the table below.
    </ResponseField>

    <ResponseField name="count" type="integer" required>
      Number of documents for this action in this period.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="total_days" type="integer" required>
  Number of days from `period_start` to `period_end`, both days included. The minimum is `1`.
</ResponseField>

<ResponseField name="average_daily_usage" type="number" required>
  Sum of all counts divided by `total_days`, rounded to one decimal.
</ResponseField>

<ResponseField name="budget_estimation_days" type="number" default="0.0">
  Estimated number of days that the credit balance covers. See [Read the budget estimate](#read-the-budget-estimate).
</ResponseField>

### How `stat_date` relates to the aggregation

| Aggregation | Value of `stat_date` |
| - | - |
| `DAY` | The day itself |
| `WEEK` | The Monday of the week |
| `MONTH` | The first day of the month |

With `WEEK` or `MONTH`, the first `stat_date` can be earlier than `period_start`. This occurs when `start_date` is not a Monday or not the first day of a month. The count for that entry contains only the documents inside the period.

For totals per calendar week or calendar month, set `start_date` to the first day and `end_date` to the last day of a full week or month.

## Read the budget estimate

`budget_estimation_days` compares the credit balance with the usage of the period in the request. One action uses one credit.

```text theme={null}
budget_estimation_days = credit_balance / average_daily_usage
```

The result is rounded to one decimal. In the month example above, the balance is 5000 and `average_daily_usage` is 7.4, so the estimate is 5000 / 7.4 = 675.7 days.

The estimate changes with the period that you request, because the average changes. A short, busy period gives a lower estimate than a long period that contains quiet months. For a forecast, use a period that represents your normal volume, for example the last 30 or 90 days.

<Warning>
  A value of `0.0` means that there is no estimate. It does not mean that there are no credits. The API returns `0.0` when `average_daily_usage` is `0.0`. This includes a period with very low usage: an average below 0.05 documents per day is rounded to `0.0`. To know the balance, read `credit_balance` from `GET /api/me/`.
</Warning>

## Credit balance and plan

`GET /api/me/` returns the account data of the company, with the `plan` and the `credit_balance`.

```bash cURL theme={null}
curl "https://api.e-invoice.be/api/me/" \
  -H "Authorization: Bearer $E_INVOICE_API_KEY"
```

```json Response theme={null}
{
  "name": "E-INVOICE BV",
  "description": null,
  "plan": "enterprise",
  "credit_balance": 5000,
  "peppol_ids": ["0208:1018265814"],
  "ibans": ["BE68539007547034"],
  "company_number": "1018265814",
  "company_tax_id": null,
  "company_name": "E-INVOICE BV",
  "company_address": "Brusselsesteenweg 119/A",
  "company_zip": "1980",
  "company_city": "Zemst",
  "company_country": "Belgium",
  "company_email": null,
  "smp_registration": false,
  "smp_registration_date": null,
  "bcc_recipient_email": null
}
```

<ResponseField name="plan" type="string">
  Plan of the company: `starter`, `pro` or `enterprise`.
</ResponseField>

<ResponseField name="credit_balance" type="integer">
  Credit balance of the company. This is the value that `budget_estimation_days` uses.
</ResponseField>

The other fields of this response are in the [API reference](/api-reference).

## Usage per tenant for resellers

In the [reseller programme](/reseller-programme), each customer is a tenant with its own API key. `GET /api/stats` always reports the tenant that owns the API key in the request. To get the usage of each tenant, call the endpoint one time for each tenant, with the API key of that tenant. The `tenant_id` in each response tells you to which tenant the numbers belong.

You create and read the API keys of a tenant with the [Admin API](/admin-api). The Admin API also lets you set the `plan` and the `credit_balance` of a tenant.

The samples below read a JSON object from the environment variable `E_INVOICE_TENANT_KEYS`. The object maps a name of your choice to the API key of a tenant, for example `{"customer-a": "<api key>", "customer-b": "<api key>"}`. The samples print the monthly totals of each tenant.

<Accordion title="Usage of each tenant (Node.js and Python)">
  <CodeGroup>
    ```javascript Node.js theme={null}
    const tenantKeys = JSON.parse(process.env.E_INVOICE_TENANT_KEYS);

    const params = new URLSearchParams({
      start_date: "2026-09-01",
      end_date: "2026-09-30",
      aggregation: "MONTH",
    });

    for (const [name, apiKey] of Object.entries(tenantKeys)) {
      const response = await fetch(`https://api.e-invoice.be/api/stats?${params}`, {
        headers: { Authorization: `Bearer ${apiKey}` },
      });

      if (!response.ok) {
        console.error(`${name}: request failed with status ${response.status}`);
        continue;
      }

      const stats = await response.json();
      const totals = { DOCUMENT_SENT: 0, DOCUMENT_RECEIVED: 0 };
      for (const entry of stats.actions) {
        totals[entry.action] += entry.count;
      }

      console.log(
        `${name} (${stats.tenant_id}): sent ${totals.DOCUMENT_SENT}, received ${totals.DOCUMENT_RECEIVED}`
      );
    }
    ```

    ```python Python theme={null}
    import json
    import os

    import requests

    tenant_keys = json.loads(os.environ["E_INVOICE_TENANT_KEYS"])

    params = {
        "start_date": "2026-09-01",
        "end_date": "2026-09-30",
        "aggregation": "MONTH",
    }

    for name, api_key in tenant_keys.items():
        response = requests.get(
            "https://api.e-invoice.be/api/stats",
            headers={"Authorization": f"Bearer {api_key}"},
            params=params,
            timeout=30,
        )

        if not response.ok:
            print(f"{name}: request failed with status {response.status_code}")
            continue

        stats = response.json()
        totals = {"DOCUMENT_SENT": 0, "DOCUMENT_RECEIVED": 0}
        for entry in stats["actions"]:
            totals[entry["action"]] += entry["count"]

        print(
            f"{name} ({stats['tenant_id']}): "
            f"sent {totals['DOCUMENT_SENT']}, received {totals['DOCUMENT_RECEIVED']}"
        )
    ```
  </CodeGroup>
</Accordion>

```text Output theme={null}
customer-a (ten-9k2m4p7q3w5x8r1t): sent 221, received 49
customer-b (ten-5x7y9z1a3b5c7d9e): sent 64, received 0
```

<Tip>
  Always send `start_date` and `end_date` in a loop such as this one. With the two dates, a tenant without documents gives an empty `actions` list. Without them, that tenant gives a `404` response.
</Tip>

## Sandbox companies

A [sandbox company](/environments) has no credits and no billing. `GET /api/stats` operates the same for a sandbox company as for a production company: it counts the documents of that company that are in the `SENT` or `RECEIVED` state. Each company has its own API key, so the documents of a sandbox company are never in the counts of a production company.

Do not use `credit_balance` or `budget_estimation_days` of a sandbox company for a forecast.

## Errors

| Status | Cause |
| - | - |
| `400` | `end_date` is before `start_date`. The `detail` is `end_date must be greater than or equal to start_date`. |
| `401` | The API key is missing, invalid or inactive. |
| `404` | You omitted `start_date`, `end_date` or the two, and the company has no document in the `SENT` or `RECEIVED` state. The `detail` is `No documents found for this tenant`. |
| `422` | A date is not in `yyyy-mm-dd` format, or `aggregation` is not `DAY`, `WEEK` or `MONTH`. |

```json 404 response theme={null}
{
  "detail": "No documents found for this tenant"
}
```

See [Errors and troubleshooting](/guides/errors) for the error body formats.

## Next Steps

<CardGroup cols={2}>
  <Card title="Reseller programme" icon="handshake" href="/reseller-programme">
    Manage tenants and re-invoice usage to your customers.
  </Card>

  <Card title="Admin API" icon="code" href="/admin-api">
    Create tenants and API keys, and set the plan and credit balance.
  </Card>

  <Card title="Go-live checklist" icon="list-check" href="/going-live">
    Move from a sandbox company to a production company.
  </Card>

  <Card title="Document lifecycle and delivery tracking" icon="arrows-rotate" href="/guides/document-lifecycle">
    See which document states exist and when a document becomes `SENT` or `RECEIVED`.
  </Card>
</CardGroup>
