> For the complete documentation index, see [llms.txt](https://docs.groundcover.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.groundcover.com/reference/remote-access-and-apis/api-examples/query-data-gcql/query-logs.md).

# Query Logs

Search and aggregate log data over HTTP using gcQL queries - filter by any field, run full-text searches, and compute aggregations in a single request.

### Endpoint

**POST** `/api/logs/v2/search`

### Authentication

This endpoint requires API Key authentication via the Authorization header.

### Headers

| Header          | Required                        | Description                                                                                                                                                         |
| --------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Authorization` | Yes                             | Bearer token with your API key                                                                                                                                      |
| `Content-Type`  | Yes                             | Must be `application/json`                                                                                                                                          |
| `X-Backend-Id`  | Only for multi-backend accounts | Your backend identifier, found under **Settings → Access → API Keys** ([details](/reference/remote-access-and-apis/api-examples/query-data-gcql.md#authentication)) |

### Request Body

| Parameter | Type   | Required | Description                                  |
| --------- | ------ | -------- | -------------------------------------------- |
| `start`   | string | Yes      | Start of the time range (RFC3339 / ISO 8601) |
| `end`     | string | Yes      | End of the time range (RFC3339 / ISO 8601)   |
| `query`   | string | Yes      | The gcQL query to execute                    |

### Examples

#### Recent Error Logs

Fetch the latest error logs with a selected set of fields:

```bash
curl 'https://api.groundcover.com/api/logs/v2/search' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "start": "2026-08-22T14:00:00Z",
    "end": "2026-08-22T15:00:00Z",
    "query": "level:error | sort by (_time desc) | fields _time, workload, namespace, content | limit 20"
  }'
```

**Example Response:**

```json
[
  {
    "_time": "2026-08-22T14:50:56.503949956Z",
    "workload": "checkout-service",
    "namespace": "production",
    "content": "failed to process payment: connection timeout"
  },
  {
    "_time": "2026-08-22T14:50:12.104403877Z",
    "workload": "checkout-service",
    "namespace": "production",
    "content": "failed to process payment: connection timeout"
  }
]
```

#### Filtering by Multiple Fields

Different fields combine with AND; repeating the same field creates an OR. This query matches error logs from the `prod` or `dev` environments:

```bash
curl 'https://api.groundcover.com/api/logs/v2/search' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "start": "2026-08-22T14:00:00Z",
    "end": "2026-08-22T15:00:00Z",
    "query": "level:error env:prod env:dev | fields _time, env, workload, content | limit 20"
  }'
```

Exclusions use a `-` prefix (`-level:debug`), and explicit boolean logic is also supported: `level:error AND (env:prod OR env:dev)`. See [gcQL filters](/investigate/querying-your-groundcover-data/groundcover-query-language/filters.md) for the full syntax.

#### Full-Text Search

A bare keyword (no field prefix) runs an indexed full-text search over log content. This counts how many log lines from a workload contain "500":

```bash
curl 'https://api.groundcover.com/api/logs/v2/search' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "start": "2026-08-22T14:00:00Z",
    "end": "2026-08-22T15:00:00Z",
    "query": "workload:router 500 | stats count() as hits"
  }'
```

**Example Response:**

```json
[
  { "hits": 2433 }
]
```

{% hint style="info" %}
Prefer bare keywords (`timeout`, `500`) over leading-wildcard patterns like `content:*timeout*` - keywords hit the full-text index, while a leading wildcard forces a full scan.
{% endhint %}

#### Aggregation: Errors per Workload

Count error logs grouped by workload, sorted by count:

```bash
curl 'https://api.groundcover.com/api/logs/v2/search' \
  -H 'authorization: Bearer <YOUR_API_KEY>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "start": "2026-08-22T14:00:00Z",
    "end": "2026-08-22T15:00:00Z",
    "query": "level:error | stats by (workload) count() as errors | sort by (errors desc) | limit 10"
  }'
```

**Example Response:**

```json
[
  { "workload": "sensor", "errors": 652050 },
  { "workload": "custom-metrics", "errors": 292511 },
  { "workload": "ingress-gateway", "errors": 133992 }
]
```

#### Pagination

Use the `offset` and `limit` pipes with a stable sort order, keeping the same time range across pages:

```bash
# Page 1
"query": "level:error | sort by (_time desc) | fields _time, workload, content | limit 200"

# Page 2
"query": "level:error | sort by (_time desc) | fields _time, workload, content | offset 200 | limit 200"
```

### Best Practices

1. **Narrow the time range**: keep `start`/`end` as tight as your use case allows, and widen only if needed.
2. **Lead with a selective filter**: a specific `workload`, `namespace`, or `level` bounds the scan; on high-volume environments add a keyword predicate too.
3. **Aggregate on the server**: one `| stats` query with `count() if (condition)` beats fetching raw rows and counting client-side.
4. **Always bound results** with `| limit N`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.groundcover.com/reference/remote-access-and-apis/api-examples/query-data-gcql/query-logs.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
