Creating actions
This guide shows you how to register a Forte Action, test it, and inspect its delivery history. An Action calls a service path on a schedule or once at a set time.
Actions are available to all accounts during Beta. You can create and manage them from the console, CLI, or server-side SDK; interfaces and limits may change before GA.
Prerequisites
- A Forte Project with at least one Service: an action targets a service in the project, not an arbitrary URL.
- A path on that service that accepts a
POSTrequest. - For CLI/SDK use, the Forte CLI installed (
forte login) or a project API token (FORTE_API_TOKEN).
1. Create your action
In the console
Open Actions in the sidebar and choose Create Action. Give it a name, pick the target service and the path to call on it, then pick a schedule:
- Recurring: enter a cron expression (for example,
0 9 * * *for 9:00 every day) and a timezone (for example,America/New_York). Optionally set an active window. - One-time: pick the date and time it should run once.
Toggle Retry on failure if Forte should retry when your endpoint errors, and leave Enabled on to start the schedule immediately.
With the CLI
# Recurring: 9:00 AM every weekday, New York time, with retries
forte actions create <projectId> \
--name nightly-report \
--service svc_<id> --path /jobs/nightly \
--schedule recurring \
--cron "0 9 * * 1-5" \
--timezone America/New_York \
--retryable
# One-time: run once at a specific instant (ISO 8601)
forte actions create <projectId> \
--name launch-ping \
--service svc_<id> --path /hooks/launch \
--schedule one-time \
--at 2026-07-01T16:00:00ZOmit <projectId> and the CLI prompts you to pick one.
With the SDK (server-side)
import { ForteClient } from "@forteplatforms/sdk";
const forte = new ForteClient({ apiToken: process.env.FORTE_API_TOKEN });
const action = await forte.projects.createAction({
projectId,
createActionRequest: {
name: "nightly-report",
targetServiceId: "svc_...",
targetPath: "/jobs/nightly",
requestBody: JSON.stringify({ job: "nightly-report" }),
scheduleType: "RECURRING",
cronExpression: "0 9 * * 1-5",
timezone: "America/New_York",
retryable: true,
},
});A recurring action runs at most once per minute. Schedules that would fire more often are rejected.
2. Handle each request
When the action runs, Forte sends a POST to your URL with your body and three headers. Verify the trusted header, dedupe on the invocation ID, and return 2xx quickly:
app.post("/hooks/nightly", (req, res) => {
// 1. Confirm the call really came from Forte.
if (req.header("X-Forte-Trusted") !== "1") {
return res.sendStatus(401);
}
// 2. Make the handler idempotent: Forte may retry.
const invocationId = req.header("X-Forte-Action-Invocation-Id");
if (alreadyProcessed(invocationId)) {
return res.sendStatus(200);
}
// 3. Acknowledge fast; do slow work in the background.
enqueueWork(req.body);
res.sendStatus(200);
});3. Test with Invoke now
You don't need to wait for the schedule. Trigger a one-off run to confirm your endpoint works:
forte actions invoke <projectId> <actionId>await forte.projects.createActionInvocation({ projectId, actionId });This creates a manual invocation immediately, just like a scheduled run.
4. Inspect each invocation
Forte records each run as an invocation with its status, attempts, response code, and timing.
forte actions invocations <projectId> <actionId>const { items } = await forte.projects.listActionInvocations({ projectId, actionId });In the console, open the action to see recent invocations, or View all for the full paginated history. A FAILED invocation means your endpoint errored after all attempts; a MISSED invocation means Forte didn't run that occurrence on time.
5. Pause, update, or cancel
forte actions update <projectId> <actionId> --disable # pause the schedule
forte actions update <projectId> <actionId> --enable # resume
forte actions update <projectId> <actionId> --cron "0 */6 * * *" # change schedule
forte actions cancel <projectId> <actionId> <invocationId> # cancel a pending invocation
forte actions delete <projectId> <actionId> # remove the action and its historyPausing keeps the action and its history but stops new runs until you resume it.
Next steps
- Read the Actions concept for the full status and retry model
- Host the endpoint your action calls as a Service