Skip to main content
Scrip processes events asynchronously against configuration you author, so testing happens at three levels: a single rule’s logic, a program’s full execution path, and your own integration’s handling of results and webhooks. Work through them in that order.

The authoring loop

For a single rule, iterate without touching live data:
  1. Validate the condition (and optionally draft actions) with POST /v1/rules/validate. This catches CEL compile errors and, with a program_id, checks tier keys and asset symbols against real configuration.
  2. Simulate the draft with POST /v1/rules/simulate before saving. The response shows whether the condition matched and every resolved action amount.
  3. Save the rule, then simulate the saved rule with POST /v1/rules/{id}/simulate, passing participant_id to run against a real participant’s live state, the same context production evaluation sees.
Writing Rules: Validation and Simulation covers the endpoints, request fields, and warnings in detail. Remember what a rule’s condition cannot catch: event.* fields are schemaless, so a misspelled event field compiles fine and then silently never matches. Check which event fields your rules depend on with the event references endpoint and confirm your event sender supplies each one.

Testing multiple rule sets

Simulation evaluates one rule. It does not run the program’s other rules or rule sets, so it cannot prove cross-set ordering or stop_after_match containment. To verify the full execution sequence before publishing, send the same draft used by analysis and preview as rule_configuration in POST /v1/test-runs. Scenario mode exercises matches, misses, windows, budgets, and set-local stops. Replay mode runs recent historical events. Both run in rollback-only transactions. Set options.compare_live to run the current and proposed configurations against the same inputs. Use trace or full to see ordered condition and action outcomes. Put specific rule IDs in options.diagnostics.rules when you need clause-level explanations. Check these properties in the event response:
  • Evaluations follow ascending set order and then local rule order.
  • Each evaluation carries the rule_set_id used at execution time.
  • A matching stop_after_match rule skips later rules in its own set only.
  • Rules in later sets still participate.
  • Conditions and dynamic action expressions use the pre-event state snapshot.
See Managing rule configuration for analysis, test runs, and the preview/apply path.

Verifying processed events

Every event records what happened, which makes the event itself your main debugging tool:
  • status shows the lifecycle: PENDINGPROCESSINGCOMPLETED or FAILED. Failed events carry a machine-readable error_code.
  • rule_evaluations is the execution trace: which rules matched, credited, or were skipped, in the order they ran. An empty trace on a COMPLETED event means no condition matched.
  • GET /v1/events/{id}/impact shows the ledger effect: every balance change the event caused, with system accounts as counterparties.
Failed events with a fixed underlying cause can be replayed with the retry endpoint.

Testing webhooks

Webhook handling is part of your integration and deserves its own tests:
  • Replay real deliveries with the resend endpoint instead of manufacturing traffic: it re-dispatches a past delivery through the normal path with a fresh signature.
  • Verify signatures against the documented scheme, not by skipping verification in test environments. The signature verification section includes worked examples.
  • Watch endpoint health with delivery stats and the delivery listing to catch failures your handler swallows.
Events sent to a development program emit real webhooks to that program’s configured endpoints, so a dev program plus a dev endpoint gives you an end-to-end rehearsal of the production flow.