Skip to content

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:

FieldMeaning
idUnique identifier of this event
typeThe event type, for example medipal.submission.created
sourceThe instance and component that produced the event
timeWhen the event happened (ISO 8601, UTC)
subjectThe identifier of the affected resource
dataThe event payload: the resource as it was after the change
correlation and causation identifiersLink events that belong to the same user action or were caused by another event

Event types ​

FamilyTypes
Submissionsmedipal.submission.created, medipal.submission.updated, medipal.submission.deleted, medipal.submission.anonymous_created
Questionnairesmedipal.questionnaire.created, .updated, .published, .archived, .restored, .deleted
Foldersmedipal.folder.created, .updated, .deleted
Usersmedipal.user.created, .updated, .deleted, medipal.user.password.changed
Authenticationmedipal.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:

HeaderContent
Content-Typeapplication/json
X-Event-TypeThe event type
X-Webhook-IDThe identifier of the webhook
X-Delivery-IDThe identifier of this delivery attempt series
X-TimestampUnix time (seconds) at which the request was signed
X-Signaturesha256=<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 ​

  1. Read X-Timestamp and the raw request body exactly as received (do not re-serialise it).
  2. Build the string <timestamp>.<body>.
  3. Compute HMAC-SHA256 of that string with your signing secret as the key, and hex-encode the result.
  4. Compare it, using a constant-time comparison, with the value after sha256= in X-Signature.
  5. 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 time and 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.