Automation

Create a trigger

Schedule recurring or one-time runs, or start runs from a webhook, for a published script or workflow.

Schedule recurring or one-time runs, or start runs from a webhook, for a published script or workflow. For one immediate run without a persistent trigger, use praxis.automation.runs.create. There may be at most 100 enabled triggers per tenant. Targets accept only exact versions or tags; webhook_url is returned only when creating a webhook or rotating its URL, so save it securely.

POST /automation/v1/triggers

Authentication

Authorization: Bearer $PRAXIS_API_KEY

Request fields

ParameterTypeDescription
header: Idempotency-Keystringoptional; Optional; 1–256 characters. Within 24 hours, the same key replays the first response with Idempotent-Replayed: true; a different request body returns 422; an in-flight request returns 409. minLength: 1; maxLength: 256

application/json

no additional fields.

FieldTypeDescription
namestringrequired; Trigger display name, 1–100 characters and not all whitespace; uniqueness is not required. minLength: 1; maxLength: 100
descriptionstringoptional; Description, at most 1,000 characters. maxLength: 1000
labelsobjectoptional; At most 64 user labels; the praxis. prefix is reserved and internal labels do not count. Keys 1–40 characters, values at most 500.
targetstringrequired; ns/name@tag or ns/name@version, defaulting to latest when @ is omitted. Triggers do not accept version ranges.
inputnull / string / number / boolean / object / null / string / number / boolean / object / JSON[][]optional; Static JSON input for scheduled firings, default {}; checked against the target schema on create/update. Omitted webhook input is not validated at creation.
input (variant 5).* (variant 5)objectRecursive JSON value.
input (variant 5).* (variant 6)[]null / string / number / boolean / object / JSON[]Recursive JSON value.
input (variant 6)[] (variant 5).*null / string / number / boolean / object / JSON[]Recursive JSON value.
input (variant 6)[] (variant 6)[]null / string / number / boolean / object / JSON[]Recursive JSON value.
kind"schedule" / "webhook"required; schedule fires on a schedule; webhook fires on an HTTP delivery. Immutable after creation.
scheduleobject / object / objectoptional; Choose one: a five-field cron (L/W/# supported), every as an ISO 8601 duration or duration object resolving to positive integer milliseconds from one minute to 366 days, or at as a one-time RFC 3339 timestamp within the next year.
schedule (variant 1).cronstringrequired; Five fields; supports L, W, #. DST gaps skip the day and overlaps run once.
schedule (variant 2).everystring / objectrequired; A duration: an ISO 8601 string such as PT5M, or an object with days, hours, minutes, seconds and milliseconds. It must convert to a whole number of milliseconds between 60000 and 31622400000 (1 minute to 366 days).
schedule (variant 2).every (variant 2).daysintegeroptional; Number of days, a non-negative integer. minimum: 0
schedule (variant 2).every (variant 2).hoursintegeroptional; Number of hours, a non-negative integer. minimum: 0
schedule (variant 2).every (variant 2).minutesintegeroptional; Number of minutes, a non-negative integer. minimum: 0
schedule (variant 2).every (variant 2).secondsintegeroptional; Number of seconds, a non-negative integer. minimum: 0
schedule (variant 2).every (variant 2).millisecondsintegeroptional; Number of milliseconds, a non-negative integer. minimum: 0
schedule (variant 3).atstringrequired; One-time firing instant with a Z or ±HH:MM timezone, between the request time and one calendar year later. Replace the example with a future instant in that range. pattern: "(Z|[+-]\d\d:\d\d)$"; format: "date-time"
timezonestringoptional; IANA timezone, default UTC. DST gaps are skipped and repeated local times fire once. default: "UTC"
start_atstring / nulloptional; Optional RFC 3339 start time with timezone; null means no lower bound.
end_atstring / nulloptional; Optional RFC 3339 end time with timezone; cannot precede start_at. null means no upper bound.
overlap"skip" / "allow"optional; skip (default) skips when a previous run is still active; allow permits overlapping runs. default: "skip"
catchup_window_secondsintegeroptional; Nonnegative integer seconds, default 300. Only scheduled firings delayed beyond the window are recorded as missed; webhooks ignore this window. default: 300; minimum: 0
webhookobjectoptional; input_mode is body (default) or envelope. The latter contains body, raw_body, raw_body_encoding, allowlisted headers, webhook_id and received_at; full URLs are returned only on creation or rotation. no additional fields.
webhook.input_mode"body" / "envelope"required; Shape of the input a webhook delivery gives the target. body (default) passes only the request body; envelope passes an object with body, raw_body, raw_body_encoding, headers, webhook_id and received_at. default: "body"

Examples

Set these environment variables to your own resources:

: "${TARGET:?Set TARGET}"
BODY=$(jq -n --arg TARGET "$TARGET" '{
  "name": "sample-webhook",
  "target": $TARGET,
  "kind": "webhook",
  "labels": {
    "namespace": "docs-samples"
  },
  "webhook": {
    "input_mode": "body"
  }
}')
curl --fail-with-body -X POST "https://api.deepraxis.ai/automation/v1/triggers" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H "Content-Type: application/json" \
  --data "$BODY"
import { createAutomationClient } from '@deepraxis/sdk/automation';

function env(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name}`);
  return value;
}
const automation = createAutomationClient({
  apiKey: env('PRAXIS_API_KEY'),
  baseUrl: 'https://api.deepraxis.ai',
  maxRetries: 0,
  timeoutMs: 90_000,
});
const result = await automation.triggers.create({
  "body": {
    "name": "sample-webhook",
    "target": env("TARGET"),
    "kind": "webhook",
    "labels": {
      "namespace": "docs-samples"
    },
    "webhook": {
      "input_mode": "body"
    }
  }
});
console.log(result);

Response

HTTP 200

Success

HeaderTypeDescription
ETagstringCurrent resource revision for conditional updates.
Idempotent-ReplayedbooleanPresent and true when replaying the first response for this key.

application/json

FieldTypeDescription
namestringrequired; Trigger name, 1–100 characters. minLength: 1; maxLength: 100
descriptionstringrequired; Trigger description, at most 1000 characters. maxLength: 1000
labelsobjectrequired; Trigger tags as string key and value pairs, at most 64; keys must not start with the reserved prefix praxis. (400 INPUT_INVALID).
targetstringrequired; Script or workflow to run, as ns/name@tag-or-version; it follows latest by default, and @1.2.0 pins a version.
inputnull / string / number / boolean / object / JSON[]required; Any JSON value: null, boolean, number, string, array or object.
input (variant 5).*null / string / number / boolean / object / JSON[]Recursive JSON value.
input (variant 6)[]null / string / number / boolean / object / JSON[]Recursive JSON value.
kind"schedule" / "webhook"required; Trigger kind. schedule fires on a plan (cron, every or at); webhook fires on an inbound HTTP request.
scheduleobject / object / object / nullrequired; Schedule rule for kind=schedule, exactly one of cron, every or at; null for webhooks.
schedule (variant 1) (variant 1).cronstringrequired; Five fields; supports L, W, #. DST gaps skip the day and overlaps run once.
schedule (variant 1) (variant 2).everystring / objectrequired; A duration: an ISO 8601 string such as PT5M, or an object with days, hours, minutes, seconds and milliseconds. It must convert to a whole number of milliseconds between 60000 and 31622400000 (1 minute to 366 days).
schedule (variant 1) (variant 2).every (variant 2).daysintegeroptional; Number of days, a non-negative integer. minimum: 0
schedule (variant 1) (variant 2).every (variant 2).hoursintegeroptional; Number of hours, a non-negative integer. minimum: 0
schedule (variant 1) (variant 2).every (variant 2).minutesintegeroptional; Number of minutes, a non-negative integer. minimum: 0
schedule (variant 1) (variant 2).every (variant 2).secondsintegeroptional; Number of seconds, a non-negative integer. minimum: 0
schedule (variant 1) (variant 2).every (variant 2).millisecondsintegeroptional; Number of milliseconds, a non-negative integer. minimum: 0
schedule (variant 1) (variant 3).atstringrequired; Instant of a one-time firing (RFC 3339 UTC); it cannot be in the past or more than one year ahead. The trigger becomes expired after it runs. format: "date-time"
timezonestringrequired; IANA time zone name used to interpret the schedule; UTC by default through the API. default: "UTC"
start_atstring / nullrequired; Start time of a scheduled trigger (RFC 3339 UTC); it does not fire before then. null for no limit.
end_atstring / nullrequired; End time of a scheduled trigger (RFC 3339 UTC); after it the trigger becomes expired. null for no end.
overlap"skip" / "allow"required; Overlap policy when a firing is due while the previous run is still active: skip (default) skips it, allow starts it anyway. default: "skip"
catchup_window_secondsintegerrequired; Catch-up window in seconds, default 300, for scheduled triggers only: if a firing is later than this (downtime, pause) it is recorded as missed and not run. default: 300; minimum: 0
webhookobject / nullrequired; Webhook settings for kind=webhook; null for scheduled triggers.
webhook (variant 1).input_mode"body" / "envelope"required; Shape of the input a webhook delivery gives the target. body (default) passes only the request body; envelope passes an object with body, raw_body, raw_body_encoding, headers, webhook_id and received_at.
webhook (variant 1).url_hintstringrequired; Masked webhook address with an ellipsis replacing the secret token; it cannot be invoked. Newly created triggers use a full public URL; historical records may contain a relative /automation/v1/hooks/{id}/… path.
idstringrequired; Trigger id, prefixed trg_; used in the webhook address and by every trigger endpoint.
ownerstringrequired; Tenant that owns the trigger, injected by the gateway; treat it as an opaque string.
state"enabled" / "paused" / "expired"required; Trigger state. enabled fires on schedule or request; paused does not fire; expired is final, reached after a one-time trigger has run or end_at has passed, and no longer fires.
source"api" / "definition"required; Origin of the trigger. api was created through the API and can be changed and deleted; definition was generated from the schedule in a workflow YAML and can only be paused or resumed, changes return 409 TRIGGER_MANAGED.
created_byobjectrequired; Principal {type, id} injected by the gateway that says who initiated or acted. This service does not resolve names; the console resolves them in batches. no additional fields.
created_by.type"user" / "api_key" / "agent" / "run" / "trigger"required; Principal type. user is a signed-in user; api_key is a platform API key; agent is an agent; run is an action performed by a run itself (for example a parent run); trigger is a trigger.
created_by.idstringrequired; Principal identifier whose meaning follows type: a user, API key, agent, run or trigger id. Treat it as an opaque string.
created_by_user_idstringrequired; Real user id of the creator, forwarded by the gateway; runs the trigger starts take their token from this user, for audit and usage attribution.
next_fire_timesstring[]required; Up to the next 5 firing times (RFC 3339 UTC); empty for webhook, paused or expired triggers. maxItems: 5
last_firingobject / nullrequired; The most recent firing record, or null if it has never fired.
last_firing (variant 1).idstringrequired; Firing record id; records are kept for 30 days.
last_firing (variant 1).trigger_idstringrequired; Id (trg_) of the trigger this firing belongs to.
last_firing (variant 1).scheduled_atstringrequired; Planned firing time (RFC 3339 UTC); for webhooks, the time the request arrived. format: "date-time"
last_firing (variant 1).fired_atstringrequired; Time the firing actually happened (RFC 3339 UTC). format: "date-time"
last_firing (variant 1).outcome"accepted" / "started" / "skipped_overlap" / "missed" / "failed" / "deduped"required; Firing outcome. accepted means persisted and awaiting processing; started means a run was created; skipped_overlap means skipped because the previous run was still active; missed means it was later than the catch-up window and was not run; failed means creating the run failed; deduped means it repeated a webhook-id seen within 24 hours.
last_firing (variant 1).run_idstring / nullrequired; Id (run_) of the run this firing created, or null if no run was created.
last_firing (variant 1).resolved_versionstring / nullrequired; Exact version this firing resolved to; null when not yet resolved or when it failed before resolving.
last_firing (variant 1).errorobject / nullrequired; Reason {code, message} when the firing failed; null otherwise.
last_firing (variant 1).error (variant 1).codestringrequired; Error code of the failure.
last_firing (variant 1).error (variant 1).messagestringrequired; Message describing the failure.
countsobjectrequired; Cumulative firing counts {started, skipped, missed, failed}. no additional fields.
counts.startedintegerrequired; Number of firings that started a run. minimum: 0
counts.skippedintegerrequired; Number of firings skipped because overlap is skip and the previous run was still active. minimum: 0
counts.missedintegerrequired; Number of firings missed because they were later than the catch-up window. minimum: 0
counts.failedintegerrequired; Number of firings where creating the run failed. minimum: 0
created_atstringrequired; Creation time (RFC 3339 UTC). format: "date-time"
updated_atstringrequired; Time of the last update (RFC 3339 UTC). format: "date-time"
etagstringrequired; Current revision tag of the trigger; send it as If-Match when updating, and a mismatch returns 412.
usage_30dobject / nulloptional; Always null in a create response; the 30-day usage is only returned by GET /triggers/{id}.
usage_30d (variant 1).currency"USD"required; Charge currency, always USD.
usage_30d (variant 1).coststringrequired; Rated actual charges as an exact dollar decimal string with six fractional digits; 0.000000 when there is no usage. pattern: "^[0-9]+\.[0-9]{6}$"
usage_30d (variant 1).pending_eventsintegerrequired; Number of unrated usage events whose charges will be included later. minimum: 0
webhook_urlstringoptional; Returned only on webhook creation or rotation. format: "uri"

Measured response

HTTP 200

{
  "id": "trg_00mv67mzzqa0d63b98d72446dd9d1331051a3e100e",
  "owner": "tnt_3a9759864ccb4e00",
  "name": "sample-webhook-1791867412840-b05e8a",
  "description": "",
  "labels": {
    "namespace": "docs-samples"
  },
  "target": "docs-samples/sample-scripts-1791867412840-b05e8a@1.0.0",
  "input": {},
  "kind": "webhook",
  "schedule": null,
  "timezone": "UTC",
  "start_at": null,
  "end_at": null,
  "overlap": "skip",
  "catchup_window_seconds": 300,
  "webhook": {
    "input_mode": "body",
    "url_hint": "https://api-develop.deepraxis.ai/automation/v1/hooks/trg_00mv67mzzqa0d63b98d72446dd9d1331051a3e100e/…"
  },
  "state": "enabled",
  "source": "api",
  "created_by": {
    "type": "api_key",
    "id": "key_3e00b8984967"
  },
  "created_by_user_id": "usr_49d4fcb99517",
  "next_fire_times": [],
  "last_firing": null,
  "counts": {
    "started": 0,
    "skipped": 0,
    "missed": 0,
    "failed": 0
  },
  "created_at": "2026-10-13T04:58:09.974Z",
  "updated_at": "2026-10-13T04:58:09.974Z",
  "etag": "etag_00mv67mzzqc6ef5487c69f4857b65b91dab497104c",
  "webhook_url": "https://api-develop.deepraxis.ai/automation/v1/hooks/trg_00mv67mzzqa0d63b98d72446dd9d1331051a3e100e/${WEBHOOK_TOKEN}"
}

Errors

HTTPCodes and description
400INVALID_PARAMS: Invalid request parameters, path, cursor, or body format. SCHEDULE_INVALID: The schedule or time boundaries are invalid. TIMEZONE_INVALID: The timezone is not a valid IANA timezone. INTERVAL_TOO_SHORT: The schedule interval is shorter than one minute. INPUT_INVALID: The input does not satisfy the target contract or validation rules.
404TARGET_NOT_FOUND: The target does not exist or has an incompatible type. VERSION_NOT_FOUND: The requested version or revision does not exist.
409IDEMPOTENCY_IN_FLIGHT: A request with the same idempotency key is still in progress. TARGET_ARCHIVED: The target is archived and cannot be used for this operation; action execution error detail includes ns/name.
412PRECONDITION_FAILED: The revision, source digest, or concurrent write precondition does not match.
422IDEMPOTENCY_KEY_MISMATCH: The idempotency key was already used for different request content. NO_MATCHING_VERSION: No published version matches the requested tag, version, or range.
429TRIGGER_LIMIT: The tenant has reached the limit of 100 enabled triggers.
defaultRFC 9457 automation problem. 429 includes Retry-After.

Authentication and common errors · Retain the X-Request-Id response header for troubleshooting.

Export

On this page