Azure Event Grid has a validation handshake that trips up most simple webhook endpoints. When you subscribe to an event, Azure sends a SubscriptionValidationEvent and expects your endpoint to echo back the validation code within seconds. Miss it, and your subscription stays in a pending state.
Beyond that, Azure's Event Grid schema wraps your actual data inside nested objects with metadata you probably do not need. Hookpipe handles the handshake automatically and transforms the payload into something your app actually wants.
When you create an Azure Event Grid subscription, Azure POSTs a validation request:
[
{
"id": "2d1781af-3a4c-4d23-a5e3-6f8e6c7f8f9a",
"topic": "/subscriptions/.../resourceGroups/.../providers/Microsoft.Storage/storageAccounts/mystorage",
"subject": "",
"data": {
"validationCode": "ABC123...",
"validationUrl": "https://..."
},
"eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
"eventTime": "2026-02-26T12:00:00Z",
"metadataVersion": "1",
"dataVersion": "2"
}
]
Your endpoint must respond with HTTP 200 and echo the validationCode:
{
"validationResponse": "ABC123..."
}
Most custom endpoints aren't built to handle this. Hookpipe handles it for you.
Hookpipe recognizes Microsoft.EventGrid.SubscriptionValidationEvent automatically. When it sees this event type, it responds with the correct validation response: no configuration needed.
Your subscription activates immediately without you writing any handshake code.
Once validated, Azure sends your actual events in its Event Grid schema — a JSON envelope with metadata fields like eventType, subject, and eventTime wrapping the real data:
{
"id": "12345",
"eventType": "Microsoft.Storage.BlobCreated",
"subject": "/blobServices/default/containers/container1/blobs/file.jpg",
"data": {
"api": "PutBlob",
"clientRequestId": "abc-123",
"url": "https://mystorage.blob.core.windows.net/container/file.jpg",
"sequencer": "00000000000000000000"
},
"eventTime": "2026-02-26T12:00:00Z",
"dataVersion": "1"
}
{
"event": "Microsoft.Storage.BlobCreated",
"fileUrl": "https://mystorage.blob.core.windows.net/container/file.jpg",
"operation": "PutBlob",
"requestId": "abc-123",
"resource": "/blobServices/default/containers/container1/blobs/file.jpg",
"timestamp": "2026-02-26T12:00:00Z"
}
Hookpipe's field mapping pulls from nested paths and flattens everything:
curl -X POST https://hookpipe.app/api/hooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "azure-blob-events",
"destinationUrl": "https://your-app.com/api/azure",
"transformConfig": {
"fieldMapping": {
"event": "eventType",
"fileUrl": "data.url",
"operation": "data.api",
"requestId": "data.clientRequestId",
"resource": "subject",
"timestamp": "eventTime"
},
"filters": [
{ "field": "eventType", "operator": "contains", "value": "Microsoft.Storage" }
]
}
}'
Point it at your internal endpoint that processes Azure events:
curl -X POST https://hookpipe.app/api/hooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "azure-event-grid",
"destinationUrl": "https://your-app.com/api/ingest/azure",
"transformConfig": {
"fieldMapping": {
"event": "eventType",
"timestamp": "eventTime",
"resourceId": "subject"
}
}
}'
Use the Hookpipe URL as your endpoint:
az eventgrid event-subscription create \
--name my-hook \
--resource-group my-rg \
--provider-namespace Microsoft.Storage \
--resource-type storageAccounts \
--resource-name mystorage \
--endpoint https://hookpipe.app/hooks/YOUR_HOOK_ID
Azure sends the validation event. Hookpipe responds automatically. Your subscription shows as "Enabled" in the Azure portal: no manual steps required.
Supported Azure services
Hookpipe works with any Azure service that uses Event Grid: Storage (Blob, Queue, Table), Event Hubs, Service Bus, IoT Hub, Key Vault, and custom topics. The validation handshake is handled the same way for all of them.
Skip the validation boilerplate. Get clean payloads instead of nested Azure envelopes.