---
name: azion-break-down-requests-by-status-code
description: >-
  Split your applications' requests by status code, narrow them to one class, rank the hosts that return errors, and compare each code with the origin's answer.
---

# Break down requests by status code

You can split the requests of your [applications](/en/documentation/platform/applications/) by the HTTP status code they returned, in Azion Console or with the GraphQL API. [Real-Time Metrics](/en/documentation/platform/real-time-metrics/) reads these numbers from the `httpMetrics` dataset. For what each chart of the **Status Codes** dashboard measures, refer to [Build dashboards](/en/documentation/platform/real-time-metrics/build-dashboards/#status-codes).

## Prerequisites

- An Azion account. To create one, refer to [Create an account](/en/documentation/fundamentals/creating-account/).
- An application served by a [workload](/en/documentation/platform/workloads/), with requests in the range you want to read.

**Console**

- Access to Azion Console. To sign in, refer to [How to access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**API**

- A personal token. To create one, refer to [How to manage a personal token](/en/documentation/guides/platform/account-and-billing/personal-tokens/).
- `curl`.

---

## Open the status breakdown

The breakdown counts the requests of every application in your account, one count per status code.

**Console**

To open the breakdown in Azion Console:

1. **Open Real-Time Metrics**

   Access [Azion Console](https://console.azion.com/) > **Real-Time Metrics**.

   The page opens on the **Build** category, the **Applications** tab, and the **Data Transferred** dashboard.

2. **Select Status Codes in the dashboard selector**

The dashboard shows four line charts, **HTTP Status Codes 2XX** to **HTTP Status Codes 5XX**, and the **Requests by Status and Upstream Status** table. Each legend entry totals one series over the range, which starts at **Last 5 minutes**. To read a longer period, refer to [Filters and time range](/en/documentation/platform/real-time-metrics/filters-and-time-range/#time-range).

**API**

To read the breakdown with the GraphQL API, send a `POST` request to `https://api.azion.com/v4/metrics/graphql`. The query sums `requests` and groups the sums by `status`.

Replace `[TOKEN VALUE]` with your personal token, and the `begin` and `end` values with your range:

```bash
curl -X POST 'https://api.azion.com/v4/metrics/graphql' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Token [TOKEN VALUE]' \
  -d '{"query":"query RequestsByStatus { httpMetrics(limit: 100, filter: { tsRange: { begin: \"2026-01-01T12:00:00\", end: \"2026-01-02T12:00:00\" } }, aggregate: { sum: requests }, groupBy: [status], orderBy: [sum_DESC]) { status sum } }"}'
```

The API answers `200` with one row per status code, the most frequent first:

```json
{
  "data": {
    "httpMetrics": [
      {
        "status": 200,
        "sum": 1253
      },
      {
        "status": 496,
        "sum": 210
      },
      {
        "status": 501,
        "sum": 198
      },
      {
        "status": 304,
        "sum": 140
      },
      …
    ]
  }
}
```

The `sum` values of all rows add up to the `requestsTotal` of the range. `limit: 100` keeps every code: without `limit`, the API returns 10 rows. For every field of the dataset, refer to [Real-Time Metrics GraphQL fields](/en/documentation/devtools/graphql/gql-real-time-metrics-fields/#workloadmetrics).

---

## Narrow it to one status class

A filter on the status code keeps one class, such as the 5XX server errors. This section keeps the codes from 500 to 599.

**Console**

To filter the dashboard in Azion Console:

1. **Add a filter**

   In the filter row, select the filter icon, whose tooltip reads **Add filter**.

2. **Select the Status field**

   In **Filter**, select **Status**.

3. **Select the Between operator**

   In **Operator**, select **Between**.

4. **Enter the range**

   Enter `500` in **Begin** and `599` in **End**.

5. **Select Apply**

A chip under the filter row reads `Status between: (500,599)`. The **Requests by Status and Upstream Status** table now lists only the pairs whose status is in that range, so a server error is no longer hidden behind the most frequent `200` responses.

**API**

To filter with the API, add `statusRange` to `filter`, next to `tsRange`:

```bash
curl -X POST 'https://api.azion.com/v4/metrics/graphql' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Token [TOKEN VALUE]' \
  -d '{"query":"query ServerErrorsByStatus { httpMetrics(limit: 100, filter: { tsRange: { begin: \"2026-01-01T12:00:00\", end: \"2026-01-02T12:00:00\" }, statusRange: { begin: 500, end: 599 } }, aggregate: { sum: requests }, groupBy: [status], orderBy: [sum_DESC]) { status sum } }"}'
```

The API answers `200` with the 5XX codes alone:

```json
{
  "data": {
    "httpMetrics": [
      {
        "status": 501,
        "sum": 198
      },
      {
        "status": 502,
        "sum": 31
      },
      {
        "status": 504,
        "sum": 1
      }
    ]
  }
}
```

To total a class, sum `requests` with `statusRange`, as above. `requestsStatusCode5xx` can return less for the same range, because it counts only the 5XX codes that have no field of their own. For each class field, refer to [Build dashboards](/en/documentation/platform/real-time-metrics/build-dashboards/#status-codes).

---

## Find the hosts that return the errors

With the class filter in place, you can check which hosts return those errors. The API ranks every host in one query. In Azion Console, a second filter narrows the dashboard to one host at a time.

**Console**

To narrow the 5XX responses to one host in Azion Console, keep the **Status** filter and add a second one:

1. **Add a filter**

   In the filter row, select the filter icon, whose tooltip reads **Add filter**.

2. **Select the Host field**

   In **Filter**, select **Host**.

3. **Select the Equals operator**

   In **Operator**, select **Equals**.

4. **Enter the host**

   Enter the host to check, such as `www.example.com`.

5. **Select Apply**

A second chip reads `Host equals: www.example.com`. The **HTTP Status Codes 5XX** chart and the table now count only the 5XX responses of that host. To check another host, select the **Host** chip and change its value.

**API**

To rank the hosts with the API, keep `statusRange` and group by `host` instead of `status`:

```bash
curl -X POST 'https://api.azion.com/v4/metrics/graphql' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Token [TOKEN VALUE]' \
  -d '{"query":"query ServerErrorsByHost { httpMetrics(limit: 10, filter: { tsRange: { begin: \"2026-01-01T12:00:00\", end: \"2026-01-02T12:00:00\" }, statusRange: { begin: 500, end: 599 } }, aggregate: { sum: requests }, groupBy: [host], orderBy: [sum_DESC]) { host sum } }"}'
```

The API answers `200` with the hosts that returned 5XX responses, the most errors first:

```json
{
  "data": {
    "httpMetrics": [
      {
        "host": "www.example.com",
        "sum": 199
      },
      {
        "host": "api.example.com",
        "sum": 28
      },
      {
        "host": "static.example.com",
        "sum": 3
      }
    ]
  }
}
```

`limit: 10` keeps the ten hosts with the most errors.

---

## Find what the origin answered

The status code is what the client received. The upstream status is what the origin returned. When both carry the same error code, the error came from the origin.

**Console**

In Azion Console, keep the **Status** filter and read the **Requests by Status and Upstream Status** table. Each row pairs a **Status** with an **Upstream Status**, and **Total** counts the requests with that pair. The table lists the 10 most frequent pairs.

**API**

To pair the two codes with the API, group by `status` and `upstreamStatus`. The query keeps the 5XX filter and the ten most frequent pairs, as the Console table does:

```bash
curl -X POST 'https://api.azion.com/v4/metrics/graphql' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Token [TOKEN VALUE]' \
  -d '{"query":"query ServerErrorsByUpstreamStatus { httpMetrics(limit: 10, filter: { tsRange: { begin: \"2026-01-01T12:00:00\", end: \"2026-01-02T12:00:00\" }, statusRange: { begin: 500, end: 599 } }, aggregate: { sum: requests }, groupBy: [status, upstreamStatus], orderBy: [sum_DESC]) { status upstreamStatus sum } }"}'
```

The API answers `200` with one row per pair:

```json
{
  "data": {
    "httpMetrics": [
      {
        "status": 501,
        "upstreamStatus": 501,
        "sum": 198
      },
      {
        "status": 502,
        "upstreamStatus": 502,
        "sum": 21
      },
      {
        "status": 502,
        "upstreamStatus": 0,
        "sum": 10
      },
      {
        "status": 504,
        "upstreamStatus": 504,
        "sum": 1
      }
    ]
  }
}
```

A row whose `upstreamStatus` equals `status` counts errors that the origin returned. One status code can appear in several rows, once per upstream status.

---

## Next steps

- [Build dashboards](/en/documentation/platform/real-time-metrics/build-dashboards.md#status-codes): What each chart of the Status Codes dashboard counts, and the fields behind it.
- [Filter a Real-Time Metrics dashboard](/en/documentation/guides/platform/observability/add-filters-metrics.md): Add, edit, and remove the filters that narrow every chart.
- [Troubleshoot Real-Time Metrics](/en/documentation/platform/real-time-metrics/troubleshooting.md): Fix the symptoms that keep a chart or a query from returning the numbers you expect.
- [Real-Time Events](/en/documentation/platform/real-time-events.md): Read the logs behind each count, when a total is not enough to find the cause.
