resumeHook
Resume a paused workflow by sending a payload to a hook token or hook object.
Resumes a workflow run by sending a payload to a hook identified by its token or an existing hook object.
resumeHook() returns the resumed hook entity, not the workflow's eventual return value. This is useful when you need the associated runId, hookId, or hook metadata immediately after resumption.
It creates a hook_received event and re-queues the workflow so execution can continue. Use resumeHook() for hooks created with createHook(), whether the token was explicitly set or auto-generated. For hooks created with createWebhook(), use resumeWebhook() instead.
resumeHook is a runtime function that must be called from outside a workflow function.
import { resumeHook } from "workflow/api";
export async function POST(request: Request) {
const { token, data } = await request.json();
try {
const hook = await resumeHook(token, data);
console.info(JSON.stringify({
event: "workflow.hook.resumed",
token: hook.token,
hookId: hook.hookId,
runId: hook.runId,
}));
return Response.json({
runId: hook.runId,
});
} catch (error) {
if (error instanceof Error && error.name === "HookNotFoundError") {
console.warn(JSON.stringify({
event: "workflow.hook.not_found",
token,
}));
return Response.json(
{ error: "Hook not found", token },
{ status: 404 }
);
}
console.error(JSON.stringify({
event: "workflow.hook.resume_failed",
token,
error: error instanceof Error ? error.message : String(error),
}));
return Response.json(
{ error: "Failed to resume hook" },
{ status: 500 }
);
}
}API Signature
Parameters
| Name | Type | Description |
|---|---|---|
tokenOrHook | string | Hook | The unique token identifying the hook, or the hook object itself |
payload | NonNullable<T> | The data payload to send to the hook |
encryptionKeyOverride | CryptoKey |
Returns
Returns a Promise<Hook> that resolves to:
| Name | Type | Description |
|---|---|---|
runId | string | The unique identifier of the workflow run this hook belongs to. |
hookId | string | The unique identifier of this hook within the workflow run. |
token | string | The secret token used to reference this hook. |
ownerId | string | The owner ID (team or user) that owns this hook. |
projectId | string | The project ID this hook belongs to. |
environment | string | The environment (e.g., "production", "preview", "development") where this hook was created. |
createdAt | Date | The timestamp when this hook was created. |
metadata | unknown | Optional metadata associated with the hook, set when the hook was created. |
specVersion | number | The spec version when this hook was created. |
isWebhook | boolean | Whether this hook is resumable via the public webhook endpoint. undefined = legacy (treated as true for backwards compat). |
Error Behavior
A missing hook token is only one failure mode. resumeHook() can also fail while dehydrating the payload, creating the hook_received event, or re-queueing the workflow. In HTTP handlers, map missing hooks to 404 and unexpected failures to 500 so operational failures stay visible.
resumeHook() resolves to the hook record that was resumed. Use hook.runId with getRun() if you want to inspect the workflow after resumption; it does not wait for the workflow to finish.
Examples
Basic API Route
Using resumeHook in a basic API route to resume a hook:
import { resumeHook } from "workflow/api";
export async function POST(request: Request) {
const { token, data } = await request.json();
try {
const hook = await resumeHook(token, data);
return Response.json({
success: true,
runId: hook.runId
});
} catch (error) {
if (error instanceof Error && error.name === "HookNotFoundError") {
return Response.json({ error: "Hook not found" }, { status: 404 });
}
return Response.json({ error: "Failed to resume hook" }, { status: 500 });
}
}With Type Safety
Defining a payload type and using resumeHook to resume a hook with type safety:
import { resumeHook } from "workflow/api";
type ApprovalPayload = {
approved: boolean;
comment: string;
};
export async function POST(request: Request) {
const { token, approved, comment } = await request.json();
try {
const hook = await resumeHook<ApprovalPayload>(token, {
approved,
comment,
});
return Response.json({ runId: hook.runId });
} catch (error) {
if (error instanceof Error && error.name === "HookNotFoundError") {
return Response.json({ error: "Hook not found" }, { status: 404 });
}
return Response.json({ error: "Failed to resume hook" }, { status: 500 });
}
}Server Action (Next.js)
Using resumeHook in Next.js server actions to resume a hook:
"use server";
import { resumeHook } from "workflow/api";
export async function approveRequest(token: string, approved: boolean) {
try {
const hook = await resumeHook(token, { approved });
return hook.runId;
} catch (error) {
throw new Error("Failed to resume hook");
}
}Passing a Hook Object
Instead of a token string, you can pass a Hook object directly (e.g. one returned by getHookByToken()):
import { getHookByToken, resumeHook } from "workflow/api";
export async function POST(request: Request) {
const { token, data } = await request.json();
try {
const hook = await getHookByToken(token);
// Validate metadata before resuming
console.log("Hook metadata:", hook.metadata);
const resumedHook = await resumeHook(hook, data);
return Response.json({ success: true, runId: resumedHook.runId });
} catch (error) {
if (error instanceof Error && error.name === "HookNotFoundError") {
return Response.json({ error: "Hook not found" }, { status: 404 });
}
return Response.json({ error: "Failed to resume hook" }, { status: 500 });
}
}Related Functions
getHookByToken()- Get hook details before resuming.createHook()- Create a hook in a workflow.defineHook()- Type-safe hook helper.