Examples

CRUD notification (Case modified)

Posted when a case is updated and the subscription includes Case CRUD events:

{
  "EventTimestamp": "2026-06-29T14:32:10.123+00:00",
  "MessageId": "f1d2c3b4-5a6b-7c8d-9e0f-112233445566",
  "Event": "Modify",
  "CaseId": 12345,
  "Case": {
    "Id": 12345,
    "Identifier": "S26-001234"
    // ...remaining Case fields; matches the REST API Case model
  }
}

On a Delete, the Case object is null and only CaseId is present.

Lifecycle event notification (Slide stained)

Posted when a slide is stained and the subscription includes the Slide Stained event:

{
  "EventTimestamp": "2026-06-29T14:35:42.987+00:00",
  "MessageId": "aabbccdd-eeff-0011-2233-445566778899",
  "Event": "Stained",
  "SlideId": 98765,
  "Slide": {
    "Id": 98765,
    "Barcode": "SL-98765"
    // ...remaining Slide fields; matches the REST API Slide model
  }
}

Receiving notifications (C#)

A minimal ASP.NET Core endpoint that accepts a notification, ignores duplicates using MessageId, and returns quickly:

[ApiController]
[Route("prima/webhooks")]
public class PrimaWebHookController : ControllerBase
{
    // Illustrative only. In production, persist processed ids in a durable, shared store.
    private static readonly HashSet<Guid> ProcessedMessages = new();

    private sealed class WebHookEnvelope
    {
        public DateTimeOffset EventTimestamp { get; set; }
        public Guid MessageId { get; set; }
        public string Event { get; set; }
    }

    [HttpPost]
    public async Task<IActionResult> Receive()
    {
        using var reader = new StreamReader(Request.Body);
        var body = await reader.ReadToEndAsync();

        var envelope = JsonConvert.DeserializeObject<WebHookEnvelope>(body);

        // At-least-once delivery: skip messages we have already handled.
        if (!ProcessedMessages.Add(envelope.MessageId))
            return Ok();

        // Hand `body` off to a background queue, then return promptly so the
        // 30-second delivery timeout is never hit.

        return Ok();
    }
}