Testing HTTP Triggers in Simulation

During development, you can test your HTTP trigger workflows locally using the cre workflow simulate command. The simulator allows you to provide test payloads without setting up authorization keys or JWT authentication.

This guide focuses specifically on HTTP trigger simulation with detailed examples and scenarios. For a general overview of workflow simulation covering all trigger types, see Simulating Workflows.

Prerequisites

Before running a simulation:

  • CRE CLI installed: You need the CRE CLI to run simulations. See CLI Installation if you haven't installed it yet.
  • CRE account & authentication: You must have a CRE account and be logged in with the CLI. See Create your account and Log in with the CLI for instructions.
  • HTTP trigger configured: Your workflow must have an HTTP trigger handler registered. See Configuration & Handler for setup instructions.

Basic simulation

To simulate a workflow with an HTTP trigger, run the simulate command from your project root:

cre workflow simulate <workflow-folder> --target <target-name>

Example:

cre workflow simulate my-http-workflow --target staging-settings

The simulator will detect your HTTP trigger and prompt you to select it from available triggers.

Providing input data

You have three ways to provide JSON input to your HTTP trigger during simulation:

1. Interactive mode (default)

When you run the simulation without input flags, the CLI prompts you to enter JSON data:

$ cre workflow simulate my-http-workflow --target staging-settings

# Select the HTTP trigger when prompted
? Select a trigger to simulate: HTTP Trigger

# Enter your JSON input:
? Enter JSON input for the HTTP trigger:
{"userId": "123", "action": "purchase", "amount": 50}

The simulator converts your JSON into a payload and passes it to your callback function.

2. Inline JSON string

For non-interactive execution (useful for CI/CD or scripting), pass JSON directly using the --http-payload flag along with --non-interactive and --trigger-index:

cre workflow simulate my-http-workflow --non-interactive --trigger-index 0 --http-payload '{"userId":"123","action":"purchase","amount":50}' --target staging-settings

3. Input from file

For complex payloads or reusable test data, store your JSON in a file and reference it in non-interactive mode.

Option 1: File in workflow folder

Create the payload file in your workflow directory:

my-http-workflow/test-payload.json:

{
  "userId": "123",
  "action": "purchase",
  "amount": 50,
  "metadata": {
    "timestamp": "2025-11-10T10:00:00Z",
    "source": "mobile-app"
  }
}

Simulate:

cre workflow simulate my-http-workflow --non-interactive --trigger-index 0 --http-payload test-payload.json --target staging-settings

Option 2: File at project root

Create the payload file at your project root. Simulate (using ../ to reference the parent directory):

cre workflow simulate my-http-workflow --non-interactive --trigger-index 0 --http-payload ../test-payload.json --target staging-settings

Example workflow simulation

Let's simulate a complete workflow that processes HTTP requests.

Setup your config file:

For this example, create a config.staging.json file with:

{
  "minimumAmount": 10
}

This configuration sets the minimum purchase amount to 10, which we'll test with different scenarios.

Workflow code:

HTTP Trigger Simulation Example
1 //go:build wasip1
2
3 package main
4
5 import (
6 "encoding/json"
7 "fmt"
8 "log/slog"
9
10 "github.com/smartcontractkit/cre-sdk-go/capabilities/networking/http"
11 "github.com/smartcontractkit/cre-sdk-go/cre"
12 "github.com/smartcontractkit/cre-sdk-go/cre/wasm"
13 )
14
15 type Config struct {
16 MinimumAmount int `json:"minimumAmount"`
17 }
18
19 type RequestData struct {
20 UserID string `json:"userId"`
21 Action string `json:"action"`
22 Amount *int `json:"amount"` // Pointer to detect missing field
23 }
24
25 func onHttpTrigger(config *Config, runtime cre.Runtime, payload *http.Payload) (string, error) {
26 var data RequestData
27 if err := json.Unmarshal(payload.Input, &data); err != nil {
28 return "", fmt.Errorf("failed to parse input: %w", err)
29 }
30
31 // Validate required fields
32 if data.UserID == "" || data.Action == "" || data.Amount == nil {
33 runtime.Logger().Info("Missing required fields")
34 return "Error: Missing required fields (userId, action, amount)", nil
35 }
36
37 runtime.Logger().Info("Processing request", "action", data.Action, "userId", data.UserID)
38
39 if *data.Amount < config.MinimumAmount {
40 runtime.Logger().Info("Amount below minimum", "amount", *data.Amount, "minimum", config.MinimumAmount)
41 return "Amount too low", nil
42 }
43
44 runtime.Logger().Info("Processing amount", "amount", *data.Amount)
45 return fmt.Sprintf("Successfully processed %s", data.Action), nil
46 }
47
48 func InitWorkflow(config *Config, logger *slog.Logger, secretsProvider cre.SecretsProvider) (cre.Workflow[*Config], error) {
49 httpTrigger := http.Trigger(&http.Config{}) // Empty config OK for simulation
50
51 return cre.Workflow[*Config]{
52 cre.Handler(httpTrigger, onHttpTrigger),
53 }, nil
54 }
55
56 func main() {
57 wasm.NewRunner(cre.ParseJSON[Config]).Run(InitWorkflow)
58 }
59

Run the simulation:

cre workflow simulate my-http-workflow --non-interactive --trigger-index 0 --http-payload '{"userId":"user_123","action":"purchase","amount":100}' --target staging-settings

Expected output:

Workflow compiled
2025-11-10T11:28:25Z [SIMULATION] Simulator Initialized

2025-11-10T11:28:25Z [SIMULATION] Running trigger [email protected]
2025-11-10T11:28:25Z [USER LOG] Processing purchase for user user_123
2025-11-10T11:28:25Z [USER LOG] Processing amount: 100

Workflow Simulation Result:
 "Successfully processed purchase"

2025-11-10T11:28:25Z [SIMULATION] Execution finished signal received
2025-11-10T11:28:25Z [SIMULATION] Skipping WorkflowEngineV2

Testing different scenarios

Use simulation to test various input scenarios:

Valid request

cre workflow simulate my-http-workflow --non-interactive --trigger-index 0 --http-payload '{"userId":"123","action":"purchase","amount":100}' --target staging-settings

Invalid input (below minimum)

cre workflow simulate my-http-workflow --non-interactive --trigger-index 0 --http-payload '{"userId":"123","action":"purchase","amount":5}' --target staging-settings

Expected output:

Workflow compiled
2025-11-10T11:34:38Z [SIMULATION] Simulator Initialized

2025-11-10T11:34:38Z [SIMULATION] Running trigger [email protected]
2025-11-10T11:34:38Z [USER LOG] Processing purchase for user 123
2025-11-10T11:34:38Z [USER LOG] Amount 5 below minimum 10

Workflow Simulation Result:
 "Amount too low"

2025-11-10T11:34:38Z [SIMULATION] Execution finished signal received
2025-11-10T11:34:38Z [SIMULATION] Skipping WorkflowEngineV2

Missing fields

cre workflow simulate my-http-workflow --non-interactive --trigger-index 0 --http-payload '{"userId":"123","action":"purchase"}' --target staging-settings

Expected output:

Workflow compiled
2025-11-10T11:37:57Z [SIMULATION] Simulator Initialized

2025-11-10T11:37:57Z [SIMULATION] Running trigger [email protected]
2025-11-10T11:37:57Z [USER LOG] Missing required fields

Workflow Simulation Result:
 "Error: Missing required fields (userId, action, amount)"

2025-11-10T11:37:57Z [SIMULATION] Execution finished signal received
2025-11-10T11:37:57Z [SIMULATION] Skipping WorkflowEngineV2

This helps you verify error handling and edge cases before deployment.

Simulation vs production behavior

AspectSimulationProduction
AuthorizationNot required (empty config allowed)Required (authorizedKeys must be set)
Signature verificationSkippedStrictly enforced
ExecutionImmediate, synchronousAsynchronous via DON
LogsPrinted to terminalAvailable in CRE UI

Next steps

Once you've tested your workflow locally:

  1. Add authorization: Configure authorizedKeys in your HTTP trigger for production
  2. Deploy your workflow: Use cre workflow deploy to register it
  3. Trigger it in production: Follow the Triggering Deployed Workflows guide

Get the latest Chainlink content straight to your inbox.