Receiving events on a queue
WinkPG can send each event to an Azure Service Bus queue you own, instead of or alongside an HTTPS endpoint. The application that reads the queue takes messages at its own pace, and nothing of yours has to accept connections from the internet.
Set up a queue destination
- Create the queue in your Azure Service Bus namespace. Leave sessions turned off, because a queue that requires sessions can't receive these messages.
- Add a shared access policy to the queue with the Send right only, and copy its primary connection string. A policy scoped to the queue is safer than one for the whole namespace.
- In the portal, open Webhook endpoints, choose Azure Service Bus queue, and enter a name, the queue name, the connection string, and the events the queue should receive.
- On the destination's page, select Test connection. It proves the namespace answers, the connection string can send, and the queue exists, without delivering a message.
The connection string is stored encrypted and never shown again. To rotate it, save a new one on the destination's page. Only namespaces under servicebus.windows.net, servicebus.usgovcloudapi.net or servicebus.chinacloudapi.cn are accepted.
The message body
Each message carries one event as a UTF-8 JSON document with camelCase property names.
{
"eventId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"eventType": "Transaction.Authorized",
"tenantId": "00000000-0000-0000-0000-0000000000a1",
"resellerId": "00000000-0000-0000-0000-0000000000b2",
"merchantId": "00000000-0000-0000-0000-0000000000c3",
"resellerPath": null,
"occurredAtUtc": "2026-01-01T00:00:00Z",
"correlationId": "00000000-0000-0000-0000-0000000000d4",
"attributes": {},
"payload": {}
}| Field | Type | Description |
|---|---|---|
eventId |
string | Identifies this event occurrence. The same value is the message's MessageId. |
eventType |
string | The event type, matching an entry on the event reference. |
tenantId |
string | Scope identifier for the instance the event belongs to, or null. |
resellerId |
string | Scope identifier for the reseller, when the event is reseller-bound, or null. |
merchantId |
string | Scope identifier for the merchant, when the event is merchant-bound, or null. |
resellerPath |
string | The reseller hierarchy the event was raised under, or null. |
occurredAtUtc |
string | When the event occurred, ISO-8601 in UTC. |
correlationId |
string | Correlation identifier for the originating operation, or null. Quote it in a support conversation and it can be traced end to end. |
attributes |
object | The event's filter fields, each as a string. |
payload |
object | The event-specific body when the event publishes one, otherwise null. Its fields match the data object the event reference describes. |
The body isn't the webhook envelope. It describes the same event in the queue's own shape, and it carries no signature, because the queue's own access control is what decides who can send to it.
Message properties
Every message sets these broker properties, so the application reading the queue can route or deduplicate without parsing the body.
| Property | Value |
|---|---|
MessageId |
The event id. It's identical on every attempt and every replay of the delivery, which is what makes it a deduplication id. |
Subject |
The event type. |
CorrelationId |
The originating operation's correlation identifier, or the event id when there is none. |
ContentType |
Always application/json. |
Every application property the platform sets has a name starting with winkpg., so it can't collide with one of your own, and you can filter on it in a subscription rule.
| Application property | Value |
|---|---|
winkpg.eventType |
The event type, the same value as Subject. |
winkpg.eventId |
The event id, the same value as MessageId. |
winkpg.occurredAtUtc |
When the event occurred, ISO-8601 round-trip format in UTC. |
winkpg.tenantId |
Scope identifier for the instance. Present when the event has one. |
winkpg.merchantId |
Scope identifier for the merchant. Present when the event is merchant-bound. |
Duplicates and ordering
- Delivery is at least once. A retry or a replay sends the same message again, with the same MessageId.
- Turn on duplicate detection on the queue to have Service Bus discard a repeat inside its detection window, or deduplicate on MessageId in the application that reads the queue. A replay you ask for inside that window is discarded too.
- Order isn't guaranteed. Messages can arrive in a different order from the events, and a retry arrives after newer messages. Order by occurredAtUtc when it matters.
- Sessions aren't supported, so first-in, first-out delivery through a session-enabled queue isn't available. A queue that requires sessions refuses every message.
A connection test schedules a message 30 days ahead and cancels it at once. If a cancel ever fails, that message arrives with the subject winkpg.connectionTest and the application property winkpg.connectionTest set to true. Discard any message that carries it.
When a send fails
- A send that fails is retried with exponential backoff. A refused connection string, a missing or full queue, or an unreachable namespace all fail a send.
- After repeated failures, sending to the queue is paused. The destination's page says why, and the developers on your merchant account receive a health alert unless you turned them off.
- Every message appears on the portal's delivery log beside your webhook deliveries. Send a failed one again from there, or retry every failure in a window, under the same per-endpoint replay limit as a webhook.