| title | Wait for token |
|---|---|
| description | Wait until a token is completed using waitpoint tokens. |
Waitpoint tokens pause task runs until you complete the token. They're commonly used for approval workflows and other scenarios where you need to wait for external confirmation, such as human-in-the-loop processes.
You can complete a token using the SDK or by making a POST request to the token's URL.
To get started using wait tokens, you need to first create a token using the wait.createToken function:
import { wait } from "@trigger.dev/sdk";
// This can be called anywhere in your codebase, either in a task or in your backend code
const token = await wait.createToken({
timeout: "10m", // you can optionally specify a timeout for the token
});Once you have a token, you can wait for it to be completed using the wait.forToken function:
import { wait } from "@trigger.dev/sdk";
type ApprovalToken = {
status: "approved" | "rejected";
};
// This must be called inside a task run function
const result = await wait.forToken<ApprovalToken>(tokenId);
if (result.ok) {
console.log("Token completed", result.output.status); // "approved" or "rejected"
} else {
console.log("Token timed out", result.error);
}To complete a token, you can use the wait.completeToken function:
import { wait } from "@trigger.dev/sdk";
// This can be called anywhere in your codebase, or from an external service,
// passing in the token ID and the output of the token
await wait.completeToken<ApprovalToken>(tokenId, {
status: "approved",
});Or you can make an HTTP POST request to the url it returns. This is an HTTP callback:
import { wait } from "@trigger.dev/sdk";
const token = await wait.createToken({
timeout: "10m",
});
const call = await replicate.predictions.create({
version: "27b93a2413e7f36cd83da926f3656280b2931564ff050bf9575f1fdf9bcd7478",
input: {
prompt: "A painting of a cat by Andy Warhol",
},
// pass the provided URL to Replicate's webhook, so they can "callback"
webhook: token.url,
webhook_events_filter: ["completed"],
});
const prediction = await wait.forToken<Prediction>(token).unwrap();
// unwrap() throws a timeout error or returns the result 👆Create a waitpoint token.
The createToken function accepts an object with the following properties:
The createToken function returns a token object with the following properties:
The JSON body of the POST request will be used as the output of the token. If there's no body the output will be an empty object {}.
import { wait } from "@trigger.dev/sdk";
const token = await wait.createToken({
timeout: "10m",
idempotencyKey: "my-idempotency-key",
tags: ["my-tag"],
});Complete a waitpoint token.
The ID of the token to complete. The data to complete the token with.The completeToken function returns an object with the following properties:
import { wait } from "@trigger.dev/sdk";
await wait.completeToken<ApprovalToken>(tokenId, {
status: "approved",
});You can complete a token using a raw HTTP request or from another language.
curl -X POST "https://api.trigger.dev/api/v1/waitpoints/tokens/{tokenId}/complete" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"data": { "status": "approved"}}'import requests
response = requests.post(
"https://api.trigger.dev/api/v1/waitpoints/tokens/{tokenId}/complete",
headers={"Authorization": f"Bearer {token}"},
json={"data": { "status": "approved"}}
)require "net/http"
uri = URI("https://api.trigger.dev/api/v1/waitpoints/tokens/{tokenId}/complete")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer {token}"
request["Content-Type"] = "application/json"
request.body = JSON.generate({ data: { status: "approved" } })
response = http.request(request)package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
url := "https://api.trigger.dev/api/v1/waitpoints/tokens/{tokenId}/complete"
payload := map[string]interface{}{
"data": map[string]interface{}{
"status": "approved",
},
}
jsonData, err := json.Marshal(payload)
if err != nil {
fmt.Println("Error marshalling payload:", err)
return
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
req.Header.Set("Authorization", "Bearer {token}")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
fmt.Println("Response status:", resp.Status)
}Wait for a token to be completed.
The token to wait for.The forToken function returns a result object with the following properties:
We provide a handy .unwrap() method that will throw an error if the result is not ok. This means your happy path is a lot cleaner.
const approval = await wait.forToken<ApprovalToken>(tokenId).unwrap();
// unwrap means an error will throw if the waitpoint times out 👆
// This is the actual data you sent to the token now, not a result object
console.log("Approval", approval);import { wait } from "@trigger.dev/sdk";
const result = await wait.forToken<ApprovalToken>(tokenId);
if (result.ok) {
console.log("Token completed", result.output.status); // "approved" or "rejected"
} else {
console.log("Token timed out", result.error);
}List all tokens for an environment.
The listTokens function accepts an object with the following properties:
The listTokens function returns a list of tokens that can be iterated over using a for-await-of loop.
Each token is an object with the following properties:
The ID of the token. The URL of the token. This is the URL you can make a POST request to in order to complete the token.The JSON body of the POST request will be used as the output of the token. If there's no body the output will be an empty object {}.
import { wait } from "@trigger.dev/sdk";
const tokens = await wait.listTokens({
status: "COMPLETED",
tags: ["user:123"],
});
for await (const token of tokens) {
console.log(token);
}Retrieve a token by ID.
The ID of the token to retrieve.The retrieveToken function returns a token object with the following properties:
The JSON body of the POST request will be used as the output of the token. If there's no body the output will be an empty object {}.
import { wait } from "@trigger.dev/sdk";
const token = await wait.retrieveToken(tokenId);
console.log(token);You can pass an idempotency key to any wait function, allowing you to skip waits if the same idempotency key is used again. This can be useful if you want to skip waits when retrying a task, for example:
// Specify the idempotency key and TTL when creating a wait token
const token = await wait.createToken({
idempotencyKey: "my-idempotency-key",
idempotencyKeyTTL: "1h",
});