Testnet only (Arkiv Tiramisu). OpenTrigger 0.1 has not had an outside audit.
OpenTrigger

Webhooks

Call your server, n8n, Make or Zapier when a rule fires, and verify that the call really came from a worker you trust.

Send

await triggers.createRule({
  name: 'Ping my server',
  trigger: { on: 'block', fireAt: await triggers.toBlock(new Date(Date.now() + 10 * 60_000)) },
  action: 'webhook',
  url: 'https://example.com/hooks/arkiv',
  message: '{rule} fired at {time}',
})

The URL must be https://. It is public, so it must not carry a secret (ruleWarnings flags URLs that look like they do). Public workers refuse to call addresses that resolve to private networks.

What arrives

A POST with a JSON body, signed by the worker's wallet:

{
  "event": "0x5c1e…",
  "rule": "0xab12…",
  "ruleName": "Ping my server",
  "trigger": "block",
  "deadline": "712345",
  "firedAt": "712345",
  "message": "Ping my server fired at 2026-10-20 09:00 UTC",
  "worker": "0xf856…"
}
HeaderMeaning
x-trg-sigThe worker's signature over the exact body text (EIP-191)
x-trg-workerThe worker's address
x-trg-ruleThe rule's key
x-trg-eventThe same for every retry of one firing

Verify

Check the signature against workers you trust before you act. Run this on your server, with the raw body exactly as received.

import { verifyWebhook } from 'arkiv-triggers'

export async function POST(req: Request) {
  const raw = await req.text()
  const check = await verifyWebhook(raw, req.headers.get('x-trg-sig'), TRUSTED_WORKERS)
  if (!check.ok) return new Response(check.reason, { status: 401 })
  const body = JSON.parse(raw)
  // check.worker signed it; body.event is your de-duplication key
  return new Response('ok')
}

TRUSTED_WORKERS is a list of worker addresses, for example the public worker's address from listWorkers(), or your own.

De-duplicate on the signed event

Delivery is exactly once in practice and at least once in the worst case (a receipt delayed past the worker's lease). Keep the event values you have handled, and use the one inside the signed body: the x-trg-event header is not covered by the signature.

Retries and timing

Attemptsretries + 1 (default 4)
Timeout per attempt10 s
Back-off2 s, 4 s, 8 s…
Total budget30 s, so the receipt lands while the worker still holds its claim
Not retriedA 4xx other than 408 and 429

The receipt records result.code, result.latencyMs and result.attempts, or result.error.

n8n, Make, Zapier

Their webhook URLs are just webhooks. Paste the URL into the rule; add a verification step in your flow if it can run code, or treat the URL as public and act only on non-sensitive events.

On this page