NDNCI Docs
API v1

Webhooks in local development

Forward authorized events to a loopback receiver without exposing a local network endpoint.

Run the outbound forwarder

The local forwarder polls authorized workspace events and delivers them to a receiver on your machine. It does not ask the public API to connect to localhost and does not require a public tunnel.

Download the standalone Node.js forwarder. It requires Node.js 22 or newer and no additional packages.

Create a key with the REST transport, events:read, and the selected workspace. Put the token in an environment variable rather than a command argument.

export NDNCI_AUTOMATION_TOKEN='<scoped-secret-key>'
export NDNCI_WEBHOOK_FORWARD_SECRET='<local-signing-secret>'

node ndnci-webhook-forwarder.mjs \
  --workspace '<authorized-workspace-uuid>' \
  --target 'http://127.0.0.1:8080/webhooks' \
  --api-url 'https://api.ndnci.com' \
  --cursor-file '.ndnci-events-cursor'

For a fully local API, set --api-url 'http://localhost:3001'. The forwarder permits local HTTP and otherwise requires an HTTPS API origin. Its receiver remains restricted to loopback.

Use a dedicated local signing secret with enough entropy. Do not reuse a production webhook secret. The receiver verifies the same signature format with this local secret.

Resume without losing acknowledgements

The forwarder stores its cursor only after the local receiver acknowledges an event successfully. Transient network errors and temporary API or receiver failures retry without advancing beyond the unacknowledged event. Keep the cursor file between restarts and deduplicate event identifiers in the receiver.

When polling is rate limited, the forwarder honors Retry-After. Its token and signing secret are not printed in logs. You can revoke its key independently when the development session is finished.

Authentication errors, malformed responses and invalid receiver configuration stop with an actionable error. Correct the problem and restart using the same cursor file. Use --once to process one page without retries; a refused or failed request exits unsuccessfully.

Use a tunnel when required

For a provider or network test that requires inbound HTTPS, run a tunnel and verify its exact public hostname in the target workspace. Register that hostname as the webhook destination through the normal controls. Keep the receiver's signature verification and duplicate-event handling enabled.

Private addresses, redirected destinations and unverified hostnames remain invalid public webhook destinations.

On this page