Appearance
Events & Webhooks
Medipal records what happens on an instance as events and can push them to external systems through webhooks. Events are also what triggers Workflows inside the platform.
Events
Every event follows the CloudEvents structure:
| Field | Meaning |
|---|---|
id | Unique identifier of this event |
type | The event type, for example medipal.submission.created |
source | The instance and component that produced the event |
time | When the event happened (ISO 8601, UTC) |
subject | The identifier of the affected resource |
data | The event payload: the resource as it was after the change |
correlation and causation identifiers | Link events that belong to the same user action or were caused by another event |
Event types
| Family | Types |
|---|---|
| Submissions | medipal.submission.created, medipal.submission.updated, medipal.submission.deleted, medipal.submission.anonymous_created |
| Questionnaires | medipal.questionnaire.created, .updated, .published, .archived, .restored, .deleted |
| Folders | medipal.folder.created, .updated, .deleted |
| Users | medipal.user.created, .updated, .deleted, medipal.user.password.changed |
| Authentication | medipal.auth.provider.login.succeeded, .login.failed, medipal.auth.token.refreshed, medipal.auth.mfa.enabled, medipal.auth.mfa.challenge.failed, medipal.auth.password.reset.requested, .reset.completed |
New event types are added as the platform grows; the instance's OpenAPI document and the web application's subscription editor list the current set.
Webhooks
A webhook is an HTTPS endpoint you own, registered on the instance with the event types it should receive. Webhooks are managed in the web application (see Webhooks & Subscriptions) or through the API.
When registering a webhook you choose:
- a name and description,
- the target URL (HTTPS),
- the event types, or
*for all, - whether it is enabled.
The response to registration contains the webhook's signing secret, shown only once. Store it where your receiving service can read it; later views show only its last characters, and a new secret can be generated at any time with the rotate action.
Delivery
Each event matching a webhook is delivered as an HTTP POST with a JSON body and these headers:
| Header | Content |
|---|---|
Content-Type | application/json |
X-Event-Type | The event type |
X-Webhook-ID | The identifier of the webhook |
X-Delivery-ID | The identifier of this delivery attempt series |
X-Timestamp | Unix time (seconds) at which the request was signed |
X-Signature | sha256=<hex>, the HMAC-SHA256 signature of the request |
A delivery is successful when your endpoint answers with any 2xx status. Any other answer, or no answer, schedules a retry with exponential backoff; after the retry budget is exhausted the delivery is marked as failed. Failed deliveries can be retried manually from the delivery log, which shows every attempt with its status code and response.
Verifying a signature
- Read
X-Timestampand the raw request body exactly as received (do not re-serialise it). - Build the string
<timestamp>.<body>. - Compute HMAC-SHA256 of that string with your signing secret as the key, and hex-encode the result.
- Compare it, using a constant-time comparison, with the value after
sha256=inX-Signature. - Reject requests whose timestamp is older than a window you choose (for example five minutes) to defeat replays.
text
expected = hex( HMAC_SHA256( secret, timestamp + "." + raw_body ) )
valid = constant_time_equal( expected, signature_header_without_prefix )Receiving side good practices
- Verify the signature before doing anything else.
- Respond quickly and process the event asynchronously; long processing risks a timeout and a retry.
- Make handlers idempotent using the event
id: retries deliver the same event again. - Do not rely on ordering between events; use
timeand the resource's own timestamps. - Fetch the current state of the resource through the API when the payload alone is not enough.
Subscriptions and filters
Inside the platform, event subscriptions connect events to workflows. A subscription selects event types and can add a filter on the payload, so a workflow runs only for the submissions, questionnaires or folders that match. Filters are written with the same logic expressions used elsewhere in the designer. See Webhooks & Subscriptions and Workflows.
Outbound calls from workflows
Webhooks push events out; workflows can also call external systems as part of their logic:
- the HTTP workflow node performs a request with mapped inputs and stores the response for later nodes,
- an OpenAPI-driven plugin calls any REST API described by an OpenAPI document, validating the request against that document first,
- custom Server Plugins can implement any other integration as a workflow action.
Choose webhooks when the external system should react to changes; choose workflow nodes and plugins when Medipal should drive the interaction and use the result.