Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,10 @@
"management/runs/replay",
"management/runs/cancel",
"management/runs/reschedule",
"management/runs/update-metadata"
"management/runs/update-metadata",
"management/runs/add-tags",
"management/runs/retrieve-events",
"management/runs/retrieve-trace"
]
},
{
Expand Down
4 changes: 4 additions & 0 deletions docs/management/runs/add-tags.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: "Add tags to a run"
openapi: "v3-openapi POST /api/v1/runs/{runId}/tags"
---
4 changes: 4 additions & 0 deletions docs/management/runs/retrieve-events.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: "Retrieve run events"
openapi: "v3-openapi GET /api/v1/runs/{runId}/events"
---
4 changes: 4 additions & 0 deletions docs/management/runs/retrieve-trace.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: "Retrieve run trace"
openapi: "v3-openapi GET /api/v1/runs/{runId}/trace"
---
318 changes: 311 additions & 7 deletions docs/v3-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,250 @@ paths:

const handle = await runs.replay("run_1234");

"/api/v1/runs/{runId}/tags":
parameters:
- $ref: "#/components/parameters/runId"
post:
operationId: add_run_tags_v1
summary: Add tags to a run
description: Adds one or more tags to a run. Runs can have a maximum of 10 tags. Duplicate tags are ignored.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- tags
properties:
tags:
$ref: "#/components/schemas/RunTags"
responses:
"200":
description: Successful request
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: "Successfully set 2 new tags."
"400":
description: Invalid request
content:
application/json:
schema:
type: object
properties:
error:
type: string
"401":
description: Unauthorized request
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- Invalid or Missing API Key
Comment on lines +410 to +411
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix API Key capitalization — should be API key (lowercase k).

All other 401 error enum values in this spec use "Invalid or Missing API key" (lowercase k): lines 340, 478, 615, 764, etc. The add-tags endpoint uses a capital K, which is inconsistent and could break exact-string-match error handling in clients.

🔧 Proposed fix
                     enum:
-                      - Invalid or Missing API Key
+                      - Invalid or Missing API key
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/v3-openapi.yaml` around lines 410 - 411, Update the 401 error enum for
the add-tags operation so the string matches other entries: change the value
"Invalid or Missing API Key" to "Invalid or Missing API key" (lowercase k) so
the enum under the add-tags endpoint's 401 response is consistent with the other
401 error enum values.

"422":
description: Too many tags
content:
application/json:
schema:
type: object
properties:
error:
type: string
description: Runs can only have 10 tags.
tags:
- runs
security:
- secretKey: []
x-codeSamples:
- lang: typescript
label: SDK
source: |-
import { runs } from "@trigger.dev/sdk";

await runs.addTags("run_1234", ["tag-1", "tag-2"]);
- lang: typescript
label: Fetch
source: |-
await fetch("https://api.trigger.dev/api/v1/runs/run_1234/tags", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRIGGER_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ tags: ["tag-1", "tag-2"] }),
});

"/api/v1/runs/{runId}/trace":
parameters:
- $ref: "#/components/parameters/runId"
get:
operationId: get_run_trace_v1
summary: Retrieve run trace
description: Returns the full OTel trace tree for a run, including all spans and their children.
responses:
"200":
description: Successful request
content:
application/json:
schema:
type: object
properties:
trace:
type: object
properties:
traceId:
type: string
description: The OTel trace ID.
rootSpan:
$ref: "#/components/schemas/SpanDetailedSummary"
"401":
description: Unauthorized request
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- Invalid or Missing API key
"404":
description: Resource not found
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- Run not found
- Trace not found
tags:
- runs
security:
- secretKey: []
x-codeSamples:
- lang: typescript
source: |-
const response = await fetch("https://api.trigger.dev/api/v1/runs/run_1234/trace", {
headers: {
Authorization: `Bearer ${process.env.TRIGGER_SECRET_KEY}`,
},
});

const { trace } = await response.json();

"/api/v1/runs/{runId}/events":
parameters:
- $ref: "#/components/parameters/runId"
get:
operationId: get_run_events_v1
summary: Retrieve run events
description: Returns all OTel span events for a run. Useful for debugging and observability.
responses:
"200":
description: Successful request
content:
application/json:
schema:
type: object
properties:
events:
type: array
items:
Comment on lines +521 to +523
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add maxItems to the events array or document the absence of a limit.

The events array has no upper bound, which may return unbounded payloads for long-running or highly-instrumented tasks. If the server enforces a cap, document it with maxItems; if not, consider adding a note in the description that results can be large.

This was also flagged by Checkov (CKV_OPENAPI_21).

🔧 Proposed fix (if a server-side limit exists, e.g. 10,000)
               events:
                 type: array
+                maxItems: 10000
                 items:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/v3-openapi.yaml` around lines 521 - 523, The OpenAPI schema for the
events array currently lacks an upper bound (the "events" property), which
triggers Checkov CKV_OPENAPI_21 and may allow unbounded payloads; update the
schema for the "events" array by either adding a sensible maxItems (e.g.,
maxItems: 10000) to enforce a server-side cap on returned items or, if no cap
exists, add a clear description on the "events" array indicating that results
may be large/unbounded and documenting any pagination behavior or server limits;
modify the "events" array schema block in docs/v3-openapi.yaml accordingly
(adjust the items section to include maxItems or a description) so the contract
explicitly states the limit or lack thereof.

type: object
properties:
spanId:
type: string
description: The span ID of the event.
parentId:
type: string
nullable: true
description: The parent span ID, if any.
runId:
type: string
nullable: true
description: The run ID associated with this event.
message:
type: string
description: The event message.
startTime:
type: string
description: The start time of the event as a bigint string (nanoseconds since epoch).
Comment on lines +540 to +542
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, examine the YAML file around lines 540-542
sed -n '535,550p' docs/v3-openapi.yaml

Repository: triggerdotdev/trigger.dev

Length of output: 885


🏁 Script executed:

# Then examine the YAML file around lines 2495-2498
sed -n '2490,2505p' docs/v3-openapi.yaml

Repository: triggerdotdev/trigger.dev

Length of output: 606


🏁 Script executed:

# Search for all startTime definitions in the YAML to understand the full context
rg -n "startTime:" docs/v3-openapi.yaml | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 135


🏁 Script executed:

# Get more context to identify which schema/endpoint each startTime belongs to
sed -n '500,542p' docs/v3-openapi.yaml | grep -E "(^[a-zA-Z]|startTime:)" | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 103


🏁 Script executed:

# Get more context for the second startTime
sed -n '2450,2500p' docs/v3-openapi.yaml | grep -E "(^[a-zA-Z]|startTime:)" | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 91


🏁 Script executed:

# Read section to identify the schema for startTime at line 540
sed -n '480,542p' docs/v3-openapi.yaml

Repository: triggerdotdev/trigger.dev

Length of output: 2275


🏁 Script executed:

# Read section to identify the schema for startTime at line 2495
sed -n '2420,2505p' docs/v3-openapi.yaml

Repository: triggerdotdev/trigger.dev

Length of output: 3017


🏁 Script executed:

# Search for tests or code that calls the events endpoint
rg -i "get_run_events\|/events" --type ts --type js -A 5 | head -50

Repository: triggerdotdev/trigger.dev

Length of output: 51


🏁 Script executed:

# Search for any documentation or comments about the startTime format
rg -i "nanoseconds since epoch|bigint string" -B 2 -A 2

Repository: triggerdotdev/trigger.dev

Length of output: 915


🏁 Script executed:

# Check if there are type definitions or implementation files that clarify the format
fd -t f "types\|schema\|interface" -e ts -e js | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 51


🏁 Script executed:

# Examine the ClickHouse event repository to see actual serialization
sed -n '1,100p' apps/webapp/app/v3/eventRepository/clickhouseEventRepository.server.ts

Repository: triggerdotdev/trigger.dev

Length of output: 3370


🏁 Script executed:

# Search for how SpanDetailedSummary is actually serialized/returned
rg -i "SpanDetailedSummary" --type ts --type js -B 3 -A 10 | head -80

Repository: triggerdotdev/trigger.dev

Length of output: 6779


🏁 Script executed:

# Find the events endpoint handler code
rg -i "get_run_events|/api/v1/runs.*events" --type ts --type js -B 5 -A 20 | head -100

Repository: triggerdotdev/trigger.dev

Length of output: 1874


🏁 Script executed:

# Search for where events are serialized/returned to the client
rg -i "return.*events\|serialize.*event" apps/webapp/app/v3 --type ts -B 2 -A 5 | head -80

Repository: triggerdotdev/trigger.dev

Length of output: 51


🏁 Script executed:

# Look at the actual event structure to see how startTime is handled
rg -i "type.*event\|interface.*event" apps/webapp/app/v3/eventRepository/eventRepository.types.ts -A 15 | head -100

Repository: triggerdotdev/trigger.dev

Length of output: 51


🏁 Script executed:

# Search for the server-side route handler
find apps -type f -name "*.ts" -o -name "*.js" | xargs rg -l "get_run_events|/events" | head -10

Repository: triggerdotdev/trigger.dev

Length of output: 109


🏁 Script executed:

# Look for routes or handlers
fd -t f "route\|handler" -e ts -e js apps/webapp | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 51


🏁 Script executed:

# Search for where events endpoint returns data
rg -i "events.*startTime|startTime.*nanoseconds" --type ts -B 5 -A 5

Repository: triggerdotdev/trigger.dev

Length of output: 27998


🏁 Script executed:

# Search for the actual events endpoint route/handler
find apps/webapp -type f \( -name "*.ts" -o -name "*.tsx" \) | xargs rg -l "runId.*events|/api/v1" | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 398


🏁 Script executed:

# Look in routes directory
fd -t f "route" apps/webapp/app -e ts -e tsx | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 1700


🏁 Script executed:

# Search for any JSON serialization or response formatting for events
rg -i "json.stringify.*event|response.*event" apps/webapp/app/v3 --type ts -B 3 -A 3 | head -60

Repository: triggerdotdev/trigger.dev

Length of output: 2177


🏁 Script executed:

# Look for api routes specifically for runs endpoint
fd -t f "api" apps/webapp/app/routes -e ts | xargs grep -l "runs.*events\|/api/v1" 2>/dev/null

Repository: triggerdotdev/trigger.dev

Length of output: 163


🏁 Script executed:

# Search for where events are fetched and returned as JSON
rg -i "getRunEvents\|list.*event" apps/webapp/app/routes --type ts -B 5 -A 10

Repository: triggerdotdev/trigger.dev

Length of output: 51


🏁 Script executed:

# Look for any response.json or return statements in api routes
find apps/webapp/app/routes -name "*.ts" -type f | head -10 | xargs cat | grep -A 10 "json\|events" | head -40

Repository: triggerdotdev/trigger.dev

Length of output: 1378


🏁 Script executed:

# Try searching for files containing both "runs" and "events" in routes
find apps/webapp/app/routes -type f -name "*.ts" | xargs grep -l "events" 2>/dev/null | head -10

Repository: triggerdotdev/trigger.dev

Length of output: 185


🏁 Script executed:

# Search for the actual route file by pattern matching
fd "runs" apps/webapp/app/routes -e ts | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 1232


🏁 Script executed:

# Try a broader search for where events are formatted/returned
rg -i "startTime.*string|nanosecond.*event" apps/webapp --type ts -B 3 -A 3 | head -80

Repository: triggerdotdev/trigger.dev

Length of output: 7356


🏁 Script executed:

# Read the events endpoint handler
cat apps/webapp/app/routes/api.v1.runs.$runId.events.ts

Repository: triggerdotdev/trigger.dev

Length of output: 146


🏁 Script executed:

# Find and read the events endpoint file
fd "events.ts" apps/webapp/app/routes | xargs cat

Repository: triggerdotdev/trigger.dev

Length of output: 1982


🏁 Script executed:

# Search for getRunEvents implementation
rg -i "getRunEvents" apps/webapp --type ts -B 2 -A 15 | head -100

Repository: triggerdotdev/trigger.dev

Length of output: 8723


🏁 Script executed:

# Search for RunPreparedEvent type definition
rg -i "type.*RunPreparedEvent|interface.*RunPreparedEvent" apps/webapp --type ts -A 20 | head -80

Repository: triggerdotdev/trigger.dev

Length of output: 4575


🏁 Script executed:

# Search for PreparedEvent type definition
rg -i "type.*PreparedEvent|interface.*PreparedEvent" apps/webapp --type ts -A 25 | head -100

Repository: triggerdotdev/trigger.dev

Length of output: 6508


🏁 Script executed:

# Verify QueriedEvent type definition to confirm startTime is Date
rg -i "type.*QueriedEvent|interface.*QueriedEvent" apps/webapp/app/v3/eventRepository/eventRepository.types.ts -A 30

Repository: triggerdotdev/trigger.dev

Length of output: 1659


Fix OpenAPI spec: events endpoint startTime should declare format: date-time, not "bigint string (nanoseconds since epoch)"

The inconsistency is real. Both endpoints serialize startTime as ISO 8601 date-time strings, but the OpenAPI spec at line 540 incorrectly describes it as a nanoseconds bigint string. The events endpoint returns RunPreparedEvent[], which has startTime: Date (inherited from QueriedEvent). When serialized to JSON, JavaScript Date objects become ISO 8601 strings—matching the format: date-time declared at line 2495 for SpanDetailedSummary. Update line 540 to remove the misleading nanoseconds description, add format: date-time, and align the documentation with actual behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/v3-openapi.yaml` around lines 540 - 542, The OpenAPI schema for the
events endpoint defines startTime with an incorrect description ("bigint string
(nanoseconds since epoch)"); update the startTime property used by
RunPreparedEvent[]/QueriedEvent to match runtime serialization by removing the
nanoseconds description and adding format: date-time (type: string, format:
date-time) so it aligns with other schemas like SpanDetailedSummary and actual
ISO 8601 Date serialization.

duration:
type: number
description: The duration of the event in nanoseconds.
isError:
type: boolean
description: Whether this event represents an error.
isPartial:
type: boolean
description: Whether this event is partial (still in progress).
isCancelled:
type: boolean
description: Whether this event was cancelled.
level:
type: string
enum: [TRACE, DEBUG, LOG, INFO, WARN, ERROR]
description: The log level of the event.
kind:
type: string
enum: [UNSPECIFIED, INTERNAL, SERVER, CLIENT, PRODUCER, CONSUMER, UNRECOGNIZED, LOG]
description: The kind of span event.
attemptNumber:
type: number
nullable: true
description: The attempt number this event belongs to.
taskSlug:
type: string
description: The task identifier.
"401":
description: Unauthorized request
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- Invalid or Missing API key
"404":
description: Resource not found
content:
application/json:
schema:
type: object
properties:
error:
type: string
enum:
- Run not found
tags:
- runs
security:
- secretKey: []
x-codeSamples:
- lang: typescript
source: |-
const response = await fetch("https://api.trigger.dev/api/v1/runs/run_1234/events", {
headers: {
Authorization: `Bearer ${process.env.TRIGGER_SECRET_KEY}`,
},
});

const { events } = await response.json();

"/api/v1/runs/{runId}/metadata":
parameters:
- $ref: "#/components/parameters/runId"
Expand Down Expand Up @@ -2176,6 +2420,70 @@ components:
configure({ accessToken: "tr_pat_1234" });
```
schemas:
RunTag:
type: string
maxLength: 128
description: A single run tag. Must be less than 128 characters.
example: "user_123456"
RunTags:
oneOf:
- $ref: "#/components/schemas/RunTag"
- type: array
items:
$ref: "#/components/schemas/RunTag"
maxItems: 10
uniqueItems: true
example: ["user_123456", "product_4629101"]
description: One or more tags to attach to a run. Runs can have a maximum of 10 tags.
SpanDetailedSummary:
type: object
properties:
id:
type: string
description: The span ID.
parentId:
type: string
nullable: true
description: The parent span ID, if any.
runId:
type: string
description: The run ID this span belongs to.
data:
type: object
properties:
message:
type: string
description: The span message.
taskSlug:
type: string
description: The task identifier, if applicable.
startTime:
type: string
format: date-time
description: The start time of the span.
duration:
type: number
description: The duration of the span in nanoseconds.
isError:
type: boolean
isPartial:
type: boolean
isCancelled:
type: boolean
level:
type: string
enum: [TRACE, DEBUG, LOG, INFO, WARN, ERROR]
attemptNumber:
type: number
nullable: true
properties:
type: object
description: Arbitrary OTel attributes attached to the span.
children:
type: array
description: Nested child spans. Each child has the same structure as the parent span.
items:
$ref: "#/components/schemas/SpanDetailedSummary"
TriggerTaskResponse:
type: object
properties:
Expand Down Expand Up @@ -2350,18 +2658,14 @@ components:
delay:
$ref: "#/components/schemas/Delay"
tags:
type:
- array
- string
example: ["user_123456", "product_4629101"]
allOf:
- $ref: "#/components/schemas/RunTags"
description: |
Tags to attach to the run. Tags can be used to filter runs in the dashboard and using the SDK.

You can set up to 5 tags per run, they must be less than 64 characters each.
You can set up to 10 tags per run, each must be less than 128 characters.

We recommend prefixing tags with a namespace using an underscore or colon, like `user_1234567` or `org:9876543`. Stripe uses underscores.
items:
type: string
machine:
type: string
enum:
Expand Down