Documentation

Testing and debugging

Dry-run a flow, inspect step output, and read execution logs.

A workflow has three things to verify: triggers fire on the events you expect, conditions branch the way you expect, and actions produce the right side effects. AppEngine gives you a manual-execute endpoint, validation utilities, and a queryable execution history.

Dry-run an automation

POST/automation/:automationId/executeJWT

The same endpoint that powers manual execution doubles as a dry-run tool. Pass synthetic variables and a startStepId to skip past the trigger and run a specific branch:

curl -X POST https://appengine.appmint.io/automation/$AUTOMATION_ID/execute \
  -H "Authorization: Bearer $JWT" -H "orgid: $ORG" \
  -d '{
    "executionId": "test-001",
    "startStepId": "branch-1",
    "variables": {
      "contact": { "id": "test", "email": "[email protected]", "country": "US", "tags": ["vip"] }
    },
    "executedBy": "[email protected]"
  }'

The response is an ExecutionResult:

{
  "success": true,
  "executionId": "test-001",
  "completedSteps": ["branch-1", "us-flow-step", "send-step"],
  "totalSteps": 5,
  "logs": [
    { "level": "info", "message": "Condition branch-1 → true", "stepId": "branch-1" },
    { "level": "info", "message": "Notification sent", "stepId": "send-step" }
  ],
  "startedAt": "2026-04-25T...",
  "completedAt": "2026-04-25T..."
}

Wait actions still pause the run. To skip a delay during testing, design the flow so the test startStepId lands after it, or temporarily set duration: 0.

Dry runs are not idempotent

Manual execution still runs every action's real side effect — emails are sent, records are created, webhooks fire. Use a test contact and a sandbox webhook receiver. There is no built-in mock mode.

Validate a workflow shape

POST/automation/ai/validateJWT

Static checks against the workflow JSON: orphaned step IDs, missing required config keys, unknown actionType, broken nextStepId links. Run before saving.

curl -X POST https://appengine.appmint.io/automation/ai/validate \
  -H "Authorization: Bearer $JWT" -H "orgid: $ORG" \
  -d '{"workflow": { /* the data payload */ }}'

Response:

{
  "isValid": false,
  "errors": [
    { "type": "broken_link", "message": "Step s2 references unknown nextStepId 's99'", "location": "steps[1]", "severity": "error" }
  ],
  "suggestions": [
    { "type": "missing_branch", "message": "Condition has no elseStepId", "fix": { "elseStepId": null } }
  ]
}

Read execution history

GET/automation/execution/historyJWT

Returns past runs with full step-level logs.

Query paramDescription
automationIdFilter to one workflow
limitPage size (default 50)
offsetPage offset
curl "https://appengine.appmint.io/automation/execution/history?automationId=$ID&limit=20" \
  -H "Authorization: Bearer $JWT" -H "orgid: $ORG"

Each item carries completedSteps, the full logs array, and the error if it failed. Use this to spot the step where the run died.

Inspect dashboard stats

GET/automation/dashboard/statsJWT

Aggregate counts: active vs draft, total executions, completion rate, recent activity feed. Good for a glance after a deploy.

GET/automation/status/:automationIdJWT

Per-automation: totalExecutions, lastExecution, current status.

Debugging tips

  1. Check the trigger registered. After saving, call POST /automation/start/:id and watch logs for Registered automation triggers. Without start, no trigger fires.
  2. Pin the test data. Pass an explicit executionId and executedBy so you can find the run in history later.
  3. Look at the last completed step. completedSteps ends at the step that failed (or paused). The next step in steps[] is where to dig.
  4. Watch for circular blocks. If a data_updated automation never fires, check whether circular prevention is rejecting it — the guard logs Trigger blocked by circular prevention at debug level.
  5. Pause on a wait? Wait actions return pauseExecution: true. The execution shows success: true but with fewer completedSteps than totalSteps. The remainder runs when the queue resumes the job.

The /automation/health endpoint is unauthenticated and returns the registry sizes (number of registered actions, triggers, conditions). Use it to verify the engine itself is alive.