# Get processes (errors) by workflow

> GET /v1/workflows/{id}/processes · Workflows API

Source: https://developer.kustomer.com/api/workflows/get-processes-errors-by-workflow

```http
GET https://{orgname}.api.kustomerapp.com/v1/workflows/{id}/processes
Authorization: Bearer <API key>
```

## Authorization

Requires any one of these roles: `org.permission.workflow.read`; or legacy `org.admin.workflow.read`. The API key or user must hold at least one of them. Legacy roles predate permission sets and still work.

Retrieves all of the processes (errors) for a given workflow based on the Workflow ID.

### Workflow process attributes

In the sample response, you will notice that workflow processes (errors) have the following attributes that can help with troubleshooting an error:

- **Event**: the original event that triggered the workflow. This is a raw internal representation of the data before the data is normalized by the workflow trigger.

- **Error**: a stringified version of the error object that describes what went wrong. In some cases, this will say `System Error – Retrying`. 

- **Meta.Context**: contains a stringified version of the workflow context. This includes an `order` array of completed workflow steps and the inputs/outputs at each step.

- **Meta.WorkflowRev**: reflects the revision (`rev`) or version of the workflow that generated the error. This is useful if the workflow has been fixed or has changed since the workflow first generated the error.

## About Workflow processes (errors)

A workflow process is the record Kustomer keeps when a workflow run fails. It stores the event that started the run, the error, and the run's context up to the failure, so you can see what went wrong.

When a [workflow](https://developer.kustomer.com/api/workflows#workflows) run fails, Kustomer records a process for it. These are the same failures admins see under the **Errors** filter on the Workflows page, and the most recent one is also copied to the workflow's `lastError`. Runs that end normally, including runs where no transition matched, don't create a process. Neither do REST steps that get an error status from your service: the step succeeds, and your transitions decide what happens next.

Process records are kept for about a week, then removed. For a longer history, poll this endpoint and store the results yourself.

#### Reading a process

| Attribute | Meaning |
| --- | --- |
| `status` | `failed`. |
| `error` | A JSON string with `message` and `step`, the ID of the step that failed. |
| `event` | The raw event that started the run, before the trigger normalized it into step `1`. |
| `meta.context` | A JSON string of the run's context: `order` lists the steps that ran, and `steps.<id>.output` holds each one's output. Variables are removed. |
| `meta.workflowRev` | The workflow revision that ran. If it's older than the current one, the problem may already be fixed. |
| `createdAt` | When the failure was recorded. |

`error` and `meta.context` are strings, so parse them before reading. Runs that Kustomer retries after a temporary platform problem or a `5xx` from a Kustomer action start again from step 1, so earlier steps run again. The [debugging guide](https://developer.kustomer.com/docs/workflows/debugging) lists the other common messages and their fixes.

#### Which endpoint to use

| To | Call |
| --- | --- |
| List a workflow's failed runs | [`GET /v1/workflows/{id}/processes`](https://developer.kustomer.com/api/workflows/get-processes-errors-by-workflow) |
| See only the latest failure | `lastError` on [`GET /v1/workflows/{id}`](https://developer.kustomer.com/api/workflows/get-a-workflow-based-on-the-id) |

Results are newest first by default (`sort=asc` reverses them) and paginated, 100 per page unless you set `pageSize`; `meta.total` and `meta.totalPages` tell you how many there are. `createdAtFrom` (inclusive) and `createdAtTo` (exclusive) take ISO 8601 dates to narrow the range, which is the easy way to fetch only failures since your last check. To watch a run step by step instead, including runs that didn't fail, open **View Logs** in the workflow builder.

Related: [Debugging and logs](https://developer.kustomer.com/docs/workflows/debugging), [Workflows](https://developer.kustomer.com/api/workflows#workflows), [Workflow JSON](https://developer.kustomer.com/docs/workflows/workflow-json)

### Recipes

#### 1. Alert on new workflow failures

Check every enabled workflow on a schedule and send new failures to your alerting tool, instead of waiting for someone to open the builder.

**Step 1.** [`GET /v1/workflows`](https://developer.kustomer.com/api/workflows/get-workflows.md). List the enabled workflows. Keep each `id` and `name` so the alert can say which workflow failed.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/workflows?enabled=true&pageSize=100" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/workflows --query enabled=true --all \
  | jq -r '[.data.id, .data.attributes.name] | @tsv' > workflows.tsv
```

**Step 2.** [`GET /v1/workflows/{id}/processes`](https://developer.kustomer.com/api/workflows/get-processes-errors-by-workflow.md). For each workflow, ask only for failures since your last check with `createdAtFrom`, an ISO 8601 time that's inclusive. `error` is a JSON string: parse it for `step`, the ID of the step that failed, and `message`.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/workflows/$WORKFLOW_ID/processes?createdAtFrom=$SINCE&pageSize=100" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
while IFS=$'\t' read -r id name; do
  kusty api GET /v1/workflows/$id/processes --query createdAtFrom=$SINCE --all \
    | jq -r --arg name "$name" '.data.attributes | .error as $raw
        | (try ($raw | fromjson) catch {message: $raw}) as $e
        | [.createdAt, $name, $e.step, $e.message] | @tsv'
done < workflows.tsv
```

> Record the time each check starts and use it as the next `$SINCE`, so a failure recorded during a check isn't missed. Failure records are kept for about a week, so check at least daily, and store anything you need longer.

#### 2. See what a failed run was working with

Find the step that failed and the output of every step before it, to reproduce the problem without turning on debug logging.

**Step 1.** [`GET /v1/workflows/{id}/processes`](https://developer.kustomer.com/api/workflows/get-processes-errors-by-workflow.md). Fetch the most recent failure. Results are newest first, so `pageSize=1` is enough.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/workflows/$WORKFLOW_ID/processes?pageSize=1" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/workflows/$WORKFLOW_ID/processes --limit 1 --output json > failure.json
```

**Step 2.** Parse `error` and `meta.context`, which are both JSON strings. `order` lists the steps that ran, ending with the one that failed, and `steps.<id>.output` holds what each step produced. Variable values are removed. `meta.workflowRev` tells you which revision ran; if you've saved the workflow since, check whether newer runs still fail.

```bash title="kusty"
jq -r '.data[0].attributes
  | (.error | fromjson) as $e | (.meta.context | fromjson) as $c
  | "failed at \($e.step): \($e.message)",
    ($c.order[] as $id | "\($id): \($c.steps[$id].output | tojson)")' failure.json
```

### Example object

A real record from [`GET /v1/workflows/{id}/processes`](https://developer.kustomer.com/api/workflows/get-processes-errors-by-workflow.md):

```json
{
  "type": "workflowProcess",
  "id": "5eea124bccb9de001933f317",
  "attributes": {
    "event": {
      "id": "5eea124a9fb3750012781516",
      "name": "kustomer.customer.update",
      "org": "581392b55ac7a2110099d9c8",
      "partition": "581392b55ac7a2110099d9c8",
      "orgName": null,
      "data": {
        "type": "customer",
        "id": "5e83c3a4d95b7e0012dc9711",
        "attributes": {
          "name": null,
          "displayName": "test@test.com",
          "displayColor": "maroon",
          "displayIcon": "sun",
          "externalId": null,
          "externalIds": [],
          "sharedExternalIds": [],
          "signedUpAt": null,
          "avatarUrl": null,
          "username": null,
          "emails": [
            {
              "type": "home",
              "verified": false,
              "email": "test@kustomer.com"
            }
          ],
          "sharedEmails": [],
          "phones": [],
          "sharedPhones": [],
          "smoochIds": [],
          "whatsapps": [],
          "facebookIds": [],
          "instagramIds": [],
          "socials": [],
          "sharedSocials": [],
          "urls": [],
          "locations": [],
          "activeUsers": [],
          "watchers": [],
          "recentLocation": {
            "updatedAt": "2020-03-31T22:26:44.366Z"
          },
          "locale": null,
          "timeZone": null,
          "birthdayAt": null,
          "gender": null,
          "presence": null,
          "createdAt": "2020-03-31T22:26:44.364Z",
          "updatedAt": "2020-06-17T12:53:30.436Z",
          "modifiedAt": "2020-06-11T16:29:37.110Z",
          "lastSeenAt": null,
          "lastActivityAt": "2020-06-17T12:32:16.228Z",
          "lastCustomerActivityAt": "2020-06-17T12:32:16.228Z",
          "deleted": false,
          "deletedAt": null,
          "importedAt": null,
          "lastMessageIn": {
            "sentiment": null,
            "channel": "voice",
            "sentAt": "2020-04-15T02:23:43.906Z"
          },
          "lastMessageOut": null,
          "lastMessageUnrespondedTo": {
            "sentAt": "2020-03-31T22:38:16.123Z",
            "channel": "voice"
          },
          "lastMessageAt": "2020-04-15T02:23:43.906Z",
          "lastConversation": {
            "channels": [
              "voice"
            ],
            "tags": [],
            "id": "5e96fe3395ae63af1838b92d"
          },
          "conversationCounts": {
            "done": 12,
            "open": 0,
            "snoozed": 0,
            "all": 12
          },
          "preview": {
            "subject": "Inbound Call",
            "text": "test",
            "type": "note",
            "previewAt": "2020-06-11T16:29:37.100Z"
          },
          "tags": [],
          "sentiment": null,
          "custom": {
            "someFieldNum": null,
            "someFieldStr": null,
            "testNum": null,
            "textStr": null
          },
          "progressiveStatus": "done",
          "verified": true,
          "rev": 298,
          "recentItems": [],
          "defaultLang": null,
          "satisfactionLevel": {
            "firstSatisfaction": {
              "sentByTeams": []
            },
            "lastSatisfaction": {
              "sentByTeams": []
            }
          },
          "roleGroupVersions": [],
          "accessOverride": [],
          "companyName": null,
          "firstName": null,
          "lastName": null
        },
        "relationships": {
          "messages": {
            "links": {
              "self": "/v1/customers/5e83c3a4d95b7e0012dc9711/messages"
            }
          },
          "createdBy": {
            "links": {
              "self": "/v1/users/581392b55dca541100385c04"
            },
            "data": {
              "type": "user",
              "id": "581392b55dca541100385c04"
            }
          },
          "modifiedBy": {
            "links": {
              "self": "/v1/users/581392b55dca541100385c04"
            },
            "data": {
              "type": "user",
              "id": "581392b55dca541100385c04"
            }
          },
          "deletedBy": null,
          "org": {
            "data": {
              "type": "org",
              "id": "581392b55ac7a2110099d9c8"
            },
            "links": {
              "self": "/v1/orgs/581392b55ac7a2110099d9c8"
            }
          },
          "leads": {
            "links": {
              "self": "/v1/customers/5e83c3a4d95b7e0012dc9711/klasses/leads"
            },
            "meta": {
              "kobject": true
            }
          },
          "hats": {
            "links": {
              "self": "/v1/customers/5e83c3a4d95b7e0012dc9711/klasses/hats"
            },
            "meta": {
              "kobject": true
            }
          }
        },
        "links": {
          "self": "/v1/customers/5e83c3a4d95b7e0012dc9711"
        }
      },
      "createdAt": "2020-06-17T12:53:30.452Z",
      "changes": {
        "attributes": {
          "activeUsers": {
            "op": "replace",
            "before": [],
            "after": [
              "581392b55dca541100385c04"
            ]
          },
          "updatedAt": {
            "op": "replace",
            "before": "2020-06-17T12:32:23.669Z",
            "after": "2020-06-17T12:53:30.436Z"
          },
          "rev": {
            "op": "replace",
            "before": 297,
            "after": 298
          }
        },
        "relationships": {}
      }
    },
    "error": "{\"message\":\"Invalid regular expression: /*/: Nothing to repeat\",\"step\":\"Se73DhAs5\"}",
    "meta": {
      "context": "{\"order\":[\"1\",\"tNG_FZugW\",\"Se73DhAs5\"],\"steps\":{\"1\":{\"name\":\"kustomer.customer.update\",\"createdAt\":\"2020-06-17T12:53:30.689Z\",\"app\":\"kustomer\",\"type\":\"workflow_trigger\",\"version\":\"1.4.5\",\"output\":{\"id\":\"5e83c3a4d95b7e0012dc9711\",\"name\":null…",
      "attempt": 1,
      "retry": false,
      "workflowRev": 27
    },
    "status": "failed",
    "updatedAt": "2020-06-17T12:53:31.043Z",
    "createdAt": "2020-06-17T12:53:30.684Z"
  },
  "relationships": {
    "org": {
      "links": {
        "self": "/v1/orgs/581392b55ac7a2110099d9c8"
      },
      "data": {
        "type": "org",
        "id": "581392b55ac7a2110099d9c8"
      }
    },
    "workflowRunner": {
      "data": {
        "type": "workflowRunner",
        "id": "5ee9ec781fb3f0ce1bfe4d6d"
      }
    },
    "workflow": {
      "data": {
        "type": "workflow",
        "id": "5b84680f6a3d70001b4c7183"
      }
    }
  },
  "links": {
    "self": "/v1/workflowsProcesses/5eea124bccb9de001933f317"
  }
}
```

Fields:

- `attributes.event` (object): The raw event that started the run, before the trigger shaped it into step `1`. Its contents depend on the trigger.
- `attributes.event.name` (string): The event's name, which matches the workflow's `trigger.eventName`.
- `attributes.event.data` (object): The record the event is about, as it was when the event happened.
- `attributes.event.changes` (object): For update events, the attributes that changed, each with `before` and `after`. Workflow conditions read them as `/#steps.1.changes.attributes.<attribute>.after`.
- `attributes.error` (string): A JSON string. Parse it for `message` and `step`, the ID of the step that failed.
- `attributes.meta.context` (string): A JSON string of the run up to the failure: `order` lists the step IDs that ran, ending with the failed one, and `steps.<id>.output` holds each step's output. Variable values are removed.
- `attributes.meta.attempt` (integer): How many times Kustomer had tried to run the workflow for this event, starting at `1`.
- `attributes.meta.retry` (boolean): `false` for the failures recorded here: Kustomer doesn't run the workflow again for them, so fix the cause and the next event runs normally.
- `attributes.meta.workflowRev` (integer): The workflow revision that ran. If the workflow has been saved since, the failure may already be fixed.
- `attributes.status` (string): Always `failed`. Runs that end normally aren't recorded.
- `attributes.createdAt` (string): When the failure was recorded. Filter on it with `createdAtFrom` (inclusive) and `createdAtTo` (exclusive). Records are deleted after about a week.
- `relationships.workflow` (object): The workflow whose run failed.

### Relationships

- Points to **Workflows** via `relationships.workflow`: The workflow whose run failed. Each workflow keeps about a week of failed runs, newest first, and copies the latest one to its `lastError`.

### Permissions

Fewest roles for a read-only integration: `org.permission.workflow.read`. For every endpoint: `org.permission.workflow.read`.

## Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | Workflow ID |

## Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `createdAtFrom` | string<date-time> | no | Date to filter results with a createdAt greater than or equal to date time in ISO 8601 format |
| `createdAtTo` | string<date-time> | no | Date to filter results with a createdAt less than date time in ISO 8601 format |
| `page` | number | no | Number of pages to return for results. Default value: 1. |
| `pageSize` | number | no | Number of results to return per page. Default value: 100. |
| `sort` | string | no | Sort order by `createdAt`. Defaults to `desc` (newest first). |

## Responses

### 200

OK

- `meta` (object, required)
  - `pageSize` (integer, required)
  - `page` (integer, required)
  - `total` (integer, required)
  - `totalPages` (integer, required)
- `links` (object, required)
  - `self` (string, required)
  - `first` (string, required)
  - `prev` (string, required, nullable)
  - `next` (string, required)
  - `last` (string, required)
- `data` (array<object>, required)
  - `type` (string, required)
  - `id` (string, required)
  - `attributes` (object, required)
    - `event` (object, required)
    - `error` (string, required)
    - `meta` (object, required)
    - `status` (string, required)
    - `updatedAt` (string, required)
    - `createdAt` (string, required)
  - `relationships` (object, required)
    - `org` (object, required)
    - `workflowRunner` (object, required)
    - `workflow` (object, required)
  - `links` (object, required)
    - `self` (string, required)

```json
{
  "meta": {
    "pageSize": 10,
    "page": 1,
    "total": 1,
    "totalPages": 1
  },
  "links": {
    "self": "/v1/workflows/5b84680f6a3d70001b4c7183/processes?page=1&pageSize=10",
    "first": "/v1/workflows/5b84680f6a3d70001b4c7183/processes?page=1&pageSize=10",
    "prev": null,
    "next": "/v1/workflows/5b84680f6a3d70001b4c7183/processes?page=2&pageSize=10",
    "last": "/v1/workflows/5b84680f6a3d70001b4c7183/processes?page=2&pageSize=10"
  },
  "data": [
    {
      "type": "workflowProcess",
      "id": "5eea124bccb9de001933f317",
      "attributes": {
        "event": {
          "id": "5eea124a9fb3750012781516",
          "name": "kustomer.customer.update",
          "org": "581392b55ac7a2110099d9c8",
          "partition": "581392b55ac7a2110099d9c8",
          "orgName": null,
          "data": {
            "type": "customer",
            "id": "5e83c3a4d95b7e0012dc9711",
            "attributes": {
              "name": null,
              "displayName": "test@test.com",
              "displayColor": "maroon",
              "displayIcon": "sun",
              "externalId": null,
              "externalIds": [],
              "sharedExternalIds": [],
              "signedUpAt": null,
              "avatarUrl": null,
              "username": null,
              "emails": [
                {
                  "type": "home",
                  "verified": false,
                  "email": "test@kustomer.com"
                }
              ],
              "sharedEmails": [],
              "phones": [],
              "sharedPhones": [],
              "smoochIds": [],
              "whatsapps": [],
              "facebookIds": [],
              "instagramIds": [],
              "socials": [],
              "sharedSocials": [],
              "urls": [],
              "locations": [],
              "activeUsers": [],
              "watchers": [],
              "recentLocation": {
                "updatedAt": "2020-03-31T22:26:44.366Z"
              },
              "locale": null,
              "timeZone": null,
              "birthdayAt": null,
              "gender": null,
              "presence": null,
              "createdAt": "2020-03-31T22:26:44.364Z",
              "updatedAt": "2020-06-17T12:53:30.436Z",
              "modifiedAt": "2020-06-11T16:29:37.110Z",
              "lastSeenAt": null,
              "lastActivityAt": "2020-06-17T12:32:16.228Z",
              "lastCustomerActivityAt": "2020-06-17T12:32:16.228Z",
              "deleted": false,
              "deletedAt": null,
              "importedAt": null,
              "lastMessageIn": {
                "sentiment": null,
                "channel": "voice",
                "sentAt": "2020-04-15T02:23:43.906Z"
              },
              "lastMessageOut": null,
              "lastMessageUnrespondedTo": {
                "sentAt": "2020-03-31T22:38:16.123Z",
                "channel": "voice"
              },
              "lastMessageAt": "2020-04-15T02:23:43.906Z",
              "lastConversation": {
                "channels": [
                  "voice"
                ],
                "tags": [],
                "id": "5e96fe3395ae63af1838b92d"
              },
              "conversationCounts": {
                "done": 12,
                "open": 0,
                "snoozed": 0,
                "all": 12
              },
              "preview": {
                "subject": "Inbound Call",
                "text": "test",
                "type": "note",
                "previewAt": "2020-06-11T16:29:37.100Z"
              },
              "tags": [],
              "sentiment": null,
              "custom": {
                "someFieldNum": null,
                "someFieldStr": null,
                "testNum": null,
                "textStr": null
              },
              "progressiveStatus": "done",
              "verified": true,
              "rev": 298,
              "recentItems": [],
              "defaultLang": null,
              "satisfactionLevel": {
                "firstSatisfaction": {
                  "sentByTeams": []
                },
                "lastSatisfaction": {
                  "sentByTeams": []
                }
              },
              "roleGroupVersions": [],
              "accessOverride": [],
              "companyName": null,
              "firstName": null,
              "lastName": null
            },
            "relationships": {
              "messages": {
                "links": {
                  "self": "/v1/customers/5e83c3a4d95b7e0012dc9711/messages"
                }
              },
              "createdBy": {
                "links": {
                  "self": "/v1/users/581392b55dca541100385c04"
                },
                "data": {
                  "type": "user",
                  "id": "581392b55dca541100385c04"
                }
              },
              "modifiedBy": {
                "links": {
                  "self": "/v1/users/581392b55dca541100385c04"
                },
                "data": {
                  "type": "user",
                  "id": "581392b55dca541100385c04"
                }
              },
              "deletedBy": null,
              "org": {
                "data": {
                  "type": "org",
                  "id": "581392b55ac7a2110099d9c8"
                },
                "links": {
                  "self": "/v1/orgs/581392b55ac7a2110099d9c8"
                }
              },
              "leads": {
                "links": {
                  "self": "/v1/customers/5e83c3a4d95b7e0012dc9711/klasses/leads"
                },
                "meta": {
                  "kobject": true
                }
              },
              "hats": {
                "links": {
                  "self": "/v1/customers/5e83c3a4d95b7e0012dc9711/klasses/hats"
                },
                "meta": {
                  "kobject": true
                }
              }
            },
            "links": {
              "self": "/v1/customers/5e83c3a4d95b7e0012dc9711"
            }
          },
          "createdAt": "2020-06-17T12:53:30.452Z",
          "changes": {
            "attributes": {
              "activeUsers": {
                "op": "replace",
                "before": [],
                "after": [
                  "581392b55dca541100385c04"
                ]
              },
              "updatedAt": {
                "op": "replace",
                "before": "2020-06-17T12:32:23.669Z",
                "after": "2020-06-17T12:53:30.436Z"
              },
              "rev": {
                "op": "replace",
                "before": 297,
                "after": 298
              }
            },
            "relationships": {}
          }
        },
        "error": "{\"message\":\"Invalid regular expression: /*/: Nothing to repeat\",\"step\":\"Se73DhAs5\"}",
        "meta": {
          "context": "{\"order\":[\"1\",\"tNG_FZugW\",\"Se73DhAs5\"],\"steps\":{\"1\":{\"name\":\"kustomer.customer.update\",\"createdAt\":\"2020-06-17T12:53:30.689Z\",\"app\":\"kustomer\",\"type\":\"workflow_trigger\",\"version\":\"1.4.5\",\"output\":{\"id\":\"5e83c3a4d95b7e0012dc9711\",\"name\":null…",
          "attempt": 1,
          "retry": false,
          "workflowRev": 27
        },
        "status": "failed",
        "updatedAt": "2020-06-17T12:53:31.043Z",
        "createdAt": "2020-06-17T12:53:30.684Z"
      },
      "relationships": {
        "org": {
          "links": {
            "self": "/v1/orgs/581392b55ac7a2110099d9c8"
          },
          "data": {
            "type": "org",
            "id": "581392b55ac7a2110099d9c8"
          }
        },
        "workflowRunner": {
          "data": {
            "type": "workflowRunner",
            "id": "5ee9ec781fb3f0ce1bfe4d6d"
          }
        },
        "workflow": {
          "data": {
            "type": "workflow",
            "id": "5b84680f6a3d70001b4c7183"
          }
        }
      },
      "links": {
        "self": "/v1/workflowsProcesses/5eea124bccb9de001933f317"
      }
    }
  ]
}
```

### 401

Unauthorized. Missing or invalid bearer token.

### 403

Forbidden. The authenticated user does not have permission to view workflow processes.

### 404

Not Found. No workflow found with the given ID.

## Example request

```bash
curl --request GET \
  --url 'https://api.kustomerapp.com/v1/workflows/5b84680f6a3d70001b4c7183/processes' \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```
