chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:32:57 +08:00
commit cd420f9332
4811 changed files with 884702 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
---
title: Advanced usage
sidebarTitle: Advanced usage
description: Advanced usage of the Trigger.dev management API
---
### Accessing raw HTTP responses
All API methods return a `Promise` subclass `ApiPromise` that includes helpers for accessing the underlying HTTP response:
```ts
import { runs } from "@trigger.dev/sdk";
async function main() {
const { data: run, response: raw } = await runs.retrieve("run_1234").withResponse();
console.log(raw.status);
console.log(raw.headers);
const response = await runs.retrieve("run_1234").asResponse(); // Returns a Response object
console.log(response.status);
console.log(response.headers);
}
```
+224
View File
@@ -0,0 +1,224 @@
---
title: Authentication
sidebarTitle: Authentication
description: Authenticating with the Trigger.dev management API
---
There are two methods of authenticating with the management API: using a secret key associated with a specific environment in a project (`secretKey`), or using a personal access token (`personalAccessToken`). Both methods should only be used in a backend server, as they provide full access to the project.
<Note>
There is a separate authentication strategy when making requests from your frontend application.
See the [Realtime guide](/realtime/overview) for more information. This guide is for backend usage
only.
</Note>
Certain API functions work with both authentication methods, but require different arguments depending on the method used. For example, the `runs.list` function can be called using either a `secretKey` or a `personalAccessToken`, but the `projectRef` argument is required when using a `personalAccessToken`:
```ts
import { configure, runs } from "@trigger.dev/sdk";
// Using secretKey authentication
configure({
secretKey: process.env["TRIGGER_SECRET_KEY"], // starts with tr_dev_, tr_prod_, or tr_preview_
});
function secretKeyExample() {
return runs.list({
limit: 10,
status: ["COMPLETED"],
});
}
// Using personalAccessToken authentication
configure({
secretKey: process.env["TRIGGER_ACCESS_TOKEN"], // starts with tr_pat_
});
function personalAccessTokenExample() {
// Notice the projectRef argument is required when using a personalAccessToken
return runs.list("prof_1234", {
limit: 10,
status: ["COMPLETED"],
projectRef: "tr_proj_1234567890",
});
}
```
<Accordion title="View endpoint support">
Consult the following table to see which endpoints support each authentication method.
| Endpoint | Secret key | Personal Access Token |
| ---------------------- | ---------- | --------------------- |
| `task.trigger` | ✅ | |
| `task.batchTrigger` | ✅ | |
| `runs.list` | ✅ | ✅ |
| `runs.retrieve` | ✅ | |
| `runs.cancel` | ✅ | |
| `runs.replay` | ✅ | |
| `envvars.list` | ✅ | ✅ |
| `envvars.retrieve` | ✅ | ✅ |
| `envvars.upload` | ✅ | ✅ |
| `envvars.create` | ✅ | ✅ |
| `envvars.update` | ✅ | ✅ |
| `envvars.del` | ✅ | ✅ |
| `schedules.list` | ✅ | |
| `schedules.create` | ✅ | |
| `schedules.retrieve` | ✅ | |
| `schedules.update` | ✅ | |
| `schedules.activate` | ✅ | |
| `schedules.deactivate` | ✅ | |
| `schedules.del` | ✅ | |
</Accordion>
### Secret key
Secret key authentication scopes the API access to a specific environment in a project, and works with certain endpoints. You can read our [API Keys guide](/apikeys) for more information.
### Personal Access Token (PAT)
A PAT is a token associated with a specific user, and gives access to all the orgs, projects, and environments that the user has access to. You can identify a PAT by the `tr_pat_` prefix. Because a PAT does not scope access to a specific environment, you must provide the `projectRef` argument when using a PAT (and sometimes the environment as well).
For example, when uploading environment variables using a PAT, you must provide the `projectRef` and `environment` arguments:
```ts
import { configure, envvars } from "@trigger.dev/sdk";
configure({
secretKey: process.env["TRIGGER_ACCESS_TOKEN"], // starts with tr_pat_
});
await envvars.upload("proj_1234", "dev", {
variables: {
MY_ENV_VAR: "MY_ENV_VAR_VALUE",
},
override: true,
});
```
### Preview branch targeting
When working with preview branches, you may need to target a specific branch when making API calls. This is particularly useful for managing environment variables or other resources that are scoped to individual preview branches.
<Tabs>
<Tab title="SDK">
To target a specific preview branch, include the `previewBranch` option in your SDK configuration:
```ts
import { configure, envvars } from "@trigger.dev/sdk";
configure({
secretKey: process.env["TRIGGER_ACCESS_TOKEN"], // starts with tr_pat_
previewBranch: "feature-xyz",
});
await envvars.update("proj_1234", "preview", "DATABASE_URL", {
value: "your_preview_database_url",
});
```
</Tab>
<Tab title="cURL">
To target a specific preview or development branch, include the `x-trigger-branch` header in your API requests with the branch name as the value:
```bash
curl --request PUT \
--url https://api.trigger.dev/api/v1/projects/{projectRef}/envvars/preview/DATABASE_URL \
--header 'Authorization: Bearer <token>' \
--header 'x-trigger-branch: feature-xyz' \
--header 'Content-Type: application/json' \
--data '{
"value": "your_preview_database_url"
}'
```
</Tab>
</Tabs>
This will set the `DATABASE_URL` environment variable specifically for the `feature-xyz` preview branch.
<Note>
The `x-trigger-branch` header is only relevant when working with the `preview` or `dev` environments (`{env}
` parameter set to `preview` or `development`). It has no effect when working with `staging`, or `prod`
environments.
</Note>
#### SDK usage with preview branches
When using the SDK to manage preview branch environment variables, the branch targeting is handled automatically when you're running in a preview environment with the `TRIGGER_PREVIEW_BRANCH` environment variable set. However, you can also specify the branch explicitly:
```ts
import { configure, envvars } from "@trigger.dev/sdk";
configure({
secretKey: process.env["TRIGGER_ACCESS_TOKEN"], // starts with tr_pat_
previewBranch: "feature-xyz", // Optional: specify the branch
});
await envvars.update("proj_1234", "preview", "DATABASE_URL", {
value: "your_preview_database_url",
});
```
### Talking to multiple projects, environments, or branches
A long-running process often needs to talk to more than one Trigger.dev target. There are two patterns:
- **`new TriggerClient({...})`** — an explicit instance that owns its own auth, baseURL, and preview branch. Use this when the targets are long-lived (a dashboard that watches prod + preview, a worker that triggers across multiple projects, etc.). Each instance is fully isolated and concurrent calls don't interfere. See [Multiple SDK clients](/management/multiple-clients) for details.
- **`auth.withAuth(config, fn)`** — runs a single callback under a temporary config override, then restores. Use this for short, sequential overrides (e.g. one batch under a different token) where keeping a dedicated client around is overkill.
```ts
import { auth, runs } from "@trigger.dev/sdk";
const projectBRuns = await auth.withAuth(
{ accessToken: process.env.TRIGGER_SECRET_KEY_PROJECT_B },
async () => {
return runs.list({ limit: 10 });
},
);
```
Any SDK call inside the callback uses the overridden config. Calls outside the callback continue to use whatever was set by `configure` (or picked up from `TRIGGER_SECRET_KEY`).
The override is scoped via [AsyncLocalStorage](https://nodejs.org/api/async_context.html), so concurrent `auth.withAuth` calls (including overlapping calls inside `Promise.all` with different tokens) do not interfere. Nested calls compose — an inner `auth.withAuth({ accessToken })` inside an outer `auth.withAuth({ baseURL })` runs with both fields applied.
Unlike `TriggerClient` instances (which stay isolated unless you opt in), `auth.withAuth` keeps the surrounding task context: a call made inside a task still inherits `parentRunId`, version locking, and the test flag, the same as a direct SDK call. See the [isolation contract](/management/multiple-clients#isolation-contract).
<Note>
On runtimes without AsyncLocalStorage (browsers and some edge runtimes), the SDK falls back to
swapping the global config in place for the duration of the callback, which is not safe under
concurrency. If you need concurrent multi-target calls there, use
[`new TriggerClient({...})`](/management/multiple-clients) instances instead.
</Note>
## Session scopes
[Sessions](/ai-chat/sessions) are addressed by a session-scoped public access token — a short-lived JWT you mint in your backend and pass to frontend or server-side clients. The token carries one or both of two scopes, each pinned to a session by its friendly ID (`session_…`) or your `externalId`:
| Scope | Grants |
| --- | --- |
| `read:sessions:{id}` | Retrieve the session, list its runs, and subscribe to and drain both its `.in` and `.out` [channels](/management/sessions/channels). |
| `write:sessions:{id}` | Append to the session's `.in` channel, and create runs on the session (including the create call itself). |
Two boundaries follow from the table, and both are enforced server-side:
- **`write:sessions` does not grant `.out` append.** The `.out` channel is the task's to write. Appending to `.out` requires a **secret key**; a public token gets `403`.
- **Updating or closing a session requires a secret key.** A session public token cannot call `PATCH /api/v1/sessions/{session}` or `POST /api/v1/sessions/{session}/close` — those are admin operations.
Mint a token with `auth.createPublicToken` in your backend:
```ts Your backend
import { auth } from "@trigger.dev/sdk";
const publicToken = await auth.createPublicToken({
scopes: {
read: { sessions: "session_123" },
write: { sessions: "session_123" },
},
});
```
`sessions` accepts a single ID or an array. The default token TTL is 1 hour. One token authorizes **both** URL forms — pass either your `externalId` or the `session_…` ID in the path.
The `publicAccessToken` returned by [`sessions.start()`](/management/sessions/create) already carries both scopes for the session it created, so you usually don't mint one by hand for the create flow.
For the full channel HTTP surface these scopes authorize, see [Session channels](/management/sessions/channels). For the SDK side, see [Sessions](/ai-chat/sessions). For general public-token usage (expiration formats, trigger tokens, scoping to runs and tasks), see [Realtime authentication](/realtime/auth).
+41
View File
@@ -0,0 +1,41 @@
---
title: Auto-pagination
sidebarTitle: Auto-pagination
description: Using auto-pagination with the Trigger.dev management API
---
All list endpoints in the management API support auto-pagination.
You can use `for await … of` syntax to iterate through items across all pages:
```ts
import { runs } from "@trigger.dev/sdk";
async function fetchAllRuns() {
const allRuns = [];
for await (const run of runs.list({ limit: 10 })) {
allRuns.push(run);
}
return allRuns;
}
```
You can also use helpers on the return value from any `list` method to get the next/previous page of results:
```ts
import { runs } from "@trigger.dev/sdk";
async function main() {
let page = await runs.list({ limit: 10 });
for (const run of page.data) {
console.log(run);
}
while (page.hasNextPage()) {
page = await page.getNextPage();
// ... do something with the next page
}
}
```
+5
View File
@@ -0,0 +1,5 @@
---
title: "Create batch"
openapi: "openapi POST /api/v3/batches"
---
@@ -0,0 +1,4 @@
---
title: "Retrieve batch results"
openapi: "v3-openapi GET /api/v1/batches/{batchId}/results"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve a batch"
openapi: "v3-openapi GET /api/v1/batches/{batchId}"
---
+5
View File
@@ -0,0 +1,5 @@
---
title: "Stream batch items"
openapi: "openapi POST /api/v3/batches/{batchId}/items"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Abort bulk action"
openapi: "v3-openapi POST /api/v1/bulk-actions/{bulkActionId}/abort"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Create bulk action"
openapi: "v3-openapi POST /api/v1/bulk-actions"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List bulk actions"
openapi: "v3-openapi GET /api/v1/bulk-actions"
---
@@ -0,0 +1,4 @@
---
title: "Retrieve bulk action"
openapi: "v3-openapi GET /api/v1/bulk-actions/{bulkActionId}"
---
@@ -0,0 +1,11 @@
---
title: "Get latest deployment"
openapi: "v3-openapi GET /api/v1/deployments/latest"
---
<Warning>
This endpoint only returns **unmanaged** deployments, which are used in self-hosted setups. It
will return `404` for standard CLI deployments made against Trigger.dev Cloud.
If you're using the CLI to deploy, use the [list deployments](/management/deployments/list) endpoint instead.
</Warning>
+5
View File
@@ -0,0 +1,5 @@
---
title: "List deployments"
description: "List all deployments for the authenticated environment, ordered by most recent first."
openapi: "v3-openapi GET /api/v1/deployments"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Promote deployment"
openapi: "v3-openapi POST /api/v1/deployments/{version}/promote"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Get deployment"
openapi: "v3-openapi GET /api/v1/deployments/{deploymentId}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Create Env Var"
openapi: "v3-openapi POST /api/v1/projects/{projectRef}/envvars/{env}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Delete Env Var"
openapi: "v3-openapi DELETE /api/v1/projects/{projectRef}/envvars/{env}/{name}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Import Env Vars"
openapi: "v3-openapi POST /api/v1/projects/{projectRef}/envvars/{env}/import"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List Env Vars"
openapi: "v3-openapi GET /api/v1/projects/{projectRef}/envvars/{env}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve Env Var"
openapi: "v3-openapi GET /api/v1/projects/{projectRef}/envvars/{env}/{name}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Update Env Var"
openapi: "v3-openapi PUT /api/v1/projects/{projectRef}/envvars/{env}/{name}"
---
+66
View File
@@ -0,0 +1,66 @@
---
title: Errors and retries
sidebarTitle: Errors and retries
description: Handling errors and retries with the Trigger.dev management API
---
## Handling errors
When the SDK method is unable to connect to the API server, or the API server returns a non-successful response, the SDK will throw an `ApiError` that you can catch and handle:
```ts
import { runs, APIError } from "@trigger.dev/sdk";
async function main() {
try {
const run = await runs.retrieve("run_1234");
} catch (error) {
if (error instanceof ApiError) {
console.error(`API error: ${error.status}, ${error.headers}, ${error.body}`);
} else {
console.error(`Unknown error: ${error.message}`);
}
}
}
```
## Retries
The SDK will automatically retry requests that fail due to network errors or server errors. By default, the SDK will retry requests up to 3 times, with an exponential backoff delay between retries.
You can customize the retry behavior by passing a `requestOptions` option to the `configure` function:
```ts
import { configure } from "@trigger.dev/sdk";
configure({
requestOptions: {
retry: {
maxAttempts: 5,
minTimeoutInMs: 1000,
maxTimeoutInMs: 5000,
factor: 1.8,
randomize: true,
},
},
});
```
All SDK functions also take a `requestOptions` parameter as the last argument, which can be used to customize the request options. You can use this to disable retries for a specific request:
```ts
import { runs } from "@trigger.dev/sdk";
async function main() {
const run = await runs.retrieve("run_1234", {
retry: {
maxAttempts: 1, // Disable retries
},
});
}
```
<Note>
When running inside a task, the SDK ignores customized retry options for certain functions (e.g.,
`task.trigger`, `task.batchTrigger`), and uses retry settings optimized for task execution.
</Note>
+4
View File
@@ -0,0 +1,4 @@
---
title: "Ignore an error"
openapi: "v3-openapi POST /api/v1/errors/{errorId}/ignore"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List errors"
openapi: "v3-openapi GET /api/v1/errors"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Resolve an error"
openapi: "v3-openapi POST /api/v1/errors/{errorId}/resolve"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve an error"
openapi: "v3-openapi GET /api/v1/errors/{errorId}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Unresolve an error"
openapi: "v3-openapi POST /api/v1/errors/{errorId}/unresolve"
---
+88
View File
@@ -0,0 +1,88 @@
---
title: Multiple SDK clients
sidebarTitle: Multiple SDK clients
description: Use TriggerClient to talk to multiple Trigger.dev projects, environments, or preview branches from a single process.
---
The global `configure()` API binds the SDK to one set of credentials per process. When a single process needs to talk to more than one Trigger.dev project, environment, or preview branch, use `new TriggerClient({...})` for each target instead. Each instance owns its own auth, baseURL, and preview branch, and concurrent calls across instances stay isolated.
```ts
import { TriggerClient } from "@trigger.dev/sdk";
const prod = new TriggerClient({ accessToken: process.env.TRIGGER_PROD_KEY });
const preview = new TriggerClient({
accessToken: process.env.TRIGGER_PREVIEW_KEY,
previewBranch: "signup-flow",
});
const payload = { to: "user@example.com" };
await prod.tasks.trigger("send-email", payload);
await preview.runs.list({ status: ["COMPLETED"] });
```
## Configuration
`TriggerClient` accepts the same fields as `configure()`:
| Field | Description | Env-var fallback |
| --------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| `accessToken` | Secret key (`tr_dev_*`, `tr_prod_*`, `tr_preview_*`) or personal access token (`tr_pat_*`). | `TRIGGER_SECRET_KEY`, then `TRIGGER_ACCESS_TOKEN` |
| `previewBranch` | Preview branch name when using a `tr_preview_*` key. | `TRIGGER_PREVIEW_BRANCH`, then `VERCEL_GIT_COMMIT_REF` |
| `baseURL` | Override the Trigger.dev API URL. Defaults to `https://api.trigger.dev`. | `TRIGGER_API_URL` |
| `requestOptions`| Request-level options (retry policy, additional headers, etc.) — see the `ApiRequestOptions` type. | — |
Fields not passed to the constructor fall back to the matching env var (and then to a sensible default for `baseURL`). Explicit constructor values always win, so you can mix env-var-backed clients and fully explicit clients in the same process.
```ts
// Picks up TRIGGER_SECRET_KEY / TRIGGER_PREVIEW_BRANCH from env.
const fromEnv = new TriggerClient();
// Explicit values override env entirely.
const explicit = new TriggerClient({
accessToken: process.env.OTHER_PROJECT_KEY,
previewBranch: "feature-x",
});
```
If no `accessToken` resolves from either the constructor or env vars, the first API call throws an `ApiClientMissingError` with a clear message.
## What's on a TriggerClient instance
Each instance exposes the management surface as namespaced properties: `tasks`, `runs`, `batch`, `schedules`, `envvars`, `queues`, `deployments`, `prompts`, and `auth`.
```ts
import type { emailTask } from "./trigger/email";
const client = new TriggerClient();
await client.tasks.trigger<typeof emailTask>("send-email", { to: "user@example.com" });
await client.runs.list({ status: ["COMPLETED"], limit: 10 });
await client.schedules.create({ task: "daily-report", cron: "0 9 * * *" });
await client.envvars.update("proj_1234", "preview", "DATABASE_URL", { value: "..." });
```
Methods that only make sense inside a running task are not on the instance surface: `tasks.triggerAndWait`, `tasks.batchTriggerAndWait`, `tasks.triggerAndSubscribe`, `batch.triggerAndWait`, `batch.triggerByTaskAndWait`, and the task-definition helpers (`schedules.task`, `prompts.define`).
## Isolation contract
When you make a call through a `TriggerClient` instance, the SDK does not look at the process-wide global config, env vars (other than the constructor-time fallback), or the ambient task context. Two instances pointing at different projects can run in the same process — including in parallel under `Promise.all` — without interfering with each other.
That isolation also means a call from inside a task does not automatically inherit the surrounding task's `parentRunId`, `lockToVersion`, or test flag. If you specifically want a call to inherit those (rare — usually you want a clean external trigger), opt in with `inheritContext: true`:
```ts
const sameProject = new TriggerClient({
accessToken: process.env.TRIGGER_SECRET_KEY,
inheritContext: true,
});
```
## When to use what
| Scenario | Recommended |
| ------------------------------------------------------------------------- | ------------------------------------ |
| Single process, single project/env | `configure()` (or env vars only) |
| Single process talking to multiple projects, envs, or branches | `new TriggerClient({...})` per target |
| Short, sequential override (e.g. one batch under a different token) | `auth.withAuth(config, fn)` |
| Inside a task, trigger a run in a different project | `new TriggerClient({...})` |
See [Authentication](/management/authentication) for the underlying token types and the `auth.withAuth` helper.
+65
View File
@@ -0,0 +1,65 @@
---
title: "Management API overview"
sidebarTitle: Overview
description: Using the Trigger.dev management API
---
## Installation
The management API is available through the same `@trigger.dev/sdk` package used in defining and triggering tasks. If you have already installed the package in your project, you can skip this step.
<CodeGroup>
```bash npm
npm i @trigger.dev/sdk@latest
```
```bash pnpm
pnpm add @trigger.dev/sdk@latest
```
```bash yarn
yarn add @trigger.dev/sdk@latest
```
</CodeGroup>
## Usage
All `v3` functionality is provided through the `@trigger.dev/sdk` module. You can import the entire module or individual resources as needed.
```ts
import { configure, runs } from "@trigger.dev/sdk";
configure({
// this is the default and if the `TRIGGER_SECRET_KEY` environment variable is set, can omit calling configure
secretKey: process.env["TRIGGER_SECRET_KEY"],
});
async function main() {
const completedRuns = await runs.list({
limit: 10,
status: ["COMPLETED"],
});
}
main().catch(console.error);
```
### Multiple clients in one process
If a single process needs to talk to more than one Trigger.dev project, environment, or preview branch, use `new TriggerClient({...})` for each target instead of `configure()`. Each instance owns its own auth and config, with no shared global state. See [Multiple SDK clients](/management/multiple-clients) for the full pattern.
```ts
import { TriggerClient } from "@trigger.dev/sdk";
const prod = new TriggerClient({ accessToken: process.env.TRIGGER_PROD_KEY });
const preview = new TriggerClient({
accessToken: process.env.TRIGGER_PREVIEW_KEY,
previewBranch: "signup-flow",
});
const payload = { to: "user@example.com" };
await prod.tasks.trigger("send-email", payload);
await preview.runs.list({ status: ["COMPLETED"] });
```
+4
View File
@@ -0,0 +1,4 @@
---
title: "List runs"
openapi: "v3-openapi GET /api/v1/projects/{projectRef}/runs"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List dashboards"
openapi: "v3-openapi GET /api/v1/query/dashboards"
---
+11
View File
@@ -0,0 +1,11 @@
---
title: "Execute a query"
openapi: "v3-openapi POST /api/v1/query"
---
See the [Query documentation](/observability/query#example-queries) for comprehensive examples including:
- Failed runs analysis
- Task success rates over time
- Cost tracking and optimization
- Performance metrics and percentiles
+4
View File
@@ -0,0 +1,4 @@
---
title: "Get query schema"
openapi: "v3-openapi GET /api/v1/query/schema"
---
@@ -0,0 +1,4 @@
---
title: "Override Concurrency Limit"
openapi: "v3-openapi POST /api/v1/queues/{queueParam}/concurrency/override"
---
@@ -0,0 +1,4 @@
---
title: "Reset Concurrency Limit"
openapi: "v3-openapi POST /api/v1/queues/{queueParam}/concurrency/reset"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List Queues"
openapi: "v3-openapi GET /api/v1/queues"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Pause or Resume Queue"
openapi: "v3-openapi POST /api/v1/queues/{queueParam}/pause"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve Queue"
openapi: "v3-openapi GET /api/v1/queues/{queueParam}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Add tags to a run"
openapi: "v3-openapi POST /api/v1/runs/{runId}/tags"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Cancel run"
openapi: "v3-openapi POST /api/v2/runs/{runId}/cancel"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List runs"
openapi: "v3-openapi GET /api/v1/runs"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Replay run"
openapi: "v3-openapi POST /api/v1/runs/{runId}/replay"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Reschedule run"
openapi: "v3-openapi POST /api/v1/runs/{runId}/reschedule"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve run events"
openapi: "v3-openapi GET /api/v1/runs/{runId}/events"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve run result"
openapi: "v3-openapi GET /api/v1/runs/{runId}/result"
---
+8
View File
@@ -0,0 +1,8 @@
---
title: "Retrieve run trace"
openapi: "v3-openapi GET /api/v1/runs/{runId}/trace"
---
Returns the OpenTelemetry trace subtree for the run you request. The response `trace.rootSpan` is that run's span — not necessarily the trace-wide root — with its descendant spans nested under `children`.
For a child or nested run inside a large trace, this endpoint scopes the tree to that run so you still get a useful subtree even when the full trace has more spans than the platform can return in one response.
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve run"
openapi: "v3-openapi GET /api/v3/runs/{runId}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Update metadata"
openapi: "v3-openapi PUT /api/v1/runs/{runId}/metadata"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Activate Schedule"
openapi: "v3-openapi POST /api/v1/schedules/{schedule_id}/activate"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Create Schedule"
openapi: "v3-openapi POST /api/v1/schedules"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Deactivate Schedule"
openapi: "v3-openapi POST /api/v1/schedules/{schedule_id}/deactivate"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Delete Schedule"
openapi: "v3-openapi DELETE /api/v1/schedules/{schedule_id}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List Schedules"
openapi: "v3-openapi GET /api/v1/schedules"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve Schedule"
openapi: "v3-openapi GET /api/v1/schedules/{schedule_id}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Get timezones"
openapi: "v3-openapi GET /api/v1/timezones"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Update Schedule"
openapi: "v3-openapi PUT /api/v1/schedules/{schedule_id}"
---
+128
View File
@@ -0,0 +1,128 @@
---
title: "Session channels"
sidebarTitle: "Channels"
description: "The raw HTTP endpoints behind a session's .in and .out streams: append records, read them over SSE, and drain them non-streaming."
---
Every session has two durable streams: `.in` carries records from your clients to the task, `.out` carries records from the task back to your clients. The [`sessions` SDK](/ai-chat/sessions) wraps these as `session.in.*` and `session.out.*`. This page documents the underlying HTTP endpoints for callers that aren't using the TypeScript SDK.
All channel endpoints live under `/realtime/v1/sessions/{session}/{io}`, where:
- `{session}` is the session's friendly ID (`session_…`) or your `externalId`. One token authorizes both forms.
- `{io}` is either `in` or `out`.
Authorize requests with a secret key or a [session public token](/management/authentication#session-scopes). The token's scopes decide what you can do — see [Authorization](#authorization) below.
## Append a record
Append a single record to a channel.
```bash Append to .in
curl -X POST "https://api.trigger.dev/realtime/v1/sessions/{session}/in/append" \
-H "Authorization: Bearer $TRIGGER_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Part-Id: 0f8c2b1e-..." \
--data '{"type":"user-message","text":"hello"}'
```
The body is the raw record — any text up to 1MiB (records over the per-record cap return `413`). The response is `{ "ok": true }`.
Set the `X-Part-Id` header to a unique value per record to make the append idempotent: replaying the same `X-Part-Id` does not duplicate the record. Appending to a closed or expired session returns `400`.
<Warning>
Appending to `.out` requires a **secret key**. A session public token (even one with
`write:sessions`) can only append to `.in` — appending to `.out` with a public token returns
`403`. The `.out` stream is the task's to write.
</Warning>
## Read a channel over SSE
Subscribe to a channel as a Server-Sent Events stream. New records are delivered as they arrive.
```bash Read .out
curl -N "https://api.trigger.dev/realtime/v1/sessions/{session}/out" \
-H "Authorization: Bearer $TRIGGER_TOKEN" \
-H "Last-Event-ID: 42" \
-H "Timeout-Seconds: 60"
```
| Header | Direction | Description |
| --- | --- | --- |
| `Last-Event-ID` | request | Resume after this sequence number. Set it to the last `id:` you received to pick up exactly where you left off after a disconnect. |
| `Timeout-Seconds` | request | How long the server holds the stream open with no new records before closing, `1``600`. |
Each SSE event carries:
- `id:` — the record's sequence number. Use the most recent one as `Last-Event-ID` to resume.
- `data:` — a JSON record `{ "data": <record>, "id": <id> }`. For `.out` on a `chat.agent` session, `data` is a UI message chunk (text, reasoning, tool call, or a custom data part).
```text
id: 42
data: {"data":{"type":"text","text":"echo: hello"},"id":42}
```
### Control records
Some `.out` events are **control records** rather than data. A control record has an empty body and carries a `trigger-control` header naming its subtype:
| Subtype | Meaning |
| --- | --- |
| `turn-complete` | The current turn finished. Carries sibling headers `public-access-token` (a refreshed session token), `session-in-event-id`, and `last-event-id`. |
| `upgrade-required` | The session needs to hand off to a run on a newer deployed version. |
Route control records by their subtype instead of treating them as message content. The TypeScript SDK does this for you — `session.out.read` filters control records out of the chunk stream and surfaces them through `onControl`.
## Drain records non-streaming
Fetch a batch of records without holding an SSE connection open. Useful for polling or for reading a tail at startup.
```bash Drain .out
curl "https://api.trigger.dev/realtime/v1/sessions/{session}/out/records?afterEventId=42" \
-H "Authorization: Bearer $TRIGGER_TOKEN"
```
Pass `afterEventId` to return only records after that sequence number; omit it to read from the start of the retained window. The response is:
```json
{
"records": [
{ "data": { "type": "text", "text": "echo: hello" }, "id": 43, "seqNum": 43 }
]
}
```
Each record carries `data`, `id`, `seqNum`, and an optional `headers` array (present on control records). Page forward by passing the highest `seqNum` you received as the next `afterEventId`.
## Authorization
The action you can take depends on your token and the channel:
| Action | Endpoint | Required authorization |
| --- | --- | --- |
| Subscribe (SSE) | `GET .../{io}` | `read:sessions:{id}` — works on both `.in` and `.out` |
| Drain records | `GET .../{io}/records` | `read:sessions:{id}` — works on both `.in` and `.out` |
| Append to `.in` | `POST .../in/append` | `write:sessions:{id}` |
| Append to `.out` | `POST .../out/append` | Secret key only |
Reads work in both directions for a `read:sessions` token. Writes split by direction: a `write:sessions` token can append to `.in`, but `.out` is reserved for the task and requires a secret key. See [session scopes](/management/authentication#session-scopes) for how to mint a token.
## Using the SDK instead
If you're writing TypeScript, the [`sessions` SDK](/ai-chat/sessions) is the ergonomic path. `sessions.open(idOrExternalId)` returns a `SessionHandle` whose `session.in` and `session.out` channels call these endpoints for you, with auto-retry, `Last-Event-ID` resume, and control-record routing built in:
```ts Your backend
import { sessions } from "@trigger.dev/sdk";
const session = sessions.open(chatId);
// append to .in
await session.in.send({ type: "user-message", text: "hello" });
// read .out over SSE
const stream = await session.out.read({ signal: AbortSignal.timeout(30_000) });
for await (const chunk of stream) {
console.log(chunk);
}
```
See [`session.in`](/ai-chat/sessions#session-in-—-clients-→-task) and [`session.out`](/ai-chat/sessions#session-out-—-task-→-clients) for the full handle API.
+4
View File
@@ -0,0 +1,4 @@
---
title: "Close session"
openapi: "v3-openapi POST /api/v1/sessions/{session}/close"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Create session"
openapi: "v3-openapi POST /api/v1/sessions"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List sessions"
openapi: "v3-openapi GET /api/v1/sessions"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve session"
openapi: "v3-openapi GET /api/v1/sessions/{session}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Update session"
openapi: "v3-openapi PATCH /api/v1/sessions/{session}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Batch trigger"
openapi: "v3-openapi POST /api/v1/tasks/batch"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Trigger task batch"
openapi: "v3-openapi POST /api/v1/tasks/{taskIdentifier}/batch"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Trigger"
openapi: "v3-openapi POST /api/v1/tasks/{taskIdentifier}/trigger"
---
@@ -0,0 +1,4 @@
---
title: "Complete a waitpoint token via HTTP callback"
openapi: "v3-openapi POST /api/v1/waitpoints/tokens/{waitpointId}/callback/{callbackHash}"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Complete a waitpoint token"
openapi: "v3-openapi POST /api/v1/waitpoints/tokens/{waitpointId}/complete"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Create a waitpoint token"
openapi: "v3-openapi POST /api/v1/waitpoints/tokens"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "List waitpoint tokens"
openapi: "v3-openapi GET /api/v1/waitpoints/tokens"
---
+4
View File
@@ -0,0 +1,4 @@
---
title: "Retrieve a waitpoint token"
openapi: "v3-openapi GET /api/v1/waitpoints/tokens/{waitpointId}"
---