# DevTools API

The DevTools API provides programmatic access to the same real-time traffic data shown in the DevTools browser UI. Use it to build custom tooling, integrate with scripts, or pipe traffic data to other systems.

{% hint style="info" %}
**When to use the API vs the UI**: The browser UI is great for interactive debugging. The API is better when you want to filter/process data programmatically, integrate with other tools, or capture output to a file.
{% endhint %}

***

## Endpoint

When DevTools is enabled, Qtap exposes an SSE (Server-Sent Events) stream at:

```
http://localhost:10001/devtools/api/events
```

The stream delivers events in real-time as traffic flows through the system.

***

## Quick Start

```bash
# Stream all events
curl -sN http://localhost:10001/devtools/api/events

# Stream and filter for HTTP transactions only
curl -sN http://localhost:10001/devtools/api/events | grep "request.http_transaction"

# Pretty-print event data
curl -sN http://localhost:10001/devtools/api/events | \
  grep "^data:" | sed 's/^data: //' | jq .
```

***

## Event Types

The API streams six event types:

| Event                      | Description                                               |
| -------------------------- | --------------------------------------------------------- |
| `system.connected`         | Initial connection to the event stream                    |
| `process.started`          | New process detected on host                              |
| `process.stopped`          | Process terminated                                        |
| `connection.opened`        | New network connection established                        |
| `connection.updated`       | Connection metadata updated (protocol detected, TLS info) |
| `connection.closed`        | Connection terminated                                     |
| `request.http_transaction` | Complete HTTP request/response captured                   |

***

## Event Format

Events follow the SSE format with `event:` and `data:` lines:

```
event: process.started
data: {"data":{...},"ts":"2025-12-12T16:58:10.452Z"}

event: connection.opened
data: {"data":{...},"ts":"2025-12-12T16:58:11.123Z"}
```

***

## Event Schemas

### process.started / process.stopped

Process lifecycle events include container attribution when applicable.

```json
{
  "data": {
    "binary": "python3.11",
    "path": "/usr/local/bin/python3.11",
    "pid": 60895,
    "hostname": "my-container",
    "user": {
      "id": 0,
      "name": "root"
    },
    "container": {
      "id": "1781322a598f",
      "name": "my-app",
      "image": "python:3.11-slim",
      "labels": {
        "app": "frontend",
        "env": "production"
      }
    },
    "createdAt": "2025-12-12T16:42:58.300Z"
  },
  "ts": "2025-12-12T16:58:10.452Z"
}
```

| Field              | Description                                     |
| ------------------ | ----------------------------------------------- |
| `binary`           | Executable name                                 |
| `path`             | Full path to binary                             |
| `pid`              | Process ID                                      |
| `hostname`         | Container hostname or system hostname           |
| `user`             | User ID and name running the process            |
| `container`        | Container metadata (when running in Docker/K8s) |
| `container.labels` | Labels from Docker or Kubernetes                |

### connection.opened / connection.updated / connection.closed

Connection events include source/destination info, protocol detection, and TLS details.

```json
{
  "data": {
    "data": {
      "meta": {
        "connectionId": "d4u4dho7p3qk26l914bg",
        "endpointId": "api.stripe.com",
        "tlsProbeTypesDetected": ["openssl"],
        "tlsProbeIntrospected": true
      },
      "direction": "egress-external",
      "socketProtocol": "tcp",
      "l7Protocol": "http1",
      "tlsVersion": "TLS 1.3",
      "source": {
        "address": {"ip": "172.18.0.7", "port": 34438},
        "hostname": "my-container",
        "exe": "/usr/local/bin/python3.11",
        "user": "root",
        "container": {
          "id": "ac55e22af23b",
          "name": "payment-service",
          "image": "python:3.11-slim"
        }
      },
      "destination": {
        "address": {"ip": "52.4.128.73", "port": 443}
      },
      "tags": {
        "bin": ["python3.11"],
        "host": ["my-container"]
      }
    }
  },
  "ts": "2025-12-12T16:58:40.980Z"
}
```

| Field                        | Description                                                   |
| ---------------------------- | ------------------------------------------------------------- |
| `meta.connectionId`          | Unique connection identifier                                  |
| `meta.endpointId`            | Resolved hostname of destination                              |
| `meta.tlsProbeTypesDetected` | TLS libraries detected (openssl, gotls, nodetls, javassl)     |
| `meta.tlsProbeIntrospected`  | Whether TLS was successfully introspected                     |
| `direction`                  | Traffic direction (egress-external, egress-internal, ingress) |
| `l7Protocol`                 | Detected application protocol (http1, http2, other)           |
| `tlsVersion`                 | TLS version (TLS 1.2, TLS 1.3)                                |
| `source`                     | Source process, container, and address info                   |
| `destination`                | Destination address                                           |
| `tags`                       | Metadata tags from container labels                           |

### request.http\_transaction

HTTP transaction events contain the full request/response with headers and bodies.

```json
{
  "data": {
    "data": {
      "connectionId": "d4u4jhg7p3qk26l91icg",
      "endpointId": "api.example.com",
      "requestId": "d4u4jhg7p3qk26l91id0",
      "type": "http_transaction",
      "data": "eyJtZXRhZGF0YSI6ey4uLn0sInJlcXVlc3QiOns...}",
      "contentType": "application/json",
      "summary": {
        "request_method": "POST",
        "request_host": "api.example.com",
        "request_scheme": "https",
        "request_protocol": "http1",
        "response_status": 200,
        "duration_ms": 81,
        "container_name": "my-app",
        "process_exe": "/usr/local/bin/python3.11",
        "direction": "egress-external"
      }
    }
  },
  "ts": "2025-12-12T16:58:46.516Z"
}
```

The `data` field contains base64-encoded JSON with the full transaction:

```json
{
  "metadata": {
    "process_id": "60895",
    "process_exe": "/usr/local/bin/python3.11",
    "container_name": "my-app",
    "container_image": "python:3.11-slim",
    "bytes_sent": 517,
    "bytes_received": 324
  },
  "request": {
    "method": "POST",
    "url": "https://api.example.com/v1/users",
    "scheme": "https",
    "path": "/v1/users",
    "authority": "api.example.com",
    "protocol": "http1",
    "user_agent": "python-requests/2.31.0",
    "content_type": "application/json",
    "headers": {
      "Authorization": "Bearer token123",
      "Content-Type": "application/json"
    },
    "body": "eyJ1c2VyIjogImpvaG4ifQ=="
  },
  "response": {
    "status": 200,
    "content_type": "application/json",
    "headers": {
      "Content-Type": "application/json"
    },
    "body": "eyJpZCI6IDEyM30="
  },
  "duration_ms": 81,
  "direction": "egress-external"
}
```

{% hint style="warning" %}
Request and response bodies are base64-encoded within the transaction data. Decode them to see the actual content.
{% endhint %}

***

## Examples

### Filter for errors only

```bash
curl -sN http://localhost:10001/devtools/api/events | \
  grep "request.http_transaction" -A1 | \
  grep "^data:" | \
  sed 's/^data: //' | \
  jq 'select(.data.data.summary.response_status >= 400)'
```

### Watch connections to a specific host

```bash
curl -sN http://localhost:10001/devtools/api/events | \
  grep "connection" -A1 | \
  grep "^data:" | \
  sed 's/^data: //' | \
  jq 'select(.data.data.meta.endpointId == "api.stripe.com")'
```

### Decode HTTP transaction bodies

```bash
curl -sN http://localhost:10001/devtools/api/events | \
  grep "request.http_transaction" -A1 | \
  grep "^data:" | \
  sed 's/^data: //' | \
  jq -r '.data.data.data' | \
  base64 -d | \
  jq .
```

### Export to file for later analysis

```bash
curl -sN http://localhost:10001/devtools/api/events > traffic-capture.txt

# Then analyze later
grep "request.http_transaction" traffic-capture.txt | wc -l
```

***

## Comparison with Plugin Output

| Aspect                    | DevTools API         | Plugins (stdout/S3)      |
| ------------------------- | -------------------- | ------------------------ |
| **Delivery**              | Real-time SSE stream | Log output or S3 objects |
| **Filtering**             | Client-side          | Server-side via Rulekit  |
| **Persistence**           | Ephemeral            | Configurable storage     |
| **Process visibility**    | All processes        | Only HTTP traffic        |
| **Connection visibility** | All connections      | HTTP transactions only   |
| **Use case**              | Live debugging       | Production capture       |

For production monitoring and compliance storage, use [plugins with S3 storage](/getting-started/qtap/configuration/storage-configuration.md). The DevTools API is optimized for real-time debugging sessions.

***

## Security Considerations

{% hint style="warning" %}
The DevTools API exposes complete HTTP traffic including headers, bodies, and authentication tokens. Keep port 10001 secured.
{% endhint %}

* DevTools listens only on `localhost` by default
* Use SSH tunneling for remote access: `ssh -L 10001:localhost:10001 user@server`
* Never expose port 10001 to the public internet
* Consider network segmentation in production environments


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.qpoint.io/guides/devtools-guides/devtools-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
