Webhook notifications


Version Notice: SOFT Integration is available starting from API version 2026-08-01.
The API version you have selected does not include it. Switch to 2026-08-01 to access this functionality.

When your organization has an OnMedicalReportFinished destination configured, the clinical result of every finished SOFT Integration consultation is delivered to it.

SOFT Integration does not use a dedicated event. It reuses OnMedicalReportFinished, the same event fired when a clinical note is completed in the platform. Consultations opened through SOFT Integration are recognised by the origin field and carry two extra fields, described below.

Configuration

The destination URL is configured per organization. One URL per organization receives this event.

Requirements for the destination URL:

RequirementDetail
ProtocolHTTPS only.
ReachabilityPublicly reachable from the internet.
Response timeMust respond within the delivery timeout of 30 seconds.
Response codeAny 2xx is considered a successful delivery.

Delivery

The event is sent as JSON with the standard webhook headers:

Content-Type: application/json
User-Agent: Invox-Medical-Webhook/1.0

Payload

The consultationSessionId carries the requestId you generated, so you can correlate the result with the consultation you opened:

{
  "eventName": "OnMedicalReportFinished",
  "organizationId": "1111111",
  "userId": "3333-3333-3333-3333",
  "timestamp": "2026-03-31T19:06:58.667Z",
  "consultationSessionId": "2222-2222-2222-2222",
  "origin": "SOFT_INTEGRATION",
  "consultationMetadata": {
    "patientId": "PAT-123-56",
    "hcId": "1234567"
  },
  "medicalReport": {
    "fields": []
  },
  "requestSignature": "<hmac-sha256-base64>"
}

Fields specific to SOFT Integration

FieldPresentDetail
consultationSessionIdAlwaysIn SOFT Integration it is the requestId you sent when generating the signature. For consultations started inside the platform it is the internal session identifier.
originOnly in SOFT IntegrationAlways "SOFT_INTEGRATION". Informational: use it to tell both flows apart.
consultationMetadataOnly in SOFT IntegrationThe metadata you sent when generating the signature, returned untouched. Absent if you sent none.
The same destination receives clinical notes produced inside the platform and those produced through SOFT Integration. Check origin if you need to process them differently. Match consultationSessionId against the requestId values you generated to correlate a SOFT consultation.
The clinical content of medicalReport follows the same structure as the OnMedicalReportFinished event. The same clinical and correlation fields are returned inside result by Get consultation result, so a single parser handles both. The retrieved result includes requestSignature when the organization has a webhook credential configured.

Verifying the signature

Every payload includes a requestSignature field computed with HMAC-SHA256 over the payload values and your secretKey. Always verify it before processing the event: it is what proves the request really comes from Invox Medical.

The algorithm, together with implementations in TypeScript, C#, Java and Python, is described in Webhooks — Introduction.

Verify the signature against the payload exactly as you received it, without reordering or rebuilding its fields. The signature concatenates every field present, so a SOFT Integration payload signs two more values than a consultation started inside the platform:
organizationId|userId|timestamp|consultationSessionId|origin|{"patientId":"..."}|{"fields":[...],...}|API_KEY
The same consultation result delivered by webhook and retrieved through Get consultation result carries two different signatures, because each channel signs the payload it sends. Both are valid: never compare them with each other, and never reuse one to validate the other.
An endpoint that accepts unverified payloads is an open door for anyone who discovers its URL. Reject any request whose signature does not match.

Good practices

  • Respond fast. Acknowledge with 2xx immediately and process the report asynchronously.
  • Be idempotent. Deduplicate by consultationSessionId, which carries your requestId: the same result may also be fetched by you through the WebSocket path.
  • Log failures. If your endpoint was unreachable, the result is still retrievable with Get consultation result until it expires.