Replies: 3 comments
-
Open Questions
|
Beta Was this translation helpful? Give feedback.
0 replies
-
Open QUestion Answers
|
Beta Was this translation helpful? Give feedback.
0 replies
-
|
This feature will not be implemented & instead, the webhook event handling will be supported via Platform API. Therefore, going forward, the same connection between GW & CP (Websocket) will be used to propagate Devportal changes to GW by emitting events to Platform API webhook endpoint. Hence, close the discussion. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Problem Statement
API Platform Gateway currently does not have a dedicated webhook event handling path for events emitted by other platform components. This becomes a limitation when another component, such as Developer Portal or Management Portal, performs an operation asynchronously and Gateway needs to become aware of that operation later.
Examples:
Related Discussions : #1774
Scope
This effort focuses on the Gateway-side webhook implementation.
The first set of supported event families will be:
apikey.generatedapikey.regeneratedapikey.revokedsubscription.createdsubscription.plan_changedsubscription.deletedProposal
High-Level Flow
Webhook Endpoint
POST /webhook/eventsConfiguration options
enabled- control whether the gateway webhook endpoint is registeredsecret- the HMAC signing secret shared with the event producerprivate_key_path- points to the GW private key used to decrypt encrypted sensitive payload data fieldsgateway_type- used to filter events meant for this gw typesignature_tolerance- prevents replay atatcks using old signed requestsmax_body_size- protects endpoint from unexpectedly large request bodiesEvent Envelope
{ "event_id": "550e8400-e29b-41d4-a716-446655440000", "event_type": "apikey.generated", "occurred_at": "2026-04-24T10:00:00.000Z", "org_id": "org-uuid", "gateway_type": "wso2/api-platform", "schema_version": "1.0", "aggregate_id": "domain-object-id", "data": {} }aggregate_id- Stable domain objecr ID affected by the eventaggregate_idshould be included for events where the affected domain object must be identified even when event-specific fields are missing or changed later.Security Model
Signature Verification
Each webhook request must include an HMAC-SHA256 signature header.
Ex:
X-Devportal-Signature: t=1713952800,v1=<calculated_hmac>The signature should be calculated over the raw request body.
Sensitive Data Decryption
{ "encrypted_key": { "wrappedKey": "<base64>", "iv": "<base64>", "tag": "<base64>", "ciphertext": "<base64>" } }HTTP Processing Flow
flowchart TD A[POST /devportal/events] --> B{Webhook enabled?} B -- No --> C[404] B -- Yes --> D[Read raw body with size limit] D --> E{Signature valid?} E -- No --> F[401 Unauthorized] E -- Yes --> G[Decode event envelope] G --> H{Envelope valid?} H -- No --> I[400 Bad Request] H -- Yes --> J{gateway_type matches?} J -- No --> K[202 Accepted as no-op] J -- Yes --> L{Dispatch by event_type} L --> M[Apply event-specific DB idempotency check] M --> N{Domain state already persisted?} N -- Yes --> O[Skip duplicate DB write] N -- No --> P[Persist domain state] O --> Q[Publish EventHub event for replicas] P --> Q Q --> R{Publish successful?} R -- No --> S[500 Retryable failure] R -- Yes --> T[Refresh policy engine state using xDS] T --> U{Refresh successful?} U -- No --> V[500 Retryable failure] U -- Yes --> W[200 OK or 202 Accepted]Webhok vs Normal GW API
Suggested Package Structure for Development
API Key Event Handling
Supported Events
apikey.generatedapikey.regeneratedapikey.revokedAPI Key Generation Event Payload
{ "event_id": "event-uuid", "event_type": "apikey.generated", "occurred_at": "2026-04-24T10:00:00.000Z", "org_id": "org-uuid", "gateway_type": "wso2/api-platform", "schema_version": "1.0", "aggregate_id": "key-uuid", # Optional "data": { "key_id": "key-uuid", // Uses for external_ref_id, required field "name": "my-key", "expires_at": "2027-01-01T00:00:00.000Z", "api": { "ref_id": "api-handle", // required for api key generation to identify the API related to generated key "name": "Order API", "version": "1.0.0" }, "subscription": { // Though subscription object is sent in the event, still there's no usage when processing event "ref_id": "subscription-uuid", "plan_name": "Gold" }, "encrypted_key": { "wrappedKey": "<base64>", "iv": "<base64>", "tag": "<base64>", "ciphertext": "<base64>" } } }API Key Revoke Event Payload
{ "event_id": "event-uuid", "event_type": "apikey.revoked", "occurred_at": "2026-04-24T10:00:00.000Z", "org_id": "org-uuid", "gateway_type": "wso2/api-platform", "schema_version": "1.0", "aggregate_id": "key-uuid", # Optional "data": { "key_id": "key-uuid", // required "name": "my-key", "api": { "name": "MyFlights API", "version": "1.0.0", "ref_id": "api_handler" } }API Key Regenerate Event Payload
{ "event_id": "event-uuid", "event_type": "apikey.regenrated", "occurred_at": "2026-04-24T10:00:00.000Z", "org_id": "org-uuid", "gateway_type": "wso2/api-platform", "schema_version": "1.0", "aggregate_id": "key-uuid", # Optional "data": { "key_id": "key-uuid", // required "name": "my-key", "api": { "name": "MyFlights API", "version": "1.0.0", "ref_id": "api_handler" } }data.key_id: This will be mapped toexternal_ref_idofapi_keystable, useful toapi_key.generatedevent receivesapi_key.regenerateorapi_key.revokedevent receivesAPI Reference Resolution
data.api.ref_idshould resolve to Gateway artifact handle.API Key Generation Flow
data.api.ref_iddata.encrypted_keyAPI Key Regeneration/Revoke
data.key_idwhich maps toexternal_ref_idof GW database to identify the exact API key.Subscription Event Handling
Supported Events
susbcription.createdsubscription.plan_changedsubscription.deletedSubscription Creation Event Payload
{ "event_id": "event-uuid", "event_type": "subscription.created", "occurred_at": "2026-04-24T10:00:00.000Z", "org_id": "org-uuid", "gateway_type": "wso2/api-platform", "schema_version": "1.0", "aggregate_id": "subscription-uuid", // Optional "data": { "subscription_plan": { "ref_id": "subscription_plan_name", // required, since org+plan_name unique in DB "status": "ACTIVE" }, "api": { "ref_id": "api_handle", // required "name": "Order API" "version": "1.0.0" }, "encrypted_key": { "wrappedKey": "<base64>", "iv": "<base64>", "tag": "<base64>", "ciphertext": "<base64>" } } }Subscription Deletion Event Payload
{ "event_id": "event-uuid", "event_type": "subscription.deleted", "occurred_at": "2026-04-24T10:00:00.000Z", "org_id": "org-uuid", "gateway_type": "wso2/api-platform", "schema_version": "1.0", "aggregate_id": "subscription-uuid", // Optional "data": { "subscription_plan": { "ref_id": "subscription_plan_name", "plan_name": "Gold", // Optional "status": "ACTIVE" // Optional }, "api": { "name": "MyFlights API", "version": "1.0.0", "ref_id": "api_handle" } } }Subscription Reference Resolution
data.api.ref_idshould resolve GW API handledata.subscription_plan.ref_idshould resolve subscription plan name for the provided orgSubscription Creation Flow
data.api.ref_iddata.susbcription_plan.ref_iddata.encryted_keySubscription Plan Update/Delete
ref_ids to identify the subscription.Persistence and State Update Order
Idempotency
500causes Developer Portal to retry the same event.sequenceDiagram participant DP as Developer Portal participant GW as Gateway Controller participant DB as Gateway Storage participant XDS as xDS Snapshot Manager participant EH as EventHub DP->>GW: POST event GW->>GW: Verify signature and validate envelope GW->>DB: Check event-specific domain state alt State not found GW->>DB: Persist domain state else State already exists GW->>GW: Skip duplicate DB write end GW->>XDS: Refresh policy engine state alt xDS refresh fails GW-->>DP: 500 Retryable failure else xDS refresh succeeds GW->>EH: Publish internal replica event alt EventHub publish fails GW-->>DP: 500 Retryable failure else EventHub publish succeeds GW-->>DP: 200 OK end endEventHub & Replica Synchronization
Error Handling
404401401401400400400202200500500Beta Was this translation helpful? Give feedback.
All reactions