---
title: "Executions"
description: "GET /v1/executions/{trace_id} and /output. Retrieve execution status, results, and reconnect to streaming output after a disconnect. Full request/response reference."
url: https://baponi.ai/docs/api/executions
lastUpdated: 2026-03-16
---
# Executions
Baponi is a sandboxed code execution platform for AI agents. The Executions endpoints let you retrieve the status and result of any execution by its `trace_id`, and reconnect to a [streaming execution's](/docs/api/execute.md#streaming-execution-ndjson) output after a client disconnect.

Every execution (inline or streaming) is assigned a `trace_id` that uniquely identifies it. For inline executions, the `trace_id` is available in the [admin console](https://console.baponi.ai) audit log. For streaming executions, the `trace_id` is returned in the first `status` event of the NDJSON stream.

## Get execution status

```
GET https://api.baponi.ai/v1/executions/{trace_id}
```

**Authentication:** Bearer token with an API key (`sk-us-...`).

Returns the current status and result of an execution. Use this to check whether a streaming execution completed after your client disconnected, or to retrieve the final result of any past execution.

### Path parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `trace_id` | string | The execution's trace ID (e.g., `trc_a1b2c3d4`). Returned in the `status` event of a streaming execution. |

### Response body

```json
{
  "trace_id": "trc_a1b2c3d4",
  "status": "success",
  "exit_code": 0,
  "stdout": "Hello from Baponi!\n",
  "stderr": "",
  "error": null,
  "duration_ms": 142,
  "delivery_mode": "streaming",
  "created_at": "2026-03-15T10:30:00Z",
  "completed_at": "2026-03-15T10:30:01Z"
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `trace_id` | string | Unique execution identifier. |
| `status` | string | `"running"`, `"success"`, `"failed"`, `"timeout"`, `"blocked"`, `"oom"`, or `"cancelled"`. |
| `exit_code` | integer or null | Process exit code. `null` while the execution is still running. |
| `stdout` | string or null | Standard output. `null` while the execution is still running. |
| `stderr` | string or null | Standard error. `null` while the execution is still running. |
| `error` | string or null | Platform-level error message, if any. `null` on success. |
| `duration_ms` | integer | Wall-clock execution time in milliseconds. |
| `delivery_mode` | string | `"inline"`, `"streaming"`, or `"webhook"`. |
| `created_at` | string | ISO 8601 timestamp when the execution was created. |
| `completed_at` | string or null | ISO 8601 timestamp when the execution finished. `null` while still running. |
| `webhook_url` | string or null | Webhook URL used for delivery. `null` for inline/streaming. |
| `webhook_delivery_status` | string or null | `"pending"`, `"delivered"`, or `"failed"`. `null` for non-webhook. |

### Examples

```bash
curl https://api.baponi.ai/v1/executions/trc_a1b2c3d4 \
  -H "Authorization: Bearer $BAPONI_API_KEY"
```

```python
from baponi import Baponi

client = Baponi()
status = client.get_execution("trc_a1b2c3d4")
print(f"Status: {status.status}, exit_code: {status.exit_code}")
```

```python

response = requests.get(
    "https://api.baponi.ai/v1/executions/trc_a1b2c3d4",
    headers={"Authorization": "Bearer sk-us-YOUR_API_KEY"},
)
execution = response.json()
print(f"Status: {execution['status']}, exit_code: {execution['exit_code']}")
```

## Reconnect to output stream

```
GET https://api.baponi.ai/v1/executions/{trace_id}/output?after_seq=N
```

**Authentication:** Bearer token with an API key (`sk-us-...`).

Returns NDJSON output chunks with `seq` greater than `after_seq`. Use this to resume a streaming execution after a client disconnect. Pick up from the last `seq` number you received and you will not miss any output.

### Path parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `trace_id` | string | The execution's trace ID. |

### Query parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `after_seq` | integer | No | `0` | Return only events with `seq` greater than this value. Set to the last `seq` you received. |

### Response

The response is `application/x-ndjson` with the same event format as the [streaming execution](/docs/api/execute.md#streaming-execution-ndjson) response. Each line is a JSON object with a `type` field (`output` or `keepalive`). To get the final result, use the [execution status endpoint](#get-execution-status).

```bash
curl "https://api.baponi.ai/v1/executions/trc_a1b2c3d4/output?after_seq=3" \
  -H "Authorization: Bearer $BAPONI_API_KEY"
```

Example response (events with `seq > 3`):

```jsonl
{"type":"output","stream":"stdout","data":"step 2\n","seq":4}
{"type":"output","stream":"stdout","data":"step 3\n","seq":5}
```

### Reconnection example

```python

last_seq = 0

def stream_execution(api_key, code, timeout=60):
    """Stream execution with automatic reconnection."""
    global last_seq

    # Start streaming execution
    response = requests.post(
        "https://api.baponi.ai/v1/sandbox/execute",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
            "Accept": "application/x-ndjson",
        },
        json={"code": code, "timeout": timeout},
        stream=True,
    )

    trace_id = None
    try:
        for line in response.iter_lines():
            if not line:
                continue
            event = json.loads(line)
            last_seq = event.get("seq", last_seq)

            if event["type"] == "status":
                trace_id = event["trace_id"]
            elif event["type"] == "output":
                print(event["data"], end="")
            elif event["type"] == "result":
                return event["result"]
    except requests.exceptions.ConnectionError:
        if trace_id:
            return reconnect(api_key, trace_id)
    return None

def reconnect(api_key, trace_id):
    """Reconnect and fetch missed output chunks."""
    # Get missed output
    output = requests.get(
        f"https://api.baponi.ai/v1/executions/{trace_id}/output",
        headers={"Authorization": f"Bearer {api_key}"},
        params={"after_seq": last_seq},
    )
    for line in output.text.strip().split("\n"):
        if line:
            event = json.loads(line)
            if event["type"] == "output":
                print(event["data"], end="")

    # Get final result
    status = requests.get(
        f"https://api.baponi.ai/v1/executions/{trace_id}",
        headers={"Authorization": f"Bearer {api_key}"},
    )
    return status.json()
```

### Output retention

Output chunks are retained for the execution's `timeout` value plus 300 seconds (5 minutes) after the execution starts. For example, an execution with a 60-second timeout retains output for 360 seconds. After this window, the reconnection endpoint returns an empty response. The execution status endpoint continues to return the final result indefinitely.

## Cancel a running execution

```
POST https://api.baponi.ai/v1/executions/{trace_id}/cancel
```

**Authentication:** Bearer token with an API key (`sk-us-...`).

Cancels a running execution immediately. The sandbox process is killed, any in-progress streaming connection emits a final `result` event with `status: "cancelled"`, and the execution record is updated to `cancelled`. Only works on executions in `running` state.

### Path parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `trace_id` | string | The execution's trace ID (e.g., `trc_a1b2c3d4`). |

### Response body

```json
{
  "trace_id": "trc_a1b2c3d4",
  "status": "cancelling"
}
```

The response confirms the cancel was accepted. The status is `"cancelling"` (not `"cancelled"`) because the signal is asynchronous - the execution may still be running for a brief moment. Poll the [execution status endpoint](#get-execution-status) to confirm the final `"cancelled"` state.

### Examples

```bash
curl -X POST https://api.baponi.ai/v1/executions/trc_a1b2c3d4/cancel \
  -H "Authorization: Bearer $BAPONI_API_KEY"
```

```python
from baponi import Baponi

client = Baponi()
result = client.cancel_execution("trc_a1b2c3d4")
print(result.status)  # cancelling
```

```python

response = requests.post(
    "https://api.baponi.ai/v1/executions/trc_a1b2c3d4/cancel",
    headers={"Authorization": "Bearer sk-us-YOUR_API_KEY"},
)
print(response.json())  # {"trace_id": "trc_a1b2c3d4", "status": "cancelling"}
```

### Cancel error responses

| Status | Error Code | When |
|--------|------------|------|
| `401` | `unauthorized` | Missing, invalid, or revoked API key. |
| `404` | `not_found` | Execution does not exist or belongs to a different organization. |
| `409` | `conflict` | Execution is already in a terminal state (`success`, `failed`, `timeout`, `cancelled`, etc.). |

## Error responses

All endpoints return structured JSON errors:

```json
{
  "error": "not_found",
  "message": "Execution trc_a1b2c3d4 not found"
}
```

| Status | Error Code | When |
|--------|------------|------|
| `401` | `unauthorized` | Missing, invalid, or revoked API key. |
| `404` | `not_found` | Execution does not exist or belongs to a different organization. |

Executions are scoped to the organization that owns the API key. You cannot access executions from other organizations, even with a valid API key.

## FAQ

### Can I use these endpoints with inline (non-streaming) executions?

Yes. Every execution (inline or streaming) is recorded with a `trace_id`. The status endpoint works for both. The output reconnection endpoint only returns data for streaming executions, since inline executions do not persist output chunks.

### How long are execution records retained?

Execution status records are retained according to your plan's audit log retention period: 1 day (Free), 30 days (Pro), unlimited (Enterprise). The output reconnection buffer has a shorter retention window. See [Output retention](#output-retention).

### Can I cancel a running execution?

Yes. Call `POST /v1/executions/{trace_id}/cancel` with the same API key used to start the execution. The process is killed immediately and the execution status becomes `"cancelled"`. If the execution was streaming, the NDJSON stream emits a final `result` event with `status: "cancelled"` and `error: "Cancelled by user"`. You can also cancel executions from the [admin console](https://console.baponi.ai) execution detail page.

### What happens if the execution is still running when I call the status endpoint?

The endpoint returns the current state with `status: "running"`, `exit_code: null`, and `completed_at: null`. Poll periodically or use streaming mode to receive real-time updates.