# Get Workflow Log Statistics

GET https://services.leadconnectorhq.com/workflows/{workflowId}/logs/aggregate

**Limited availability.** The workflow API is currently enabled for selected sub-accounts only; any other sub-account receives 403 `WORKFLOW_API_NOT_ENABLED_FOR_LOCATION`.

Count the log records of one workflow, grouped by one or more dimensions. It answers how many: enrollments, completions, failures per step, why contacts left, and trends over time. To answer who, use Get Workflow Logs.

**Before you call it.** Get `workflowId` from Search Workflows. Never pass a workflow name.

**Grouping.** Each row holds one value for every dimension in `groupBy`, plus `count`. Grouping by `week`, `day` or `hour` adds `bucket`, the start of each interval in `timezone`. `startDate` and `endDate` always stay UTC. Rows are sorted by the grouped values in ascending order (`status`, then `type`, `stepId`, `removedReason` and `bucket`), not by count.

**Finding filter values.** Group by a dimension to see which values this workflow has, then filter on them. For example, `groupBy=removedReason` lists the reasons present, and those values work in `removedReasons`.

**Steps.** Rows grouped by `stepId` also carry `stepName`, the name of that step on its most recent log record in the date range. `stepId` matches `actions[].id` in Get Workflow Definition. A step count includes the `remove_from_workflow` record written when a contact leaves the workflow at that step, so group by `stepId` and `type` together to count how often the step itself ran.

**Common questions.**
- Enrollments: `statuses=added_to_workflow`
- Completions: `removedReasons=end_of_workflow`. Divide by enrollments for a completion rate
- Failures per step: `statuses=error,failed,failed_retry_limit_reached&groupBy=stepId`
- Why contacts left: `types=remove_from_workflow&groupBy=removedReason`
- Stopped because the contact replied: `removedReasons=contact_reply_stop_response`
- Goal reached: `types=workflow_goal&statuses=success`
- Enrollment trend: `statuses=added_to_workflow&groupBy=week` (or `day`)
- Change over time: call twice with back-to-back windows of equal length and compare

Completions in a window can include contacts who enrolled before it, so a completion rate can exceed 100%. With fewer than about 30 enrollments, rates swing widely. Zero is a real answer. A `workflowId` that does not exist in the sub-account returns 404.

**Limits.** The range defaults to the last 30 days and must not exceed 30 days. Logs are available for the last 60 days. A grouping that produces more rows than `limit` is refused with 422 rather than truncated, because a truncated count reports wrong totals.

**Compatibility.** New optional fields and new values of `status`, `type` and `removedReason` can appear at any time. Ignore fields you do not know, and treat an unknown value as other.

## Authentication

Send `Authorization: Bearer <token>` using:

- **Sub-Account token: OAuth access token or Private Integration Token.** Scopes: `workflows.logs`

## Parameters

### Header Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `Version` | string | Yes | API Version. Send `v3`. |

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `workflowId` | string | Yes | Workflow ID. Get it from Search Workflows. Never pass a workflow name |

### Query Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `locationId` | string | Yes | Sub-account (location) ID. It must be the sub-account the token belongs to, otherwise the request is refused with 403 |
| `startDate` | string | No | Start of the range, ISO 8601: a plain date (start of that day, UTC) or a full timestamp. Send it together with endDate. Defaults to 30 days ago. Logs are available for the last 60 days, so it cannot be earlier than that |
| `endDate` | string | No | End of the range, ISO 8601. A plain date includes the whole day. At most 30 days after startDate. Defaults to now |
| `groupBy` | array | No | Dimensions to group the counts by. Repeat the parameter or send a comma-separated list. `status` is the step outcome, `type` the step type, `stepId` the step, `removedReason` why the contact left the workflow, and `week`, `day` or `hour` a time bucket (one at most). Defaults to `status` |
| `statuses` | array | No | Count only these step outcomes. Values: `added_to_workflow` (the contact entered the workflow), `success` (the step ran), `error` and `failed` (the step did not complete), `failed_retry_limit_reached` (the step gave up after its retries), `retry` (the step will run again), `skipped` (the step did not run, for example because of DND, a time window or missing data), `waiting` (the contact is waiting at the step), `wait_finished` (a wait ended), `finished` (the contact left the workflow, see removedReason), `paused_due_to_draft_mode` (the workflow was unpublished while the contact was in it), `contact_merged` (the contact was merged into another contact), `drip_queued` (the contact is waiting in a drip step for its batch), `drip_resume` (the batch was released and the contact moved on), `processing` (the step has started and has not finished yet), and `winner_declared` (an A/B test step picked its winning path; the record has no contact). New values can appear. Group by `status` first to see the values this workflow has |
| `types` | array | No | Count only these step types: a step `type` key, as listed by Get Step Types or in `actions[].type` of Get Workflow Definition. Unlike Get Workflow Logs, `if_else` and `drip` match only those exact keys here. New values can appear. Group by `type` first to see the types this workflow has |
| `removedReasons` | array | No | Count only records removed for these reasons. Values: `end_of_workflow` (the contact reached the end), `contact_deleted` (the contact was deleted), `deleted_workflow` (the workflow was deleted), `record_deleted` (the record was deleted), `goal_action` (a goal step removed the contact), `contact_reply_stop_response` (the contact replied and the workflow stops on reply), `contact_merge` (the contact was merged), `appointment-change`, `invoice-change` and `service-booking-change` (the appointment, invoice or booking changed and the workflow restarted for the contact), `attendee-change` (the Events attendee or their event changed, and the run for that attendee ended), `rental-booking-change` (the rental booking that started the workflow was deleted or cancelled), `wait_step_window_in_past` (a wait step time window pointed to a time in the past, so the contact left), and `missing-data` (the step the contact was on was deleted from the workflow). Values are exact, including the ones with hyphens. New values can appear. Group by `removedReason` first to see the values this workflow has |
| `timezone` | string | No | IANA timezone for the week, day and hour buckets. It does not move startDate and endDate, which stay UTC. Defaults to UTC |
| `limit` | number | No | Maximum number of grouped rows. A grouping that produces more is refused with 422 rather than truncated. Default 1000, maximum 5000 |

## OpenAPI Specification

```json
{
  "openapi": "3.0.0",
  "info": {
    "title": "LeadConnector API",
    "version": "v3"
  },
  "servers": [
    {
      "url": "https://services.leadconnectorhq.com"
    }
  ],
  "paths": {
    "/workflows/{workflowId}/logs/aggregate": {
      "get": {
        "summary": "Get Workflow Log Statistics",
        "operationId": "getWorkflowLogStatistics",
        "description": "**Limited availability.** The workflow API is currently enabled for selected sub-accounts only; any other sub-account receives 403 `WORKFLOW_API_NOT_ENABLED_FOR_LOCATION`.\n\nCount the log records of one workflow, grouped by one or more dimensions. It answers how many: enrollments, completions, failures per step, why contacts left, and trends over time. To answer who, use Get Workflow Logs.\n\n**Before you call it.** Get `workflowId` from Search Workflows. Never pass a workflow name.\n\n**Grouping.** Each row holds one value for every dimension in `groupBy`, plus `count`. Grouping by `week`, `day` or `hour` adds `bucket`, the start of each interval in `timezone`. `startDate` and `endDate` always stay UTC. Rows are sorted by the grouped values in ascending order (`status`, then `type`, `stepId`, `removedReason` and `bucket`), not by count.\n\n**Finding filter values.** Group by a dimension to see which values this workflow has, then filter on them. For example, `groupBy=removedReason` lists the reasons present, and those values work in `removedReasons`.\n\n**Steps.** Rows grouped by `stepId` also carry `stepName`, the name of that step on its most recent log record in the date range. `stepId` matches `actions[].id` in Get Workflow Definition. A step count includes the `remove_from_workflow` record written when a contact leaves the workflow at that step, so group by `stepId` and `type` together to count how often the step itself ran.\n\n**Common questions.**\n- Enrollments: `statuses=added_to_workflow`\n- Completions: `removedReasons=end_of_workflow`. Divide by enrollments for a completion rate\n- Failures per step: `statuses=error,failed,failed_retry_limit_reached&groupBy=stepId`\n- Why contacts left: `types=remove_from_workflow&groupBy=removedReason`\n- Stopped because the contact replied: `removedReasons=contact_reply_stop_response`\n- Goal reached: `types=workflow_goal&statuses=success`\n- Enrollment trend: `statuses=added_to_workflow&groupBy=week` (or `day`)\n- Change over time: call twice with back-to-back windows of equal length and compare\n\nCompletions in a window can include contacts who enrolled before it, so a completion rate can exceed 100%. With fewer than about 30 enrollments, rates swing widely. Zero is a real answer. A `workflowId` that does not exist in the sub-account returns 404.\n\n**Limits.** The range defaults to the last 30 days and must not exceed 30 days. Logs are available for the last 60 days. A grouping that produces more rows than `limit` is refused with 422 rather than truncated, because a truncated count reports wrong totals.\n\n**Compatibility.** New optional fields and new values of `status`, `type` and `removedReason` can appear at any time. Ignore fields you do not know, and treat an unknown value as other.",
        "parameters": [
          {
            "name": "Version",
            "in": "header",
            "description": "API Version. Send `v3`.",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "v3"
              ]
            }
          },
          {
            "name": "workflowId",
            "required": true,
            "in": "path",
            "description": "Workflow ID. Get it from Search Workflows. Never pass a workflow name",
            "schema": {
              "example": "a7321e66-8b68-4c10-afc7-4cc9744f17af",
              "type": "string"
            }
          },
          {
            "name": "locationId",
            "required": true,
            "in": "query",
            "description": "Sub-account (location) ID. It must be the sub-account the token belongs to, otherwise the request is refused with 403",
            "schema": {
              "example": "ve9EPM428h8vShlRW1KT",
              "type": "string"
            }
          },
          {
            "name": "startDate",
            "required": false,
            "in": "query",
            "description": "Start of the range, ISO 8601: a plain date (start of that day, UTC) or a full timestamp. Send it together with endDate. Defaults to 30 days ago. Logs are available for the last 60 days, so it cannot be earlier than that",
            "schema": {
              "example": "2026-06-01",
              "type": "string"
            }
          },
          {
            "name": "endDate",
            "required": false,
            "in": "query",
            "description": "End of the range, ISO 8601. A plain date includes the whole day. At most 30 days after startDate. Defaults to now",
            "schema": {
              "example": "2026-06-30",
              "type": "string"
            }
          },
          {
            "name": "groupBy",
            "required": false,
            "in": "query",
            "description": "Dimensions to group the counts by. Repeat the parameter or send a comma-separated list. `status` is the step outcome, `type` the step type, `stepId` the step, `removedReason` why the contact left the workflow, and `week`, `day` or `hour` a time bucket (one at most). Defaults to `status`",
            "schema": {
              "example": [
                "type",
                "status"
              ],
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "status",
                  "type",
                  "stepId",
                  "removedReason",
                  "week",
                  "day",
                  "hour"
                ]
              }
            }
          },
          {
            "name": "statuses",
            "required": false,
            "in": "query",
            "description": "Count only these step outcomes. Values: `added_to_workflow` (the contact entered the workflow), `success` (the step ran), `error` and `failed` (the step did not complete), `failed_retry_limit_reached` (the step gave up after its retries), `retry` (the step will run again), `skipped` (the step did not run, for example because of DND, a time window or missing data), `waiting` (the contact is waiting at the step), `wait_finished` (a wait ended), `finished` (the contact left the workflow, see removedReason), `paused_due_to_draft_mode` (the workflow was unpublished while the contact was in it), `contact_merged` (the contact was merged into another contact), `drip_queued` (the contact is waiting in a drip step for its batch), `drip_resume` (the batch was released and the contact moved on), `processing` (the step has started and has not finished yet), and `winner_declared` (an A/B test step picked its winning path; the record has no contact). New values can appear. Group by `status` first to see the values this workflow has",
            "schema": {
              "example": [
                "error",
                "failed"
              ],
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "types",
            "required": false,
            "in": "query",
            "description": "Count only these step types: a step `type` key, as listed by Get Step Types or in `actions[].type` of Get Workflow Definition. Unlike Get Workflow Logs, `if_else` and `drip` match only those exact keys here. New values can appear. Group by `type` first to see the types this workflow has",
            "schema": {
              "example": [
                "email"
              ],
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "removedReasons",
            "required": false,
            "in": "query",
            "description": "Count only records removed for these reasons. Values: `end_of_workflow` (the contact reached the end), `contact_deleted` (the contact was deleted), `deleted_workflow` (the workflow was deleted), `record_deleted` (the record was deleted), `goal_action` (a goal step removed the contact), `contact_reply_stop_response` (the contact replied and the workflow stops on reply), `contact_merge` (the contact was merged), `appointment-change`, `invoice-change` and `service-booking-change` (the appointment, invoice or booking changed and the workflow restarted for the contact), `attendee-change` (the Events attendee or their event changed, and the run for that attendee ended), `rental-booking-change` (the rental booking that started the workflow was deleted or cancelled), `wait_step_window_in_past` (a wait step time window pointed to a time in the past, so the contact left), and `missing-data` (the step the contact was on was deleted from the workflow). Values are exact, including the ones with hyphens. New values can appear. Group by `removedReason` first to see the values this workflow has",
            "schema": {
              "example": [
                "end_of_workflow"
              ],
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "timezone",
            "required": false,
            "in": "query",
            "description": "IANA timezone for the week, day and hour buckets. It does not move startDate and endDate, which stay UTC. Defaults to UTC",
            "schema": {
              "example": "America/New_York",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum number of grouped rows. A grouping that produces more is refused with 422 rather than truncated. Default 1000, maximum 5000",
            "schema": {
              "example": 1000,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowLogStatisticsResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedDTO"
                }
              }
            }
          },
          "403": {
            "description": "The token does not have access to this sub-account (locationId), or the workflow API is not enabled for it (code `WORKFLOW_API_NOT_ENABLED_FOR_LOCATION`, not a token or scope problem)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowApiNotEnabledDto"
                }
              }
            }
          },
          "404": {
            "description": "No such workflow in this location",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowNotFoundDto"
                }
              }
            }
          },
          "422": {
            "description": "The request is not valid. `message` lists what to fix",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnprocessableDTO"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Every public token has a daily quota and a short burst limit. Wait for `X-RateLimit-Interval-Milliseconds`, then retry.",
            "headers": {
              "X-RateLimit-Max": {
                "description": "Requests allowed in the current burst window",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current burst window",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Interval-Milliseconds": {
                "description": "Length of the burst window",
                "schema": {
                  "type": "integer",
                  "example": 10000
                }
              },
              "X-RateLimit-Limit-Daily": {
                "description": "Daily request quota for the token",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Daily-Remaining": {
                "description": "Requests left in the daily quota",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Daily-Reset": {
                "description": "Milliseconds until the daily quota resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRateLimitedDto"
                }
              }
            }
          },
          "504": {
            "description": "The query ran past its time limit and was stopped. Narrow it as the message says, then try again. The same request sent again usually times out again",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowLogStatisticsTimeoutDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": [
              "workflows.logs"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "name": "Authorization",
        "in": "header",
        "description": "Use the Access Token generated with user type as Sub-Account (OR) Private Integration Token of Sub-Account.",
        "type": "http"
      },
      "Location-Access": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "name": "Authorization",
        "in": "header",
        "description": "Use the Access Token generated with user type as Sub-Account (OR) Private Integration Token of Sub-Account.",
        "type": "http"
      },
      "Location-Access-Only": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "name": "Authorization",
        "in": "header",
        "description": "Use the Access Token generated with user type as Sub-Account.",
        "type": "http"
      },
      "Agency-Access": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "name": "Authorization",
        "in": "header",
        "description": "Use the Access Token generated with user type as Agency (OR) Private Integration Token of Agency.",
        "type": "http"
      },
      "Agency-Access-Only": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "name": "Authorization",
        "in": "header",
        "description": "Use the Access Token generated with user type as Agency.",
        "type": "http"
      }
    },
    "schemas": {
      "WorkflowLogStatisticsResponseDto": {
        "type": "object",
        "properties": {
          "count": {
            "type": "number",
            "description": "Number of rows in this response",
            "example": 3
          },
          "statistics": {
            "description": "The grouped counts",
            "example": [
              {
                "status": "finished",
                "count": 1369
              },
              {
                "status": "skipped",
                "count": 57
              },
              {
                "status": "success",
                "count": 4210
              }
            ],
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "string",
                  "description": "Step outcome. Present when grouping by status. New values can appear",
                  "example": "finished"
                },
                "type": {
                  "type": "string",
                  "description": "Step type. Present when grouping by type. New values can appear",
                  "example": "email"
                },
                "stepId": {
                  "type": "string",
                  "description": "Step ID. Present when grouping by stepId. Matches `actions[].id` in Get Workflow Definition. Usually a UUID. For an if/else step with `\"version\": 2` it is the branch that was taken, as in Get Workflow Logs. Enrollment rows use `added_to_workflow` or `add_to_workflow`, and removals with no current step (for example after the contact was deleted) have an empty string. The count includes the `remove_from_workflow` record written when a contact leaves the workflow at this step. Add `type` to groupBy to count them apart",
                  "example": "123e4567-e89b-12d3-a456-426614174000"
                },
                "stepName": {
                  "type": "string",
                  "description": "Name of the step on its most recent log record in the date range. Present when grouping by stepId",
                  "example": "Update Custom Value"
                },
                "removedReason": {
                  "type": "string",
                  "description": "Why the contact left the workflow. Present when grouping by removedReason. Null when no removal reason is recorded, which includes every record that is not a removal. Values: `end_of_workflow` (the contact reached the end), `contact_deleted` (the contact was deleted), `deleted_workflow` (the workflow was deleted), `record_deleted` (the record was deleted), `goal_action` (a goal step removed the contact), `contact_reply_stop_response` (the contact replied and the workflow stops on reply), `contact_merge` (the contact was merged), `appointment-change`, `invoice-change` and `service-booking-change` (the appointment, invoice or booking changed and the workflow restarted for the contact), `attendee-change` (the Events attendee or their event changed, and the run for that attendee ended), `rental-booking-change` (the rental booking that started the workflow was deleted or cancelled), `wait_step_window_in_past` (a wait step time window pointed to a time in the past, so the contact left), and `missing-data` (the step the contact was on was deleted from the workflow). New values can appear",
                  "nullable": true,
                  "example": "end_of_workflow"
                },
                "bucket": {
                  "type": "string",
                  "description": "Start of the time bucket in the requested timezone: `YYYY-MM-DD` for week (weeks start on Monday), `YYYY-MM-DD HH:mm:ss` for day and hour. Present when grouping by week, day or hour",
                  "example": "2026-09-01 00:00:00"
                },
                "count": {
                  "type": "number",
                  "description": "Number of log records in this group",
                  "example": 1369
                }
              },
              "required": [
                "count"
              ],
              "title": "WorkflowLogAggregateRowDto"
            }
          }
        },
        "required": [
          "count",
          "statistics"
        ],
        "title": "WorkflowLogStatisticsResponseDto"
      },
      "UnauthorizedDTO": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "example": 401
          },
          "message": {
            "type": "string",
            "example": "Invalid token: access token is invalid"
          },
          "error": {
            "type": "string",
            "example": "Unauthorized"
          }
        },
        "title": "UnauthorizedDTO"
      },
      "WorkflowApiNotEnabledDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "description": "HTTP status code",
            "example": 403
          },
          "error": {
            "type": "string",
            "description": "HTTP error name",
            "example": "Forbidden"
          },
          "code": {
            "type": "string",
            "description": "Stable code to branch on. Only ever this value for an enrolment refusal.",
            "example": "WORKFLOW_API_NOT_ENABLED_FOR_LOCATION"
          },
          "message": {
            "type": "string",
            "description": "Why the request was refused",
            "example": "The workflow API is not enabled for location ve9EPM428h8vShlRW1KT. This is not a token or scope problem — the API is currently available to selected sub-accounts only, and this one is not among them."
          }
        },
        "title": "WorkflowApiNotEnabledDto"
      },
      "WorkflowNotFoundDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "description": "HTTP status code",
            "example": 404
          },
          "message": {
            "type": "string",
            "description": "Which workflow was not found, and in which sub-account",
            "example": "Workflow b1b0de82-3efb-4d63-83f6-13c50aef208c not found in location ve9EPM428h8vShlRW1KT"
          },
          "error": {
            "type": "string",
            "description": "HTTP error name",
            "example": "Not Found"
          }
        },
        "title": "WorkflowNotFoundDto"
      },
      "UnprocessableDTO": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "example": 422
          },
          "message": {
            "example": [
              "Unprocessable Entity"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "error": {
            "type": "string",
            "example": "Unprocessable Entity"
          }
        },
        "title": "UnprocessableDTO"
      },
      "WorkflowRateLimitedDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "description": "HTTP status code",
            "example": 429
          },
          "message": {
            "type": "string",
            "description": "`Too Many Requests` when the integration's quota is spent, `Too Many Requests !` when the sub-account budget is spent. Branch on the status code, not this text.",
            "example": "Too Many Requests !"
          }
        },
        "title": "WorkflowRateLimitedDto"
      },
      "WorkflowLogStatisticsTimeoutDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "description": "HTTP status code",
            "example": 504
          },
          "message": {
            "type": "string",
            "description": "Why the query was stopped, and how to narrow it",
            "example": "The query took too long and was stopped. Try a shorter date range, or group by fewer dimensions (removedReason is the slowest). Sending the same request again will likely time out again."
          },
          "error": {
            "type": "string",
            "description": "HTTP error name",
            "example": "Gateway Timeout"
          }
        },
        "title": "WorkflowLogStatisticsTimeoutDto"
      }
    }
  }
}
```

## Code Examples

**cURL**

```bash
curl -L -X GET 'https://services.leadconnectorhq.com/workflows/<workflowId>/logs/aggregate?locationId=<LOCATIONID>' \
  -H 'Authorization: Bearer <TOKEN>' \
  -H 'Version: v3'
```

**Node.js**

```javascript
const options = {
  method: 'GET',
  headers: {
    Authorization: 'Bearer <TOKEN>',
    Version: 'v3'
  }
};

try {
  const response = await fetch('https://services.leadconnectorhq.com/workflows/<workflowId>/logs/aggregate?locationId=<LOCATIONID>', options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**Python**

```python
import requests

url = "https://services.leadconnectorhq.com/workflows/{workflowId}/logs/aggregate"

headers = {
    "Authorization": "Bearer <TOKEN>",
    "Version": "v3"
}

params = {
    "locationId": "<LOCATIONID>"
}

response = requests.get(url, params=params, headers=headers)
print(response.json())
```

**PHP**

```php
<?php
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => 'https://services.leadconnectorhq.com/workflows/<workflowId>/logs/aggregate?locationId=<LOCATIONID>',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer <TOKEN>',
    'Version: v3',
  ],
]);

$response = curl_exec($curl);
curl_close($curl);
echo $response;
```

**Java**

```java
HttpResponse<String> response = Unirest
  .get("https://services.leadconnectorhq.com/workflows/<workflowId>/logs/aggregate?locationId=<LOCATIONID>")
  .header("Authorization", "Bearer <TOKEN>")
  .header("Version", "v3")
  .asString();
```

**Go**

```go
package main

import (
  "fmt"
  "net/http"
  "io"
)

func main() {
  url := "https://services.leadconnectorhq.com/workflows/<workflowId>/logs/aggregate?locationId=<LOCATIONID>"
  req, _ := http.NewRequest("GET", url, nil)
  req.Header.Add("Authorization", "Bearer <TOKEN>")
  req.Header.Add("Version", "v3")

  res, _ := http.DefaultClient.Do(req)
  defer res.Body.Close()
  body, _ := io.ReadAll(res.Body)
  fmt.Println(string(body))
}
```

**Ruby**

```ruby
require 'uri'
require 'net/http'

url = URI("https://services.leadconnectorhq.com/workflows/<workflowId>/logs/aggregate?locationId=<LOCATIONID>")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer <TOKEN>"
request["Version"] = "v3"

response = http.request(request)
puts response.read_body
```

**PowerShell**

```powershell
$headers = @{
  "Authorization" = "Bearer <TOKEN>"
  "Version" = "v3"
}

$response = Invoke-RestMethod -Uri 'https://services.leadconnectorhq.com/workflows/<workflowId>/logs/aggregate?locationId=<LOCATIONID>' -Method 'GET' -Headers $headers
$response | ConvertTo-Json
```
