Skip to content

Webhook development

Webhook providers need a public HTTPS URL to deliver to. routeup gives your local service one, so you can develop against real deliveries instead of mocking them.

Run your API (say on port 8080) and expose it:

Terminal window
routeup serve example-app --port 8080 --expose

The examples below assume your saved token allows *.mukul.routeup.dev.

routeup prints the local URL, public URL, exposure scope, and targets:

route: example-app
local: https://example-app.localhost
public: https://example-app.mukul.routeup.dev
expose: all paths
targets:
/ http://localhost:8080
press Ctrl-C to stop

Register the public URL as the webhook endpoint in the provider’s dashboard:

GitHub: Settings → Webhooks → Payload URL
Stripe: Developers → Webhooks → Add endpoint
Slack: Your App → Event Subscriptions → Request URL

Use the full path your handler listens on, e.g. https://example-app.mukul.routeup.dev/api/webhooks/github.

Tail public traffic as it arrives:

Terminal window
routeup logs example-app --public --follow
12:41:03 public example-app POST /api/webhooks/github 200 38ms req_Ap7kQ3mN8vR2xLzC

Because the route and namespace are configured, you request the same endpoint on each run instead of accepting a newly generated URL. Public claims remain subject to the server’s normal conflict rules.

routeup logs shows metadata only. To see the full payload and response for a delivery, enable capture in routeup.json:

{
"name": "example-app",
"port": 8080,
"capture": {
"request": true,
"response": true,
"redact_headers": ["x-hub-signature-256", "authorization"]
}
}

Then grab the request id from the log line and inspect it:

Terminal window
routeup inspect req_Ap7kQ3mN8vR2xLzC
Request
-------
Capture: complete
Body bytes: 842
X-Github-Event: push
Body
----
{"ref":"refs/heads/main","repository":{"full_name":"acme/api"},...}
Response
--------
Capture: complete
Body bytes: 4
Body
----
{"ok":true}

If you only want the webhook path reachable and the rest of the app private, you can limit public exposure to a path prefix (for example /api/webhooks/*) so the rest of the service stays local-only:

{
"name": "example-app",
"port": 8080,
"expose": {
"paths": ["/api/webhooks/*"]
}
}