chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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);
|
||||
}
|
||||
```
|
||||
@@ -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).
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -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"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve a batch"
|
||||
openapi: "v3-openapi GET /api/v1/batches/{batchId}"
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "Stream batch items"
|
||||
openapi: "openapi POST /api/v3/batches/{batchId}/items"
|
||||
---
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Abort bulk action"
|
||||
openapi: "v3-openapi POST /api/v1/bulk-actions/{bulkActionId}/abort"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create bulk action"
|
||||
openapi: "v3-openapi POST /api/v1/bulk-actions"
|
||||
---
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Promote deployment"
|
||||
openapi: "v3-openapi POST /api/v1/deployments/{version}/promote"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get deployment"
|
||||
openapi: "v3-openapi GET /api/v1/deployments/{deploymentId}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create Env Var"
|
||||
openapi: "v3-openapi POST /api/v1/projects/{projectRef}/envvars/{env}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete Env Var"
|
||||
openapi: "v3-openapi DELETE /api/v1/projects/{projectRef}/envvars/{env}/{name}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Import Env Vars"
|
||||
openapi: "v3-openapi POST /api/v1/projects/{projectRef}/envvars/{env}/import"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List Env Vars"
|
||||
openapi: "v3-openapi GET /api/v1/projects/{projectRef}/envvars/{env}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve Env Var"
|
||||
openapi: "v3-openapi GET /api/v1/projects/{projectRef}/envvars/{env}/{name}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Update Env Var"
|
||||
openapi: "v3-openapi PUT /api/v1/projects/{projectRef}/envvars/{env}/{name}"
|
||||
---
|
||||
@@ -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>
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Ignore an error"
|
||||
openapi: "v3-openapi POST /api/v1/errors/{errorId}/ignore"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List errors"
|
||||
openapi: "v3-openapi GET /api/v1/errors"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Resolve an error"
|
||||
openapi: "v3-openapi POST /api/v1/errors/{errorId}/resolve"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve an error"
|
||||
openapi: "v3-openapi GET /api/v1/errors/{errorId}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Unresolve an error"
|
||||
openapi: "v3-openapi POST /api/v1/errors/{errorId}/unresolve"
|
||||
---
|
||||
@@ -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.
|
||||
@@ -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"] });
|
||||
```
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List runs"
|
||||
openapi: "v3-openapi GET /api/v1/projects/{projectRef}/runs"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List dashboards"
|
||||
openapi: "v3-openapi GET /api/v1/query/dashboards"
|
||||
---
|
||||
@@ -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
|
||||
@@ -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"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List Queues"
|
||||
openapi: "v3-openapi GET /api/v1/queues"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Pause or Resume Queue"
|
||||
openapi: "v3-openapi POST /api/v1/queues/{queueParam}/pause"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve Queue"
|
||||
openapi: "v3-openapi GET /api/v1/queues/{queueParam}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Add tags to a run"
|
||||
openapi: "v3-openapi POST /api/v1/runs/{runId}/tags"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Cancel run"
|
||||
openapi: "v3-openapi POST /api/v2/runs/{runId}/cancel"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List runs"
|
||||
openapi: "v3-openapi GET /api/v1/runs"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Replay run"
|
||||
openapi: "v3-openapi POST /api/v1/runs/{runId}/replay"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Reschedule run"
|
||||
openapi: "v3-openapi POST /api/v1/runs/{runId}/reschedule"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve run events"
|
||||
openapi: "v3-openapi GET /api/v1/runs/{runId}/events"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve run result"
|
||||
openapi: "v3-openapi GET /api/v1/runs/{runId}/result"
|
||||
---
|
||||
@@ -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.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve run"
|
||||
openapi: "v3-openapi GET /api/v3/runs/{runId}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Update metadata"
|
||||
openapi: "v3-openapi PUT /api/v1/runs/{runId}/metadata"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Activate Schedule"
|
||||
openapi: "v3-openapi POST /api/v1/schedules/{schedule_id}/activate"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create Schedule"
|
||||
openapi: "v3-openapi POST /api/v1/schedules"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Deactivate Schedule"
|
||||
openapi: "v3-openapi POST /api/v1/schedules/{schedule_id}/deactivate"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete Schedule"
|
||||
openapi: "v3-openapi DELETE /api/v1/schedules/{schedule_id}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List Schedules"
|
||||
openapi: "v3-openapi GET /api/v1/schedules"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve Schedule"
|
||||
openapi: "v3-openapi GET /api/v1/schedules/{schedule_id}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get timezones"
|
||||
openapi: "v3-openapi GET /api/v1/timezones"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Update Schedule"
|
||||
openapi: "v3-openapi PUT /api/v1/schedules/{schedule_id}"
|
||||
---
|
||||
@@ -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.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Close session"
|
||||
openapi: "v3-openapi POST /api/v1/sessions/{session}/close"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create session"
|
||||
openapi: "v3-openapi POST /api/v1/sessions"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List sessions"
|
||||
openapi: "v3-openapi GET /api/v1/sessions"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve session"
|
||||
openapi: "v3-openapi GET /api/v1/sessions/{session}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Update session"
|
||||
openapi: "v3-openapi PATCH /api/v1/sessions/{session}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Batch trigger"
|
||||
openapi: "v3-openapi POST /api/v1/tasks/batch"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Trigger task batch"
|
||||
openapi: "v3-openapi POST /api/v1/tasks/{taskIdentifier}/batch"
|
||||
---
|
||||
@@ -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}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Complete a waitpoint token"
|
||||
openapi: "v3-openapi POST /api/v1/waitpoints/tokens/{waitpointId}/complete"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a waitpoint token"
|
||||
openapi: "v3-openapi POST /api/v1/waitpoints/tokens"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List waitpoint tokens"
|
||||
openapi: "v3-openapi GET /api/v1/waitpoints/tokens"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Retrieve a waitpoint token"
|
||||
openapi: "v3-openapi GET /api/v1/waitpoints/tokens/{waitpointId}"
|
||||
---
|
||||
Reference in New Issue
Block a user