---
title: Route
description: Routes are JSON-encoded configuration files that you add to IG to manage requests. You can add routes in the following ways:
component: pinggateway
version: 2023.11
page_id: pinggateway:reference:Route
canonical_url: https://docs.pingidentity.com/pinggateway/2026/reference/Route.html
llms_txt: https://docs.pingidentity.com/pinggateway/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: 2025-06-03T11:21:31Z
superseded_by: https://docs.pingidentity.com/pinggateway/2026/reference/Route.html
section_ids:
  Route-usage: Usage
  Route-properties: Properties
  prom-route-metrics-prom: Route metrics at the Prometheus Scrape Endpoint
  prom-route-metrics-crest: Route Metrics at the Common REST Monitoring Endpoint
  route-conditions: Example conditions and requests
---

# Route

Routes are JSON-encoded configuration files that you add to IG to manage requests. You can add routes in the following ways:

* Manually into the filesystem.

* Through Common REST commands. For information, refer to [Routes and Common REST](../configure/crest.html).

* Through Studio. For information, refer to the [Studio guide](../studio-guide/preface.html#preface).

Routes handle requests and their context, and then hand off any request they accept to a [Handler](Handlers.html).

When a route has a condition, it handles only requests that meet the condition. When a route has no condition, it handles any request.

Routes inherit settings from their parent configuration. This means that you can configure global objects in the `config.json` heap, for example, and then reference the objects by name in any other IG configuration.

## Usage

```json
{
  "handler": Handler reference,
  "heap": [ object, ... ],
  "condition": runtime expression<boolean>,
  "name": string,
  "secrets": {
    "stores": [ SecretStore reference, ... ]
  }, //deprecated
  "session": AsyncSessionManager reference,
  "auditService": AuditService reference,
  "globalDecorators": map,
  "decorator name": Decorator object
}
```

(\*)Deprecated

## Properties

* `"handler"`: *Handler [reference](preface.html#definition-reference), required*

  The [Handler](Handlers.html) to which IG dispaches requests.

  Provide the name of a Handler object defined in the heap or an inline Handler configuration object.

* `"heap"`: *array of [objects](preface.html#definition-object), optional*

  Heap object configuration for objects local to this route.

  Objects referenced but not defined here are inherited from the parent.

  You can omit an empty array. If you only have one object in the heap, you can inline it as the handler value.

  See also [Heap objects](RequiredConfiguration.html#heap-objects).

* `"condition"`: *runtime expression<[boolean](preface.html#definition-boolean)>, optional*

  A condition based on the request, context, or IG runtime environment, such as system properties or environment variables.

  * `true`: The request is dispatched to the route.

  * `false`: The condition for the next route in the configuration is evaluated.

  * No condition: the request is dispatched unconditionally to the route.

  |   |                                                                                                                                                                                                                                                                                                                                                                         |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | For debugging, log the routes for which IG evaluates a condition, and the route that matches a condition. Add the following line to a custom `$HOME/.openig/config/logback.xml`, and restart IG:```xml
  <logger name="org.forgerock.openig.handler.router.RouterHandler" level="trace" />
  ```For information, refer to [Manage logs](../maintenance-guide/logging.html). |

  An external request can never match a condition that uses the reserved administrative route. Therefore, routes that use these conditions are effectively ignored. For example, if `/openig` is the administrative route, a route with the following condition is ignored: `${find(request.uri.path, '^/openig/my/path')}`.

  Default: `${true}`

  For example conditions and requests that match them, refer to [Example conditions and requests](#route-conditions).

* `"name"`: *[string](preface.html#definition-string), optional*

  Route name.

  The Router uses the `name` property to order the routes in the configuration. If the route does not have a `name` property, the Router uses the route ID.

  The route ID is managed as follows:

  * When you add a route manually to the routes folder, the route ID is the value of the `_id` field. If there is no `_id` field, the route ID is the filename of the added route.

  * When you add a route through the Common REST endpoint, the route ID is the value of the mandatory `_id` field.

  * When you add a route through Studio, you can edit the default route ID.

    CAUTION: The filename of a route cannot be `default.json`. The route `name` property or route ID cannot be `default`.

  Default: route ID

- `"secrets"`: *SecretStore [reference](preface.html#definition-reference), optional*

  |   |                                                                                                                                                                                                                                            |
  | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  |   | This property is deprecated; use [SecretsProvider](SecretsProvider.html) instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  One or more secret stores, as defined in [Secrets](secrets.html).

* `"session"`: *AsyncSessionManager reference. [reference](preface.html#definition-reference), optional*

  Stateless session implementation for this route. Define an AuthenticatedEncryptedJwtSessionManager object inline or in the heap.

  When a request enters the route, IG builds a new session object for the route. The session content is available to the route's downstream handlers and filters. Session content available in the ascending configuration (a parent route or `config.json`) is not available in the new session.

  When the response exits the route, the session content is serialized as a secure JWT that is encrypted and signed, and the resulting JWT string is placed in a cookie. Session information set inside the route is no longer available. The `session` references the previous session object.

  Default: Do not change the session storage implementation.

  For more information, refer to [AsyncSessionManager](../_attachments/apidocs/org/forgerock/http/session/AsyncSessionManager.html), and [Sessions](../about/about-sessions.html).

* `"auditService"`: *AuditService [reference](preface.html#definition-reference), optional*

  An audit service for the route. Provide either the name of an AuditService object defined in the heap or an inline AuditService configuration object.

  Default: No auditing of a configuration. The NoOpAuditService provides an empty audit service to the top-level heap and its child routes.

* `"globalDecorators"`: *[map](preface.html#map), optional*

  A map of one or more data pairs with the format `Map<String, JsonValue>`, where:

  * The key is a decorator name

  * The value is a decorator configuration, passed *as is* to the decorator

  The following format is required:

  ```json
  {
    "globalDecorators": {
      "decorator name": "decoration configuration",
      ...
    }
  }
  ```

  All compatible objects in a route are decorated with the mapped decorator value. For more information, refer to [Decorators](Decorators.html).

  In the following example, the property decorates all compatible objects in the route with a capture and timer decorator:

  ```json
  "globalDecorators": {
    "capture": "all",
    "timer": true
  }
  ```

  Default: Empty

* `"decorator name"`: *Decorator [object](preface.html#definition-object), optional*

  Decorate the main handler of this route with a decorator referred to by the decorator name, and provide the configuration as described in [Decorators](Decorators.html).

  Default: No decoration.

## Route metrics at the Prometheus Scrape Endpoint

Route metrics at the Prometheus Scrape Endpoint have the following labels:

* `name`: Route name, for example, `My Route`.

  If the router was declared with a default handler, then its metrics are published through the route named `default`.

* `route`: Route identifier, for example, `my-route`.

* `router`: Fully qualified name of the router, for example, `gateway.main-router`.

The following table summarizes the recorded metrics:

| Name(1)                          | [Monitoring type](MonitoringTypes.html) | Description                                                                                                                                                                                                                                   |
| -------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ig_route_request_active`        | Gauge                                   | Number of requests being processed.                                                                                                                                                                                                           |
| `ig_route_request_total`         | Counter                                 | Number of requests processed by the router or route since it was deployed.                                                                                                                                                                    |
| `ig_route_response_error_total`  | Counter                                 | Number of responses that threw an exception.                                                                                                                                                                                                  |
| `ig_route_response_null_total`   | Counter                                 | Number of responses that were not handled by IG.                                                                                                                                                                                              |
| `ig_route_response_status_total` | Counter                                 | Number of responses by HTTP status code family. The `family` label depends on the HTTP status code:- Informational (1xx)

- Successful (2xx)

- Redirection (3xx)

- Client_error (4xx)

- Server_error (5xx)

- Unknown (status code >= 600) |
| `ig_route_response_time`         | Summary                                 | A summary of response time observations.                                                                                                                                                                                                      |

(1)Metric names are deprecated and expected to be replaced with names ending in \_total. The information provided by the metric is not deprecated. Other Prometheus metrics are not affected.

For more information about the the Prometheus Scrape Endpoint, see [Prometheus Scrape Endpoint](Monitoring.html#monitoring-prom).

## Route Metrics at the Common REST Monitoring Endpoint

Route metrics at the Common REST Monitoring Endpoint are published with an `_id` in the following pattern:

* `heap.router-name.route.route-name.metric`

The following table summarizes the recorded metrics:

| Name                            | [Monitoring type](MonitoringTypes.html) | Description                                                                                                      |
| ------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `request`                       | Counter                                 | Number of requests processed by the router or route since it was deployed.                                       |
| `request.active`                | Gauge                                   | Number of requests being processed by the router or route at this moment.                                        |
| `response.error`                | Counter                                 | Number of responses that threw an exception.                                                                     |
| `response.null`                 | Counter                                 | Number of responses that were not handled by IG.                                                                 |
| `response.status.client_error`  | Counter                                 | Number of responses with an HTTP status code `400`-`499`, indicating client error.                               |
| `response.status.informational` | Counter                                 | Number of responses with an HTTP status code `100`-`199`, indicating that they are provisional responses.        |
| `response.status.redirection`   | Counter                                 | Number of responses with an HTTP status code `300`-`399`, indicating a redirect.                                 |
| `response.status.server_error`  | Counter                                 | Number of responses with an HTTP status code `500`-`599`, indicating server error.                               |
| `response.status.successful`    | Counter                                 | Number of responses with an HTTP status code `200`-`299`, indicating success.                                    |
| `response.status.unknown`       | Counter                                 | Number of responses with an HTTP status code `600`-`699`, indicating that a request failed and was not executed. |
| `response.time`                 | Timer                                   | Time-series summary statistics.                                                                                  |

For more information about the the Common REST Monitoring Endpoint, see [Common REST Monitoring Endpoint](Monitoring.html#monitoring-crest).

### Example conditions and requests

| Condition                                                                                                                                            | Requests that meet the condition                                                                                                                                                                                                                         |
| ---------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ```json
"${true}"
```                                                                                                                                | All requests, because this expression always evaluates to `true`.                                                                                                                                                                                        |
| ```json
"${find(request.uri.path, '^/login')}"
```                                                                                                   | `http://app.example.com/login`, . . .                                                                                                                                                                                                                    |
| ```json
"${request.uri.host == 'api.example.com'}"
```                                                                                               | `http://api.example.com/`, `https://api.example.com/home`, `http://api.example.com:8080/home`, . . .                                                                                                                                                     |
| ```json
"${find(contexts.client.remoteAddress, '127.0.0.1')}"
```                                                                                    | `http://localhost:8080/keygen`, `http://127.0.0.1:8080/keygen`, . . .Where `/keygen` is not mandatory and could be anything else.                                                                                                                        |
| ```json
"${find(request.uri.query, 'demo=simple')}"
```                                                                                              | `http://ig.example.com:8080/login?demo=simple`, . . .For information about URI query, refer to `query` in [URI](RequestsResponses.html#URI).                                                                                                             |
| ```json
"${request.uri.scheme == 'http'}"
```                                                                                                        | `http://ig.example.com:8080`, . . .                                                                                                                                                                                                                      |
| ```json
"${find(request.uri.path, '^/dispatch') or find(request.uri.path, '^/mylogin')}"
```                                                         | `http://ig.example.com:8080/dispatch`, `http://ig.example.com:8080/mylogin`, . . .                                                                                                                                                                       |
| ```json
"${request.uri.host == 'sp1.example.com' and not find(request.uri.path, '^/saml')}"
```                                                      | `http://sp1.example.com:8080/`, `http://sp1.example.com/mypath`, . . .Not `http://sp1.example.com:8080/saml`, `http://sp1.example.com/saml`, . . .                                                                                                       |
| ```json
"condition": "${find (request.uri.path, '&{uriPath}')}"
```                                                                                  | `http://ig.example.com:8080/hello`, when the following property is configured:```json
{
  "properties": {
    "uriPath": "hello"
  }
}
```For information about including properties in the configuration, refer to [Route properties](Properties.html). |
| ```json
"condition": "${request.headers['X-Forwarded-Host'][0] == 'service.example.com'}"
```                                                        | Requests with the header `X-Forwarded-Host`, whose first value is `service.example.com`.                                                                                                                                                                 |
| ```json
"condition": "#{find(request.uri.path, '^/openam/oauth2/access_token') && request.entity.form['client_id'][0] == 'client-service'}"
```      | Requests where an OAuth 2.0 client named `client-service` issues the original access token request.                                                                                                                                                      |
| ```json
"condition": "#{find(request.uri.path, '^/openam/oauth2/access_token') && request.entity.form['grant_type'][0] == 'client_credentials'}"
``` | Requests using the client credentials grant-type.                                                                                                                                                                                                        |
