Routy

Event webhooks

Event webhooks tell your systems when something happens on your Routy account β€” a connector breaks, an import fails, an export finishes. You register an HTTPS URL you control, and we send it a signed JSON event.

The point is timing. Today, if your data pipeline breaks, you usually find out by noticing: someone checks and the numbers are stale, or a Monday report looks wrong. With an endpoint registered, your monitoring finds out at the same moment we do.

This is machine-to-machine. Nobody reads these β€” a program parses them. If you want a person notified by email, Slack or in-app, that is the Notifications tab instead, and the two are set up separately.

The Event webhooks screen before any endpoint exists: the four setup steps, the one event type we send today, and a real sample of its payload

Not the same as postbacks. Postbacks are the conversion tracking mechanism β€” one templated URL fired per conversion. Event webhooks are about the health of your account, not your traffic. If you use both, keep them straight.

Setting one up

  1. Add an endpoint. Paste the HTTPS URL you want events sent to, give it a name for your own reference, and choose which event types it should receive (or switch on "Send every event type").
  2. Copy the signing secret. We show it once, on the screen right after you create the endpoint. It cannot be retrieved again β€” not by you, and not by Routy support. Copy it somewhere safe before you close that panel.
  3. Send a test. Pick an event type and hit Send test. We deliver a real, correctly signed sample to your live URL, through exactly the same path a real event takes. Watch it arrive in your own logs.
  4. Build your parser against the sample payloads under Payloads & verification, before anything real fires.

The signing secret, shown once, with a copy button and a Send a test event action

If you lose the secret, use Rotate secret β€” see below. Rotating is safe.

Destination URL

We are strict about the destination, because we make requests to it from inside our network. It must be:

  • HTTPS, not HTTP.
  • An absolute URL, with no username or password in it.
  • Reachable from the public internet. localhost, private ranges and internal hostnames are refused β€” including for testing. If you want to develop against it locally, use a tunnelling service that gives you a public HTTPS URL.

We never follow redirects. If your URL 3xxs, that counts as a failed delivery β€” register the final URL instead.

Signing secret

The secret proves a request came from us. It never authenticates a request to us, so it is not an API key and cannot be used in place of one.

To verify a delivery, compute HMAC-SHA256(secret, "{timestamp}.{rawBody}"), hex-encode it, and compare against the Routy-Webhook-Signature header. Verify against the raw body bytes β€” not a re-serialization of the JSON you parsed, which will differ. Then reject anything whose Routy-Webhook-Timestamp is outside a tolerance window; that is what stops a replay attack.

A working snippet and the full header list are in Payloads & verification on the screen.

The Payloads & verification drawer: the headers on every delivery and a working verifier

Rotating

Rotating is not destructive. For 24 hours after you rotate, we sign every delivery with both the new secret and the old one, and send both signatures in the header. So you can rotate now and deploy the new secret whenever you get to it β€” nothing is dropped in between. The screen shows exactly when the old one stops working.

Because any one of the signatures matching is enough, a consumer written the recommended way needs no change to survive a rotation.

Delivery guarantees

Three things your consumer has to handle:

  • At least once. You may receive the same eventId twice. Deduplicate on it. If you assume exactly-once, you will eventually double-count something.
  • No ordering. Retries interleave, so events can arrive out of order. Sort on occurredAt if order matters to you.
  • Unknown event types will arrive if you subscribed to "every event type". We add types over time. Your parser must ignore a type it does not recognise rather than throw.

Every payload carries type, eventId, occurredAt, affiliateId, simulated and a type-specific data block. Fields are only ever added β€” never removed or renamed.

Retries

If a delivery fails in a way worth retrying, we try again immediately, then after 30 seconds, 2 minutes, 10 minutes, 1 hour and 6 hours. That is six attempts over about seven hours, after which we give up on that delivery.

Ten consecutive give-ups in a row and we switch the endpoint off β€” see below.

Statuses

Endpoint

Three endpoints: one active, one switched off by us, one paused by the customer

Status What it means
Active Normal. We are delivering.
Paused by you You turned the endpoint off with the Enabled switch.
Switched off by us Your server failed to accept 10 deliveries in a row, so we stopped.

An endpoint we switched off, showing the reason, the last failure, and the Re-enable action

The last two look different on purpose. "Paused by you" is something you did. "Switched off by us" means your server stopped answering and needs looking at β€” the endpoint shows the reason, when it last failed, and a link straight to the failed deliveries. Fix the problem, then hit Re-enable, which clears the failure counter and resumes delivery.

Delivery

Delivery history with every status: Delivered, Retrying, Rejected, Gave up, and a test send

Status What it means
Queued Created, not attempted yet. Usually under a second.
Retrying Failed in a way worth retrying. The row shows when we will try next.
Delivered Your server accepted it with a 2xx.
Rejected Your server said no, in a way retrying cannot fix β€” a 4xx other than 408/429, a redirect, or a URL we now refuse.
Gave up We ran out of retries.

Rejected and Gave up are different problems. Rejected means your server replied and refused β€” read the response body on the row. Gave up means your server never accepted it across the full retry schedule β€” look at whether it was reachable at all.

Delivery history

An expanded delivery showing why it failed, the payload we sent, and the copy buttons

Every delivery for an endpoint, with what we sent, what your server replied, how many times we tried, and why we stopped. Expand a row to see the exact payload (with a copy button β€” paste it into your own test harness) and the first 2 000 characters of your server's response.

When we never got a reply at all β€” a timeout, a refused connection, a DNS failure β€” there is no status code to show, and the failure reason is the whole story.

Your own test sends appear here too, marked Test. They are useful while you are setting up and noise afterwards, so there is a filter to hide them.

History is kept for 30 days. Older deliveries are deleted, payload included. An empty history on a quiet endpoint is normal, not a fault.

Replay

The replay tab: pick a window, and we report anything past retention we could not reach

Re-fire the deliveries in a date window β€” useful after your consumer was down, or after you fixed a bug in it.

Each replayed delivery keeps its original event id, so a consumer that deduplicates correctly sees no duplicates. Your own test sends are skipped.

Replay reaches back exactly as far as history does: 30 days. If the window you pick goes back further, we tell you the cutoff rather than quietly sending less.

Sending a test

The Send a test event drawer, with the event type picker and the reassurance that a failing test never switches your endpoint off

A test send is a real, signed, schema-valid event delivered to your live URL through the real delivery path. It is not a ping.

A failing test never counts toward switching your endpoint off. Test as often as you need to.

If it is not in your plan

Event webhooks are a paid capability. If your plan does not include them, the screen says so and does not offer the form β€” there is nothing to fill in that could succeed.

The screen when the plan does not include event webhooks

Your account owner or billing contact can upgrade. Nothing you had before is affected.

When to contact support

  • The endpoint keeps getting switched off and the failure reason does not match anything you can see in your own logs.
  • A delivery shows a response you did not send.
  • Signature verification fails consistently for deliveries you can see arriving, and you have already checked that you are hashing the raw body.

Have the delivery id and event id ready β€” both are on the delivery row, and the event id has its own copy button.