---
title: NerdGraph tutorial: Create and manage Pathpoint flows
source: https://docs.newrelic.com/docs/apis/nerdgraph/examples/nerdgraph-pathpoint-flows
---

> #### 💡 PREVIEW
>
> We're still working on this feature, but we'd love for you to try it out!
>
> This feature is currently provided as part of a preview program pursuant to our [pre-release policies](https://docs.newrelic.com/docs/licenses/license-information/referenced-policies/new-relic-pre-release-policy).

You can use [our NerdGraph API](https://docs.newrelic.com/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph) to create and manage Pathpoint flows programmatically, instead of building them in the UI.

A flow represents one business journey, such as checkout, authentication, or onboarding. It's the unit you create and manage through the API. Flows are [entities](https://docs.newrelic.com/docs/new-relic-solutions/new-relic-one/core-concepts/what-entity-new-relic), so each one has an entity GUID you use to read, update, or delete it.

Every flow follows a four-tier hierarchy, with KPIs attached at the flow level, the stage level, or both:

```
Flow
├── Flow KPIs
└── Stages
    ├── Stage KPIs
    └── Levels
        └── Steps
            └── Signals (entity GUIDs, alert condition GUIDs, or a dynamic query)
```

For an introduction to Pathpoint itself, see [Get started with Pathpoint](https://docs.newrelic.com/docs/pathpoint/get-started-pathpoint).

## Before you begin [#requirements]

You need:

-   Pathpoint enabled on your account.
-   A New Relic user key to authenticate your requests.
-   Your [account ID](https://docs.newrelic.com/docs/accounts/accounts-billing/account-structure/account-id).

## Flow operations [#crud-operations]

To run these examples interactively, open the [NerdGraph GraphiQL explorer](https://api.newrelic.com/graphiql) and search the schema for `pathPoint`. Before running an example, replace its placeholders with your own values: `YOUR_ACCOUNT_ID`, `TARGET_ACCOUNT_ID`, `FLOW_GUID`, `SOURCE_FLOW_GUID`, `ENTITY_GUID`, `ANOTHER_ENTITY_GUID`, `ENTITY_NAME`, `ALERT_CONDITION_GUID`, and the stage, level, and step IDs.

### Create a flow [#create-flow]

Create a flow by passing its nested stages, levels, steps, and signals in a single mutation.

**Create a flow with three steps**

This creates a "Checkout flow" with one stage, "Frontend," containing three steps. "Login page" matches entities with a dynamic query, "Cart service" pins one specific entity by GUID, and "Checkout errors" pins an alert condition.

````graphql
mutation {
  pathPointCreate(
    scope: { id: YOUR_ACCOUNT_ID, type: ACCOUNT }
    pathpoint: {
      name: "Checkout flow"
      description: "End-to-end checkout journey"
      category: "E-Commerce"
      refreshInterval: FIVE_MINUTES
      stages: [
        {
          name: "Frontend"
          healthRollup: AUTOMATIC_ROLL_UP
          levels: [
            {
              steps: [
                {
                  name: "Login page"
                  entitySearchQuery: {
                    query: "domain = 'BROWSER' AND type = 'APPLICATION' AND name = 'Login'"
                  }
                }
                {
                  name: "Cart service"
                  signals: [
                    { guid: "ENTITY_GUID", name: "Cart service", type: ENTITY }
                  ]
                }
                {
                  name: "Checkout errors"
                  signals: [
                    {
                      guid: "ALERT_CONDITION_GUID"
                      name: "Checkout error rate"
                      type: ALERT
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ) {
    guid
    name
    version
    message
    excludedKpis
    stages {
      totalCount
      items {
        id
        name
        levels {
          items {
            id
            steps {
              items {
                id
                name
              }
            }
          }
        }
      }
    }
  }
}
```

````

**Create a flow with KPIs**

KPIs at the top level apply to the whole flow. KPIs inside a stage (`stageKpis`) apply to that stage only. Both use the same schema.

Each KPI's `timeWindow` takes either a `relativeRange` built from fixed durations or a `customRange` holding a raw NRQL time expression, not both.

````graphql
mutation {
  pathPointCreate(
    scope: { id: YOUR_ACCOUNT_ID, type: ACCOUNT }
    pathpoint: {
      name: "Checkout flow"
      refreshInterval: FIVE_MINUTES
      kpis: [
        {
          name: "Order success rate"
          category: "Revenue"
          description: "Orders completed successfully"
          query: {
            from: "Transaction"
            where: "transactionType = 'Web' AND name = 'checkout'"
            select: { aggregationType: COUNT, alias: "orders" }
            timeWindow: {
              relativeRange: { since: TWENTY_FOUR_HOURS, compareAgainst: SEVEN_DAYS }
            }
          }
        }
      ]
      stages: [
        {
          name: "Payment"
          stageKpis: [
            {
              name: "Payment errors"
              category: "Reliability"
              query: {
                from: "TransactionError"
                select: { aggregationType: COUNT, alias: "errors" }
                timeWindow: { customRange: "SINCE 30 minutes ago" }
              }
            }
          ]
          levels: [
            {
              steps: [
                {
                  name: "Payment gateway"
                  config: {
                    healthRollup: WORST_STATUS_WINS
                    thresholdType: FIXED
                    thresholdValue: 1
                  }
                  entitySearchQuery: {
                    query: "domain = 'APM' AND name = 'PaymentGateway'"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ) {
    guid
    name
    version
    excludedKpis
    kpis {
      id
      name
      category
      query {
        from
        where
        select {
          aggregationType
          attribute
          alias
        }
        timeWindow {
          customRange
          relativeRange {
            since
            compareAgainst
          }
        }
      }
    }
  }
}
```

````

**Health rollup calculation**

A flow and each of its stages calculate health in one of two ways, which you set with a `healthRollup` field at that level.

At the flow level, `healthRollup` controls how the flow's overall health is derived:

-   **Automatic rollup** (`AUTOMATIC_ROLL_UP`, the default): Health rolls up automatically from the flow's stages. Set `isExcluded: true` on a stage to leave it out of the flow's overall health. That stage's own levels, steps, and signals are still evaluated and still appear in the UI. The stage just stops affecting the flow's status, which is useful for stages under construction or temporarily out of scope. `isExcluded: false`, the default, means the stage participates normally.
-   **Alert conditions** (`ALERT_CONDITIONS`): Health comes from the alert conditions on the flow's KPIs instead of from stage rollup. Pair it with flow-level `kpis`.

    The same two methods apply at the stage level, set with a `healthRollup` field on the stage itself. `AUTOMATIC_ROLL_UP` rolls up from that stage's levels, through their steps and signals; set `isExcluded: true` on a step, signal, or `entitySearchQuery` to leave it out of that calculation. `ALERT_CONDITIONS` ties the stage's health to one of its own KPIs (`stageKpis`) instead, which suits a stage whose status should reflect a business outcome rather than step and signal telemetry, such as an email open rate KPI on a marketing campaigns stage.

    The flow-level and stage-level settings are independent, so a flow can use one method while its stages use the other.

    This example creates a "Checkout flow" that uses `AUTOMATIC_ROLL_UP` for its own overall health, with two stages. "Revenue" uses `ALERT_CONDITIONS` tied to a "Payment errors" KPI, and "Frontend" uses `AUTOMATIC_ROLL_UP` while excluding one signal from health.

    ```graphql
    mutation {
      pathPointCreate(
        scope: { id: YOUR_ACCOUNT_ID, type: ACCOUNT }
        pathpoint: {
          name: "Checkout flow"
          description: "End-to-end checkout pipeline"
          refreshInterval: FIVE_MINUTES
          healthRollup: AUTOMATIC_ROLL_UP
          stages: [
            {
              name: "Revenue"
              healthRollup: ALERT_CONDITIONS
              related: { source: false, target: true }
              stageKpis: [
                {
                  name: "Payment errors"
                  category: "Reliability"
                  query: {
                    from: "TransactionError"
                    select: { aggregationType: COUNT, alias: "errors" }
                  }
                }
              ]
              levels: [
                {
                  steps: [
                    {
                      name: "Order service"
                      config: { healthRollup: WORST_STATUS_WINS }
                      entitySearchQuery: {
                        query: "domain = 'APM' AND name = 'OrderService'"
                      }
                    }
                  ]
                }
              ]
            }
            {
              name: "Frontend"
              healthRollup: AUTOMATIC_ROLL_UP
              related: { source: true, target: false }
              levels: [
                {
                  steps: [
                    {
                      name: "Login page"
                      config: {
                        healthRollup: WORST_STATUS_WINS
                        thresholdType: FIXED
                        thresholdValue: 1
                      }
                      entitySearchQuery: {
                        query: "domain = 'BROWSER' AND name = 'Login'"
                      }
                      signals: [
                        {
                          guid: "ENTITY_GUID"
                          name: "ENTITY_NAME"
                          type: ENTITY
                          isExcluded: true
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ) {
        guid
        name
        message
      }
    }
    ```

`pathPointCreate` requires the account `scope`. Within the payload, only `name` is required. Everything else, including `stages`, is optional. A step gets its signals in one of three ways, and you can combine them:

-   **A dynamic query** (`entitySearchQuery`): Whatever entities match the query, re-evaluated at each refresh.
-   **A pinned entity** (`type: ENTITY`): One specific entity, identified by its GUID.
-   **A pinned alert condition** (`type: ALERT`): One alert condition, identified by its GUID.

The `type` field is optional. The GUID is enough to identify the signal.

Stages also take an optional `related` block that controls how the UI draws the connector arrows between them, independent of health rollup. Set `source: true` if a stage should show an incoming arrow from the stage before it, and `target: true` if it should show an outgoing arrow to the stage after it. In a flow where every stage connects to the next in sequence, the first stage is `source: false, target: true`, the last is `source: true, target: false`, and every stage in between is `true` for both.

> #### ⚠️ IMPORTANT
>
> A KPI's `accountId` defaults to the flow's account. If you set it to a different account, the KPI isn't created and no error comes back. Check the `excludedKpis` field in the response to see which KPIs the mutation skipped.

### Read a flow [#read-flow]

Read a flow by its entity GUID to get its full configuration plus the current health status of the flow, each stage, each level, and each step. `healthStatus` appears only on reads.

Stages, levels, and steps return 50 items per page. When a `nextCursor` comes back non-null, pass it to fetch the next page.

```graphql
{
  actor {
    account(id: YOUR_ACCOUNT_ID) {
      pathPoint {
        flow(guid: "FLOW_GUID") {
          guid
          name
          description
          category
          refreshInterval
          healthRollup
          healthStatus
          version
          message
          kpis {
            id
            name
            category
            accountId
            query {
              from
              where
              select {
                aggregationType
                attribute
                alias
                threshold
              }
              timeWindow {
                customRange
                relativeRange {
                  since
                  compareAgainst
                }
              }
            }
            metricQuery
          }
          stages {
            totalCount
            nextCursor
            items {
              id
              name
              link
              healthRollup
              healthStatus
              isExcluded
              related {
                source
                target
              }
              levels {
                totalCount
                nextCursor
                items {
                  id
                  healthStatus
                  steps {
                    totalCount
                    nextCursor
                    items {
                      id
                      name
                      healthStatus
                      isExcluded
                      scopedAccounts
                      config {
                        healthRollup
                        thresholdType
                        thresholdValue
                      }
                      entitySearchQuery {
                        query
                        isExcluded
                      }
                      signals {
                        guid
                        name
                        type
                        isExcluded
                      }
                    }
                  }
                }
              }
            }
          }
          metadata {
            createdAt
            createdBy {
              name
              email
            }
            updatedAt
            updatedBy {
              name
              email
            }
          }
        }
      }
    }
  }
}
```

Request fewer fields if you don't need the whole tree. Reading just `name` and `healthStatus`, for example, is enough to poll a flow's status.

### Update a flow [#update-flow]

`pathPointUpdate` is a diff-based operation. It compares the payload you send against the flow's current state and acts on each stage, level, step, and KPI according to whether you included its ID:

-   **ID included**: Updates the existing object.
-   **ID omitted**: Creates a new object.
-   **Object left out of the payload entirely**: Deletes it from the flow.

> #### ⚠️ CAUTION
>
> Because omission means deletion, always [read the flow](#read-flow) first, modify the payload you get back, and send the complete intended state. Sending a partial payload deletes everything you left out.
>
> The `version` field is also required. It's the flow's last-updated timestamp in epoch milliseconds, used for optimistic concurrency control. Omitting it or sending a stale value causes the update to fail.

**Add a step while keeping existing objects**

The first step carries its `id`, so it updates in place. The second has no `id`, so it's created as new.

````graphql
mutation {
  pathPointUpdate(
    guid: "FLOW_GUID"
    pathpoint: {
      name: "Checkout flow"
      refreshInterval: FIVE_MINUTES
      version: 1786624914316
      stages: [
        {
          id: "STAGE_ID"
          name: "Frontend"
          healthRollup: AUTOMATIC_ROLL_UP
          levels: [
            {
              id: "LEVEL_ID"
              steps: [
                {
                  id: "STEP_ID"
                  name: "Cart service"
                  signals: [
                    { guid: "ENTITY_GUID", name: "Cart service", type: ENTITY }
                  ]
                }
                {
                  name: "Recommendation service"
                  signals: [
                    { guid: "ANOTHER_ENTITY_GUID", name: "Recommendation service", type: ENTITY }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ) {
    guid
    name
    version
    message
    stages {
      totalCount
      items {
        id
        name
        levels {
          items {
            id
            steps {
              items {
                id
                name
              }
            }
          }
        }
      }
    }
  }
}
```

````

### Duplicate a flow [#duplicate-flow]

You can duplicate either the structure alone or the whole flow:

-   `STRUCTURE`: Copies stages, levels, and steps only, without signals or KPIs.
-   `WHOLE_FLOW`: Copies the structure along with its signals and KPIs.

Any property you set in the input overrides the source flow's value. Omit a property to inherit it.

**Duplicate a whole flow in the same account**

To duplicate within the same account, you don't need a `scope` argument. Set `duplicateType: WHOLE_FLOW`.

````graphql
mutation {
  pathPointDuplicate(
    sourceGuid: "SOURCE_FLOW_GUID"
    pathpoint: {
      name: "Checkout flow (copy)"
      category: "E-Commerce"
      refreshInterval: TEN_MINUTES
      duplicateType: WHOLE_FLOW
    }
  ) {
    guid
    name
  }
}
```

````

**Duplicate a whole flow into another account**

To copy a flow into a different account, add a `scope` and set its `id` to the target account. Omit `scope` to duplicate within the source account.

Duplicating into another account copies only stages, levels, steps, and signals, not KPIs.

````graphql
mutation {
  pathPointDuplicate(
    sourceGuid: "SOURCE_FLOW_GUID"
    scope: { id: TARGET_ACCOUNT_ID, type: ACCOUNT }
    pathpoint: { name: "Checkout flow", duplicateType: WHOLE_FLOW }
  ) {
    guid
    name
  }
}
```

````

**Duplicate a flow's structure**

Set `duplicateType: STRUCTURE` to copy only the flow's shape, without its signals or KPIs.

````graphql
mutation {
  pathPointDuplicate(
    sourceGuid: "SOURCE_FLOW_GUID"
    pathpoint: {
      name: "Checkout flow (copy)"
      category: "E-Commerce"
      refreshInterval: TEN_MINUTES
      duplicateType: STRUCTURE
    }
  ) {
    guid
    name
  }
}
```

````

### Delete a flow [#delete-flow]

Deleting a flow cascades: it removes the flow along with all its stages, levels, steps, and KPIs. The signals themselves, the entities and alert conditions the flow pointed at, stay in your account.

> #### ⚠️ CAUTION
>
> Deleting a flow is permanent.

```graphql
mutation {
  pathPointDelete(guid: "FLOW_GUID") {
    guid
    name
  }
}
```

## Partial failures [#partial-failures]

A create or update can succeed overall while individual objects fail. Two fields in the response tell you when that happened:

-   `message`: Details of any stages, levels, or steps that failed. It's `null` when everything succeeded.
-   `excludedKpis`: The names of KPIs that weren't created, most commonly because the KPI's `accountId` didn't match the flow's account.

Request both fields in your mutations so you don't treat a partial success as a complete one.

## Limits [#limits]

The following limits apply to every flow, whether you build it through the API or in the UI:

| Limit                           | Value |
| ------------------------------- | ----- |
| Maximum stages per flow         | 50    |
| Maximum levels per stage        | 50    |
| Maximum steps per level         | 50    |
| Maximum items returned per page | 50    |

## Type reference [#type-reference]

These enums appear in the operations above. Each row lists the accepted values, followed by what they control:

| Enum                                                      | Values                                                                                                                                                                       |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PathPointRefreshInterval`                                | `ONE_MINUTE`, `FIVE_MINUTES`, `TEN_MINUTES`, `FIFTEEN_MINUTES`, `THIRTY_MINUTES`. How often flow, stage, level, and step health refresh.                                     |
| `PathPointFlowHealthRollup`, `PathPointStageHealthRollup` | `AUTOMATIC_ROLL_UP`, `ALERT_CONDITIONS`. Whether health rolls up from child objects, or comes from the worst alert condition across the flow's or stage's KPIs.              |
| `PathPointStepHealthRollup`                               | `WORST_STATUS_WINS`, `BEST_STATUS_WINS`. Whether the step takes its least healthy signal or its healthiest.                                                                  |
| `PathPointThresholdType`                                  | `FIXED`, `PERCENTAGE`. Whether `thresholdValue` is an absolute count or a percentage of signals.                                                                             |
| `PathPointStatusValue`                                    | `OPERATIONAL`, `DEGRADED`, `DISRUPTED`, `UNKNOWN`. Computed health, returned on reads.                                                                                       |
| `PathPointSignalType`                                     | `ENTITY`, `ALERT`. Whether the GUID points to a monitored entity, such as an APM service or host, or to an alert condition.                                                  |
| `PathPointKpiNrqlAggregations`                            | `COUNT`, `SUM`, `AVERAGE`, `MAX`, `MIN`, `UNIQUE_COUNT`, `PERCENTILE`, `HISTOGRAM`. The aggregation a KPI query applies. Every function except `COUNT` needs an `attribute`. |
| `PathPointKpiTimeDuration`                                | `THIRTY_MINUTES`, `SIXTY_MINUTES`, `THREE_HOURS`, `SIX_HOURS`, `TWENTY_FOUR_HOURS`, `SEVEN_DAYS`, `THIRTY_DAYS`. Durations for a KPI's `since` and `compareAgainst`.         |
| `PathPointDuplicateType`                                  | `STRUCTURE`, `WHOLE_FLOW`. Whether to copy stages, levels, and steps only, or the structure along with its signals and KPIs.                                                 |

## Related topics [#related-topics]

[Get started with Pathpoint](https://docs.newrelic.com/docs/pathpoint/get-started-pathpoint)

Learn what Pathpoint is and how to access it.

[Create and manage flows](https://docs.newrelic.com/docs/pathpoint/create-manage-flows)

Build and configure flows in the UI.

[Introduction to NerdGraph](https://docs.newrelic.com/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph)

Learn how to use New Relic's GraphQL API.
