One event model, even without native webhooks
Some systems push events. Many push nothing at all. Maesn gives you one webhook to subscribe to, one payload shape to handle and one signature to verify, and does the polling itself wherever a system stays silent.
{
"eventType": "CREATED",
"resource": "INVOICE",
"resourceId": "bca91f06…"
}







Provet










Provet


What are unified webhooks
A webhook is the difference between asking and being told. Instead of calling an API on a schedule to see whether anything changed, you register a URL once and the system calls you when something does. For integrations that keep data in sync, that is the difference between minutes of staleness and a few seconds, and between constant traffic and traffic only when there is news.
The catch is that webhooks are the least standardized part of any API. Support is uneven, the payloads disagree, and the vocabulary for a created object differs from system to system. Unified webhooks collapse that into one subscription model and one event body, delivered through the same normalized data model as the rest of the Unified API. You write one handler, and it keeps working as your customers bring new systems.
Events are the least standardized part
Every system answers the same four questions differently, starting with whether it will tell you anything at all. Build against them directly and each integration needs its own listener.
Subscribe once, handle one event
One endpoint creates a subscription for one customer. From then on the events arrive at your callback URL in the same shape, whichever system they came from.
Where events go
The endpoint on your side that receives every event for this subscription, as a POST request.
What to hear about
Subscribe to objects being created, updated or deleted, using one vocabulary on every system.
Which objects
The resource you want to watch, an invoice or a customer for example, named the same everywhere.
One webhook type
A single unified webhook covers every system, so you write one handler instead of one per integration.
Synthetic webhooks
For systems that push nothing natively, Maesn polls on your behalf and emits the same event, so the gap never reaches your code.
Subscriptions per customer
Each subscription belongs to one customer, so their events arrive through their own subscription and stay separable.
Signed events
Every event carries an HMAC-SHA256 signature over the raw body, so you can prove it came from Maesn before you trust it.
POST /webhooksx-api-key: YOUR_API_KEYx-account-key: CUSTOMER_ACCOUNT_KEY{"callbackUrl": "https://your-app.com/events","eventType": "CREATED","resource": "INVOICE"}
Signed on every event
Every event carries an X-MAESN-SIGNATURE header. Recompute it over the raw request body with the secret you received when you created the webhook, and compare. Verify before you parse the JSON.
expected = hmacSha256(webhookSecret, rawBody) isValid = expected === headerSignature
Events from systems that push nothing
This is the part that does not exist without a unified layer. When a system has no native webhooks, or only covers a fraction of its objects, the usual answer is that you build a poller: a schedule, a cursor per customer and per resource, change detection, and a queue to smooth out the load. It works, and it becomes permanent infrastructure you own forever.
Maesn runs that poller instead, and turns the result into a normal event. You subscribe the same way you would to a native webhook, and you receive the same body with the same eventType, resource and resourceId. Nothing in your handler distinguishes the two, which is the point: whether a system pushes events stops being an input to your architecture. The polling that makes it work is paced by asynchronous processing, so it stays inside each system's limits without you scheduling around them.
You subscribe once and receive events. The polling, the scheduling and the change detection stay on Maesn's side, and the event body is the one you already handle.
Told when the write actually finishes
Not every system answers a write immediately. Some accept the object, queue it and produce the outcome later, which normally leaves you polling for your own result.
Maesn can close that loop with a webhook: when the system produces the outcome, you get an event telling you whether the write succeeded or failed. It exists because customers asked for it, which is the honest reason most of this layer exists. Every request, response and event along the way is recorded, so when something does go wrong you can see what was sent and what came back through logging and monitoring.
One listener, every system
- Learn each system's event model
- Poll the systems that send nothing
- Turn pings into real payloads
- Verify each scheme differently
- One event model to handle
- Silent systems polled for you
- Normalized payloads either way
- One signature check everywhere
Webhook support is the thing most likely to be missing from the system a customer wants next, and the thing most likely to force a rewrite when it is. Because the event model is Maesn's rather than each vendor's, that question stops mattering during a sales call: you support the system, and how its data reaches you is an implementation detail on our side. The handler you wrote for the first integration is the handler for the last one.
Common questions
Build once on the Unified API.
See how unified webhooks works for your integration, or dive into the technical reference.