> For the complete documentation index, see [llms.txt](https://docs.trezalabs.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trezalabs.com/api/pipeline-api.md).

# Pipeline API

Every published pipeline is a versioned HTTP endpoint. There are two ways to call it: the typed **`/invoke`** endpoint for JSON in and JSON out, and an OpenAI-compatible **`/chat/completions`** endpoint that works as a drop-in for any OpenAI SDK, streaming included.

***

## Base URL

```
https://trezalabs.com
```

Both endpoints live under `/api/pipelines/<id>`, where `<id>` is the pipeline's id from the dashboard. They accept and return `application/json` (the streaming variant returns Server-Sent Events).

***

## Authentication

Authenticate with a Treza API key, created on the **API keys** page in the dashboard and sent as a bearer token:

```
Authorization: Bearer treza_live_...
```

The key (`treza_live_...`) is shown once at creation. Store it in a secrets manager. A key can only invoke pipelines owned by the same account, and the pipeline must be **published**.

***

## Prerequisites

For a pipeline to accept API calls it must be published and have at least one input node and one output node. The **input keys** you send and the **output keys** you receive are derived from those nodes (the pipeline's contract). See [Publishing & versioning](/pipelines/publishing.md).

***

## `POST /api/pipelines/{id}/invoke`

Starts a run of the published pipeline with typed inputs. Runs execute asynchronously on Treza's background workers, so this returns a `runId` immediately — poll [`GET .../invoke`](#get-apipipelinesidinvoke) for the result.

### Request

```bash
curl https://trezalabs.com/api/pipelines/<id>/invoke \
  -H "Authorization: Bearer treza_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": {
      "brief": "A 6-second product demo of a matte-black water bottle on a kitchen counter"
    }
  }'
```

| Field    | Type   | Description                                                                  |
| -------- | ------ | ---------------------------------------------------------------------------- |
| `inputs` | object | Map of the pipeline's input keys to values. Keys come from your input nodes. |

### Response `202 Accepted`

```json
{
  "runId": "2026-07-10T18:30:00.000Z#a1b2c3d4",
  "status": "running",
  "version": 3,
  "statusUrl": "https://trezalabs.com/api/pipelines/<id>/invoke?runId=2026-07-10T18%3A30%3A00.000Z%23a1b2c3d4"
}
```

| Field       | Description                                         |
| ----------- | --------------------------------------------------- |
| `runId`     | Id of the run to poll. Also appears in run history. |
| `status`    | Always `running` on accept.                         |
| `version`   | The published version serving the run.              |
| `statusUrl` | Ready-made URL to poll for status and outputs.      |

***

## `GET /api/pipelines/{id}/invoke`

Polls a run started by `POST .../invoke`. Same bearer API key.

### Request

```bash
curl "https://trezalabs.com/api/pipelines/<id>/invoke?runId=<runId>" \
  -H "Authorization: Bearer treza_live_..."
```

| Query param | Description                                                |
| ----------- | ---------------------------------------------------------- |
| `runId`     | The `runId` returned by `POST .../invoke` (URL-encode it). |

### Response

While the run is in progress:

```json
{ "runId": "…", "status": "running", "version": 3, "startedAt": "…" }
```

Once finished:

```json
{
  "runId": "…",
  "status": "success",
  "version": 3,
  "startedAt": "2026-07-10T18:30:00.000Z",
  "finishedAt": "2026-07-10T18:30:48.000Z",
  "durationMs": 48213,
  "usage": { "prompt": 0, "completion": 0, "total": 1234, "costUsd": 0.42 },
  "outputs": { "video": "https://.../output.mp4" }
}
```

| Field        | Description                                                   |
| ------------ | ------------------------------------------------------------- |
| `status`     | `running`, `success`, `error`, or `partial`.                  |
| `outputs`    | Map keyed by your output nodes' keys (present once finished). |
| `usage`      | Token counts and provider cost (`costUsd`) for the run.       |
| `durationMs` | Wall-clock run time in milliseconds (once finished).          |

{% hint style="info" %}
Poll `statusUrl` every few seconds until `status` is no longer `running`. Video and image generation poll asynchronous provider jobs, so a run can take a while. Output **media URLs** are returned verbatim; long **text** outputs are truncated in the polled result.
{% endhint %}

***

## `POST /api/pipelines/{id}/chat/completions`

An OpenAI-compatible chat-completions endpoint. Point any OpenAI SDK at it by changing the base URL and API key. The latest user message is fed into the pipeline's entry node, and the output node's value is returned as the assistant message.

### curl

```bash
curl https://trezalabs.com/api/pipelines/<id>/chat/completions \
  -H "Authorization: Bearer treza_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "treza",
    "messages": [
      { "role": "user", "content": "A serene mountain lake at sunrise, cinematic" }
    ]
  }'
```

The `model` field is accepted but not used to pick a model (the pipeline's nodes decide that); send any string.

### Python (OpenAI SDK)

```python
from openai import OpenAI

client = OpenAI(
    api_key="treza_live_...",
    base_url="https://trezalabs.com/api/pipelines/<id>",  # SDK appends /chat/completions
)

completion = client.chat.completions.create(
    model="treza",
    messages=[{"role": "user", "content": "A serene mountain lake at sunrise, cinematic"}],
)

print(completion.choices[0].message.content)
```

### TypeScript (OpenAI SDK)

```typescript
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: 'treza_live_...',
  baseURL: 'https://trezalabs.com/api/pipelines/<id>', // SDK appends /chat/completions
});

const completion = await client.chat.completions.create({
  model: 'treza',
  messages: [{ role: 'user', content: 'A serene mountain lake at sunrise, cinematic' }],
});

console.log(completion.choices[0].message.content);
```

### Response

A standard OpenAI chat-completion object:

```json
{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1751904000,
  "model": "treza",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "https://.../output.mp4" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 1234 }
}
```

Two response headers help you tie a completion back to a run:

| Header                     | Meaning                                        |
| -------------------------- | ---------------------------------------------- |
| `x-treza-run-id`           | Id of the recorded run.                        |
| `x-treza-pipeline-version` | The published version that served the request. |

### Streaming

Set `"stream": true` to receive the response as Server-Sent Events, emitted as `chat.completion.chunk` objects and terminated by `data: [DONE]`. The final chunk carries `finish_reason: "stop"` and a `usage` block. Any OpenAI SDK's streaming mode works unchanged.

***

## Errors

Both endpoints share the same authorization and status model. `/invoke` returns `{ "error": "..." }`; `/chat/completions` returns OpenAI-style `{ "error": { "message": ..., "type": ... } }`.

| Status | Meaning                                                                     |
| ------ | --------------------------------------------------------------------------- |
| `400`  | Malformed request (for example, missing `messages` on `/chat/completions`). |
| `401`  | Missing or invalid API key.                                                 |
| `402`  | Insufficient credits. Top up in billing settings.                           |
| `403`  | The key does not own this pipeline.                                         |
| `404`  | Pipeline not found.                                                         |
| `409`  | Pipeline is not published.                                                  |
| `422`  | The pipeline has no entry node or no output node to serve chat completions. |
| `502`  | The pipeline ran but a node failed. The failing node's error is included.   |
| `500`  | Internal server error.                                                      |

***

## Related

* [Build your first pipeline](/pipelines/quickstart.md) - end-to-end from the canvas.
* [Publishing & versioning](/pipelines/publishing.md) - versions, rollback, and run history.
* [REST API](https://github.com/treza-labs/treza-docs-site/tree/main/developers/rest-api.md) - the rest of the Treza Platform API (keys, enclaves, gateway, and more).
