Simple Agent
Docstroubleshooting

Webhook failing

Diagnosis for when webhooks don't arrive, return errors, or the HMAC signature doesn't validate.

If your webhooks are failing, this guide covers the most common issues in order of frequency.

1. Check the delivery log

Dashboard → Settings → Webhooks → your endpoint → View deliveries.

The log shows:

  • HTTP status returned by your server
  • Request body sent
  • Your server's response
  • Next retry (if pending)

Identifying the HTTP status is the first step toward the right diagnosis.


Diagnosis by HTTP status

200 but no processing

If the delivery shows as successful but your system didn't process the event:

  • Verify your handler is actually being called (add a log at the start of the function)
  • Confirm the endpoint receives POST (not GET)
  • Check if any parsing middleware is transforming the body before the handler runs

400 — Bad Request

Your server is rejecting the payload format.

  • Confirm you're receiving Content-Type: application/json
  • If using express.json(), switch to express.raw() so you can verify HMAC before parsing:
// Wrong for HMAC webhooks:
app.use(express.json())

// Correct:
app.post('/webhook', express.raw({ type: 'application/json' }), handler)

401 / 403 — Unauthorized

Your server is rejecting the request.

  • If you have your own authentication on the endpoint, check that Simple Agent is sending the expected header
  • Simple Agent webhooks don't send additional authentication beyond the HMAC signature — use HMAC verification as your authentication

404 — Not Found

The webhook URL is wrong or the endpoint was removed.

  • Confirm the URL in the dashboard — it should have no extra trailing slash or incorrect path
  • Test with curl: curl -X POST https://yoursite.com/webhook -H "Content-Type: application/json" -d '{}'

500 — Server error

There's an unhandled error in your handler.

  • Add try/catch around all processing logic
  • Return 200 immediately and process asynchronously if the processing takes time

timeout — No response within 10s

Your handler is taking more than 10 seconds.

Solution: Return 200 immediately and process in the background:

app.post('/webhook', async (req, res) => {
  res.status(200).json({ received: true }); // respond immediately

  // process in the background (doesn't block the response)
  processEvent(req.body).catch(console.error);
});

HMAC signature not validating

Most common issue: body was parsed before verification

The signature is calculated over the raw body (string). If you parse the JSON before verifying, the comparison fails:

// WRONG - body is already an object, not a string
const rawBody = JSON.stringify(req.body); // this is NOT the same as the original body

// CORRECT - use the raw body
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
  const rawBody = req.body.toString(); // original string sent by Simple Agent
  // verify HMAC with rawBody...
});

Timestamp too old

The default verification rejects events older than 5 minutes. If your server's clock is out of sync:

# Check NTP drift
timedatectl status
ntpq -p

Wrong secret

Confirm you're using the Webhook Secret from the specific webhook's edit screen, not the account API key.


Test with curl

To check whether the problem is in Simple Agent or your server:

# Simulate a basic event without HMAC verification
curl -X POST https://yoursite.com/webhook \
  -H "Content-Type: application/json" \
  -H "X-Simple Agent-Signature: sha256=test" \
  -H "X-Simple Agent-Timestamp: $(date +%s)" \
  -d '{"event":"test","id":"evt_test","created_at":"2026-05-14T10:00:00Z","agent_id":"ag_test","data":{}}'

If your server responds 200, the problem is with the HMAC signature or the URL. If it responds with an error, the problem is in your handler.


Resend events manually

To resend a specific event without waiting for the automatic retry:

curl -X POST https://simple-agent.me/api/v1/webhooks/wh_xxx/deliveries/del_xxx/retry \
  -H "Authorization: Bearer af_live_xxx"

Or from the dashboard: View deliveries → resend icon next to the failed delivery.

Webhooks → · API Errors → · Widget not loading →