The 1st method - Webhook Message Consumer
Overview
- This is the first way of communication:
- To register consumer and consume events of application domain services using message gateway
- Webhook API follows the REST API guidelines
- The event messages are supported by .NET connectors of platform services using nuget packages
Message Gateway
MessageGateway is platform service encapsulating external communication with message broker to HTTP based technologies, gRPC and Webhooks. It is the only way for external cloud and on-premise services integrated with AVAplace platform.
See more: OIDC/OAuth2 authentication
How webhooks work (short overview)
A webhook is a lightweight HTTP callback used to deliver events in near real-time. You register a consumer webhook URL in the MessageGateway and, when an event occurs, the gateway sends an HTTP POST to that URL with a JSON payload and security headers.
Key expectations for consumers:
- Verify the JWT in the
Authorizationheader (RS256) before accepting a notification. - Process payloads idempotently and use
messageId/path variables for deduplication and correlation. - Return an HTTP 2xx response to acknowledge the message; non-2xx responses or network errors trigger redelivery with retry/backoff.
- Prefer separate webhook URLs per stage (DEMO/PROD) and per message type when practical.

How to consume webhook message using message gateway
- Register MessageGateway consumer using REST API
- Register consumer(s) for event(s) to consume filtered message queue(s) via Webhook URL
- Use HTTP client to obtain payload when a message is delivered
Webhook URL template
- Consumer webhook URL is provided by developer partner, e.g.
https://yourwebhookapi.com/webhook - It is recommended to use different URL for each stage (DEMO and PROD)
POST {webhookUrl}/{messageType}/{contractType}/{messageId}
| path variable | description |
|---|---|
| messageType | name of the message type (routing key) |
| contractType | name of the class/contract |
| messageId | unique id of the message |
Webhook request headers
Sample of request headers (shortened):
Authorization: Bearer ...
Content-Type: application/json; charset=utf-8
X-Tenant-Id: ...
X-UserClaim-Actort: ...
X-UserClaim-client_id: ...
X-UserClaim-iss: ...
X-UserClaim-locale: ...
X-UserClaim-orgs_codes: ...
X-UserClaim-sub: ...
X-UserClaim-tid: ...
X-UserClaimsExtended: ...
| header | description |
|---|---|
| Authorization | JWT token created by MessageGateway. It identifies the service context of the communication channel and is not tenant-specific. |
| X-UserClaim-Actort | Person id (Actor) in user context. |
| X-UserClaim-client_id | Client identification in user or service context. |
| X-UserClaim-iss | Issuer in user or service context. |
| X-UserClaim-locale | Language and region context (RFC 5646 / ISO-639-2) in user or service context. |
| X-UserClaim-orgs_codes | Selected organizations (organization.code) - Organization national number|Country code. |
| X-UserClaim-sub | User identification (SSO unique identifier) in user context. |
| X-UserClaim-tid | Tenant identification of selected tenant in user or service context. |
| X-UserClaimsExtended | Extended claims in user or service context in Base64 encoded JSON format. |
| X-MessageSecurityCode | The legacy message security code for the message to keep compatibility with legacy systems. |
| X-Tenant-Id | Tenant context identification of the specific message. The value originates in the service that published the message. |
Sample of UserClaimsExtended request header (shortened):
[
{ "Key": "nbf", "Value": "..." },
{ "Key": "idp", "Value": "..." },
{ "Key": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "Value": "..." },
{ "Key": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "Value": "..." },
{ "Key": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", "Value": "..." },
{ "Key": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", "Value": "..." },
{ "Key": "tname", "Value": "..." },
{ "Key": "organizations", "Value": "..." },
{ "Key": "auth_orgs", "Value": "..." },
{ "Key": "auth_orgs_codes", "Value": "..." },
{ "Key": "jti", "Value": "..." },
{ "Key": "iat", "Value": "..." }
]
Webhook request body
Message is sent in HTTP body in JSON format.
Securing incoming webhook requests
A webhook endpoint is publicly reachable over HTTPS, therefore the consumer must validate the incoming request before processing the notification. The current webhook security model combines a signed authentication token representing identification of communication channel with delivery-context headers of incoming http requests.
Authentication token
Each request contains Authorization: Bearer <token>.
MessageGateway creates this JWT as the authentication identity and context of the communication channel.
The token is intentionally not tied to a specific tenant or to the identity/context of an individual notification message.
It can therefore be used for messages with different tenants and different originating message contexts.
The token is signed using the RS256 algorithm. The consumer verifies its signature using public signing keys published through the AVAplace identity-provider configuration:
https://[hostname]/api/asol/idp/.well-known/openid-configuration
https://[hostname]/api/asol/idp/.well-known/jwks
For example, the DEMO signing keys are published at:
https://demo.avaplace.com/api/asol/idp/.well-known/jwks
Signing keys may be rotated. Consumers should therefore use the published OpenID Connect/JWKS configuration instead of embedding a certificate or public key permanently in application code.
A successful JWT validation authenticates the communication channel.
Claims contained in this token, such as iss, sub or client_id describe that channel authentication context.
They must not be interpreted as the identity or tenant context of every individual message delivered through the channel.
This distinction is important for multi-tenant processing. The notification-channel JWT is non-tenant specific, while the each message can carry own tenant and user context.
Message request headers
Headers such as X-Tenant-Id and X-UserClaim-* describe the tenant-context and user-context of the specific notification message.
These values are created by the originating platform service when that service publishes the notification message to the message bus.
They are propagated with the message and later included by MessageGateway into the webhook request.
A webhook consumer can therefore need the tenant header to process the notification in the correct tenant context.
X-UserClaim-tid- represents the specific tenant-context in user identity (so called runtime-context)X-Tenant-Id- represents the specific tenant-context explicitly assigned to message (so called tenant-context), typically used when user identity is impersonated by service context
Under normal circumstances, both values should be the same.
The message-context headers can also be used by the messaging infrastructure for message filtering/routing before the notification is delivered. On the webhook consumer side they describe the original message context and can be useful for processing, diagnostics, troubleshooting and correlation according to the integration contract.
X-MessageSecurityCode is a legacy proprietary mechanism that was introduced to protect propagated messages against spoofing or modification.
It is still present in the current webhook contract and legacy integrations may be required to validate it, but it is no longer recommended for new integrations.
Recommended request validation flow
Before the notification payload is accepted for business processing, the consumer should:
- Accept the webhook only over HTTPS.
- Require an
Authorizationheader using theBearerscheme. - Cryptographically validate the JWT signature against a currently published identity-provider signing key and require the expected signing algorithm (
RS256). - Validate standard JWT validity constraints, especially token lifetime (
expandnbfwhen present), and validate the expected issuer (iss) and audience (aud) when defined for the integration. Expected values must come from trusted consumer configuration. - Read the message-specific user identity and tenant context from the request headers required by the integration contract.
- Validate the request route and payload required by the integration before business processing.
- Use
messageIdto make processing idempotent. A repeated delivery of the same message must not create the same business effect twice. - Return an HTTP 2xx response only after the notification has been accepted according to the consumer's processing strategy.
The exact implementation depends on the consumer technology.
Standard JWT/OIDC libraries are recommended because they handle signature verification, key selection by kid, token lifetime validation and signing-key rotation.
See the technical webhook integration examples for implementation guidance.
Message acknowledgment and redelivery
Examples - OrderReleased scenario
Webhook URL
POST https://yourwebhookapi.com/webhook/ASOL.PlatformStore.OrderReleased/OrderReleased/c0eb0000-5dfe-0015-8604-08dbd6ef8bf7
| path variable | value |
|---|---|
| messageType | ASOL.PlatformStore.OrderReleased |
| contractType | OrderReleased |
| messageId | unique for each receive message |
Webhook headers
Authorization: Bearer ...
Content-Type: application/json; charset=utf-8
X-Tenant-Id: ASOLEU-DEV-fd9ad6b9-2f29-4c7a-9a3a-c7469e19b1ff
X-UserClaim-Actort: c042e6ad-f293-4e36-8266-574b665792ff
X-UserClaim-client_id: plaza-pass
X-UserClaim-iss: https://demo.avaplace.com/api/asol/idp
X-UserClaim-locale: cs-CZ
X-UserClaim-orgs_codes: 64949541|CZ
X-UserClaim-sub: 6388701d4a20a1c1bc1f0831
X-UserClaim-tid: ASOLEU-DEV-fd9ad6b9-2f29-4c7a-9a3a-c7469e19b1ff
X-UserClaimsExtended: [{"Key":"nbf","Value":"1698409522"},{"Key":"idp","Value":"local"},{"Key":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name","Value":"petr.tomala@assecosol.com"},{"Key":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress","Value":"petr.tomala@assecosol.com"},{"Key":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Value":"Petr"},{"Key":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","Value":"Tomala"},{"Key":"tname","Value":"ASOLEU-DEV"},{"Key":"organizations","Value":"fff2d400-9838-4513-9c7b-535a03bd8c94"},{"Key":"auth_orgs","Value":"fff2d400-9838-4513-9c7b-535a03bd8c94"},{"Key":"auth_orgs_codes","Value":"64949541|CZ"},{"Key":"jti","Value":"9781FBFE8F78C7F7802F494947860804"},{"Key":"iat","Value":"1698409522"}]
Webhook body
{
"orderId": "b0588700-f3a2-4bde-bbb4-d2022bf7851e",
"productId": "98fa6110-ec8b-45a4-882f-b5a1e89812ca",
"vendorCode": "64949541|CZ"
}
See examples:
Examples - RefreshSourceStatus scenario
Webhook URL
POST https://yourwebhookapi.com/webhook/ASOL.DataService.RefreshSourceStatus/RefreshStatusEvent/01000000-d3ff-1268-1fe0-08df06d5fef7
| path variable | value |
|---|---|
| messageType | ASOL.DataService.RefreshSourceStatus |
| contractType | RefreshStatusEvent |
| messageId | unique for each receive message |
Bearer token
{
"iss": "https://beta.avaplace.com/api/asol/idp",
"exp": 1788286751,
"iat": 1788283151,
"aud": "apiim",
"sub": "plaza-services",
"client_id": "plaza-services",
...
}
Webhook headers
Authorization: Bearer ...
Content-Type: application/json; charset=utf-8
X-Tenant-Id: ASOLEU-DEV-fd9ad6b9-2f29-4c7a-9a3a-c7469e19b1ff
X-UserClaim-client_id: ASOLEU-DataService-AP-
X-UserClaim-tid: ASOLEU-DEV-fd9ad6b9-2f29-4c7a-9a3a-c7469e19b1ff
X-UserClaimsExtended: []
Webhook body
{
"sourceId": "6049f30a-ce57-48e4-a97c-02e3e2edae1f",
"checkConnection": true
}
See examples: