Webhooks
A webhook tells your system at once when something changes in an organization's data in myWebLog: a booking, a flight or a remark. Instead of asking the API every few minutes whether anything is new, your server gets a short message when something has actually changed, and fetches the details then.
How it works
- Something changes in the organization's data: a member books an aircraft, a flight is logged, a remark is written.
- Within about a minute myWebLog sends a
POSTto the address you have given: what happened, and the id. - Your server checks that the message comes from myWebLog and answers
2xxat once. - Your server fetches the details through the Main API v5 with the organization's API key, for example
GET /bookings/123.
The message only says what happened and to which id, so no personal data is sent to your address. An organization also gets events for aircraft that other organizations share with it.
Events
A webhook can get events for bookings, the flight log and remarks, in any combination.
| Event | Sent when | data | Details through |
|---|---|---|---|
| booking.create | A booking is made. | id | GET /bookings/{id} |
| booking.update | A booking is changed: its time, aircraft, who it is for, its place in a queue. | id | GET /bookings/{id} |
| booking.delete | A booking is deleted, also when its aircraft is deleted (bookings that have not ended). A booking that is moved into a queue is deleted and made again with a new id: you get booking.delete for the old id and booking.create for the new one. | id | Can no longer be fetched |
| flightlog.create | A flight is logged: on the website, in an app or through an integration. | id | GET /flightlogs/{id} |
| flightlog.update | A logged flight is corrected, or endorsed (signed) in the aircraft's logbook. An endorsed flight is locked: it can no longer be changed. | id; when endorsed also change: endorsed | GET /flightlogs/{id} |
| flightlog.delete | A logged flight is deleted. | id | Can no longer be fetched |
| remark.create | A remark is written on an aircraft. | id | GET /remarks/{id} |
| remark.update | A remark is acknowledged, commented or closed. | id, change: acknowledged, commented or closed | GET /remarks/{id} |
| webhook.ping | A test: when the webhook is set up, when support tests it, and once a day while it is paused. | empty | – |
The calls are in the Main API v5. GET /remarks/{id} needs read access to the module Objects; it gives the remark with everything that has happened to it.
The request
Every event is a POST with a JSON body to your https address.
| Header | Value |
|---|---|
| Authorization | Bearer and the webhook's token. |
| Content-Type | application/json |
| X-Mwl-Event-Id | The event's id: 32 hexadecimal characters, the same on every try. Use it to drop an event you have already received. |
| X-Mwl-Timestamp | When this try was sent, in Unix time (seconds). |
| X-Mwl-Attempt | Which try this is, 1 to 8. |
| X-Mwl-Signature | The signature: HMAC-SHA256 of the timestamp, a dot and the body, with the webhook's signing key, as 64 hexadecimal characters. |
| Request-Id | The id of this try. Give it to support when you ask about a delivery. |
| User-Agent | mwl-webhooks/1.0 |
The body
"organization": { "id": 44 },
"event_type": "remark.update",
"data": { "id": 29153, "change": "closed", "object_id": 278 },
"id": "175b6d93169167ed551b8c593593a227",
"occurred_at": "2026-10-11T19:31:01Z",
"schema_version": 1
}
| Field | Value |
|---|---|
| organization.id | The organization whose webhook it is. For an aircraft that is shared with that organization, it is that organization, not the owner of the aircraft. |
| event_type | What happened, see Events. |
| data.id | The id of the booking, flight or remark. |
| data.change | Only on remark.update and on an endorsed flightlog.update, see Events. |
| data.object_id | The aircraft (object) of the booking, flight or remark, also when it has been deleted and can no longer be fetched. Not on webhook.ping. |
| id | The event's id, the same as X-Mwl-Event-Id and the same on every try. |
| occurred_at | When the change happened, in UTC. X-Mwl-Timestamp is when this try was sent, which can be up to 22 hours later. |
| schema_version | The form of the message, now 1. Fields may be added without a new version; a change to an existing field gets a new version. |
Read the fields by name and ignore fields you do not know: new fields can be added.
Checking the request
Answer only a request that comes from myWebLog:
- The
Authorizationheader isBearerand your token. - The signature matches: compute HMAC-SHA256 of
X-Mwl-Timestamp, a dot (.) and the body exactly as received, with your signing key, and compare it withX-Mwl-Signaturein constant time. - The timestamp is recent, for example within 5 minutes, so an old request can not be sent again.
Example in PHP
<?php
$token = "..."; // from myWebLog support
$signingKey = "..."; // from myWebLog support
$body = file_get_contents("php://input");
$timestamp = $_SERVER["HTTP_X_MWL_TIMESTAMP"] ?? "";
$signature = $_SERVER["HTTP_X_MWL_SIGNATURE"] ?? "";
$auth = $_SERVER["HTTP_AUTHORIZATION"] ?? "";
$expected = hash_hmac("sha256", $timestamp . "." . $body, $signingKey);
if (!hash_equals("Bearer " . $token, $auth)
|| !hash_equals($expected, $signature)
|| abs(time() - (int)$timestamp) > 300) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
// Store the event and answer at once; do the work (such as fetching the details) afterwards
http_response_code(202);
On some Apache servers the Authorization header is not passed on to PHP; then the server must be set to pass it on.
Answering, and when it fails
- Answer
2xxwithin 15 seconds. The connection must be made within 5 seconds. Store the event and answer first; do the work afterwards. - Any other answer, a timeout or no connection: the event is sent again after 1, 5, 15, 60, 180, 360 and 720 minutes, 8 tries over about 22 hours.
X-Mwl-Attemptsays which try it is. - The same event can arrive more than once, for example when your answer was lost. Use
X-Mwl-Event-Idto drop duplicates. - The events are sent oldest first, but the order is not guaranteed: a retry can arrive after a newer event. Fetch the current state through the API rather than trusting the order.
- When 5 events in a row have failed all their tries, the webhook is paused: new events are held, and a
webhook.pingis sent once a day. When one is answered with2xx, the webhook goes on by itself and the held events are sent. - A webhook that has been paused for 30 days is disabled, and the events it held are not sent. Contact support to start it again.
Getting a webhook
Webhooks are set up by myWebLog support. The events are about the organization's data, so the request must come from the organization's administrator, or be approved by them. Email support@myweblog.se with:
- the organization;
- the address that gets the events:
https://, at most 255 characters; - which events: bookings, flight log, remarks;
- a technical contact person, with email address.
You get the token and the signing key, and support sends a webhook.ping to check the address. To fetch the details you also need a key for the Main API: the organization's administrator makes it in myWebLog under ADMIN > System settings > Authorization > API access.
To change the address or the events, to get a new token or signing key, or to stop a webhook, email support.