{/* TODO: Re-link worker references to https://workers.iii.dev/workers/<name> once the Worker Docs migration ships. */} <Note> Calling a function directly with `worker.trigger` or `iii trigger` are documented in [Using iii / Functions](./functions#triggering-invoking-functions). This page covers specifics about Triggers such as registering (binding) Triggers to Functions, gating triggers, and unregistering them. </Note>
Scanned 9/3/2026
Install to Claude Code
npx -y skills add iii-hq/iii --skill using-iii --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Using Iii?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/iii-hq-using-iii-29aba6b0)More formats (shields.io, HTML) on the badges page.
<!-- generated by iii-skill-render. DO NOT EDIT (changes here are overwritten on the next render). Edit docs/next/using-iii/triggers.mdx. -->
# Triggers
{/* TODO: Re-link worker references to https://workers.iii.dev/workers/<name> once the Worker Docs migration ships. */}
<Note>
Calling a function directly with `worker.trigger` or `iii trigger` are documented in [Using iii /
Functions](./functions#triggering-invoking-functions). This page covers specifics about Triggers
such as registering (binding) Triggers to Functions, gating triggers, and unregistering them.
</Note>
## Register a trigger
<Note>
If you're authoring a worker, you'll want to refer to [Creating Workers /
Triggers](../creating-workers/triggers#bind-a-function-to-an-existing-trigger-type) to learn the
difference between registering a trigger, and registering a trigger type.
</Note>
Functions can also run when a trigger is satisfied. A trigger can be any event that happens such as
a request to an `http` endpoint, a `cron` job, a change in `state`, or any other trigger that a
worker supports. You can also [write your own](../creating-workers/triggers).
You bind triggers to functions via the `function_id`. The trigger declares its `type`, its `config`
(defined by each type), and the function to invoke.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
import { registerWorker } from "iii-sdk";
const url = process.env.III_URL;
if (!url) throw new Error("III_URL must be set");
const worker = registerWorker(url);
worker.registerTrigger({
type: "http",
function_id: "math::add",
config: { api_path: "/math/add", http_method: "POST" },
});
```
</Tab>
<Tab title="Python">
```python
import os
from iii import register_worker, InitOptions
worker = register_worker(
os.environ.get("III_URL"),
InitOptions(worker_name="my-worker"),
)
worker.register_trigger({
"type": "http",
"function_id": "math::add",
"config": {"api_path": "/math/add", "http_method": "POST"},
})
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::{InitOptions, RegisterTriggerInput, register_worker};
use serde_json::json;
let url = std::env::var("III_URL").expect("III_URL must be set");
let worker = register_worker(&url, InitOptions::default());
worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "math::add".into(),
config: json!({ "api_path": "/math/add", "http_method": "POST" }),
metadata: None,
})?;
```
</Tab>
</Tabs>
Per-type configuration is documented in each worker's Worker Docs (e.g.
[iii-http](https://workers.iii.dev/workers/iii-http) for the `http` type).
## Handling missing triggers
When the engine cannot register a trigger, most commonly because the trigger type's worker is not
active in the project, it sends a `TriggerRegistrationResult` with an `error` body back to the
worker that initiated the request and logs it.
For known trigger types (ex. `http`, `subscribe`, `state`, `durable:subscriber`, `stream`), the
error message will include the install command for the missing worker. If it doesn't you can find
the worker that exposes the needed type at [workers.iii.dev](https://workers.iii.dev)
## Bind multiple triggers to one function
It's valid to bind multiple triggers to the same `function_id` and this can be done across any
number of types. Register a second trigger with the same `function_id` and a different type or
config; the function runs unchanged whether the call arrives over HTTP, on a cron schedule, or from
a queue message.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
// Same handler runs for an HTTP POST and a weekly cron tick.
worker.registerTrigger({
type: "http",
function_id: "reports::generate",
config: { api_path: "/reports/generate", http_method: "POST" },
});
worker.registerTrigger({
type: "cron",
function_id: "reports::generate",
config: { expression: "0 0 9 * * 1" }, // Every Monday at 09:00
});
```
</Tab>
<Tab title="Python">
```python
worker.register_trigger({
"type": "http",
"function_id": "reports::generate",
"config": {"api_path": "/reports/generate", "http_method": "POST"},
})
worker.register_trigger({
"type": "cron",
"function_id": "reports::generate",
"config": {"expression": "0 0 9 * * 1"}, # Every Monday at 09:00
})
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::RegisterTriggerInput;
use serde_json::json;
worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "reports::generate".into(),
config: json!({ "api_path": "/reports/generate", "http_method": "POST" }),
metadata: None,
})?;
worker.register_trigger(RegisterTriggerInput {
trigger_type: "cron".into(),
function_id: "reports::generate".into(),
config: json!({ "expression": "0 0 9 * * 1" }), // Every Monday at 09:00
metadata: None,
})?;
```
</Tab>
</Tabs>
## Gate a trigger with a condition
A trigger can carry an optional `condition_function_id` (set inside the trigger's `config`). When
the trigger fires, the engine invokes the condition function first with the same payload the handler
would receive; the target `function_id` only runs when the condition returns truthy. The condition
is a regular registered function.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
worker.registerFunction(
"orders::is-priority",
async (payload: { customer_tier: string }) => payload.customer_tier === "gold",
);
worker.registerTrigger({
type: "http",
function_id: "orders::expedite",
config: {
api_path: "/orders/expedite",
http_method: "POST",
condition_function_id: "orders::is-priority",
},
});
```
</Tab>
<Tab title="Python">
```python
def is_priority(payload: dict) -> bool:
return payload.get("customer_tier") == "gold"
worker.register_function("orders::is-priority", is_priority)
worker.register_trigger({
"type": "http",
"function_id": "orders::expedite",
"config": {
"api_path": "/orders/expedite",
"http_method": "POST",
"condition_function_id": "orders::is-priority",
},
})
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::{RegisterFunction, RegisterTriggerInput};
use schemars::JsonSchema;
use serde::Deserialize;
use serde_json::json;
#[derive(Deserialize, JsonSchema)]
struct Payload { customer_tier: String }
worker.register_function(RegisterFunction::new(
"orders::is-priority",
|input: Payload| -> Result<bool, String> {
Ok(input.customer_tier == "gold")
},
));
worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "orders::expedite".into(),
config: json!({
"api_path": "/orders/expedite",
"http_method": "POST",
"condition_function_id": "orders::is-priority",
}),
metadata: None,
})?;
```
</Tab>
</Tabs>
## Unregister a trigger
Trigger registration returns a handle with an `unregister()` method. Call it to drop the trigger at
runtime; when the worker disconnects, all of its triggers are removed automatically.
<Tabs>
<Tab title="Node / TypeScript">
```typescript
const trigger = worker.registerTrigger({
type: "http",
function_id: "math::add",
config: { api_path: "/math/add", http_method: "POST" },
});
trigger.unregister();
```
</Tab>
<Tab title="Python">
```python
trigger = worker.register_trigger({
"type": "http",
"function_id": "math::add",
"config": {"api_path": "/math/add", "http_method": "POST"},
})
trigger.unregister()
```
</Tab>
<Tab title="Rust">
```rust
use iii_sdk::RegisterTriggerInput;
use serde_json::json;
let trigger = worker.register_trigger(RegisterTriggerInput {
trigger_type: "http".into(),
function_id: "math::add".into(),
config: json!({ "api_path": "/math/add", "http_method": "POST" }),
metadata: None,
})?;
trigger.unregister();
```
</Tab>
</Tabs>
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!