Event Grid Webhook Endpoints
Azure Event Grid can deliver events to any publicly accessible HTTPS endpoint. This endpoint is called a webhook. Webhooks open Event Grid to any application, platform, or service — not just Azure services. A custom web application, a third-party platform, or a service running in any cloud can receive Event Grid events through a webhook.
What Is a Webhook
A webhook is an HTTP endpoint that listens for incoming POST requests. When Event Grid delivers an event, it sends an HTTP POST request to the webhook URL with the event data in the request body.Think of a webhook like a doorbell. You register your address (webhook URL) with the post office (Event Grid). When mail (an event) arrives, the post office rings your doorbell (sends a POST request). Your application opens the door and processes the mail.
Event Occurs in Azure
|
| Event Grid picks it up
v
+--------------------+
| Event Grid |
| Subscription |
| Endpoint: |
| https://myapp |
| .com/events |
+--------+-----------+
|
| HTTP POST with event JSON
v
+--------------------+
| Your Webhook |
| Endpoint |
| (any HTTPS URL) |
| |
| Reads event body |
| Processes it |
| Returns 200 OK |
+--------------------+
Webhook Validation: Required First Step
When you create a subscription with a webhook endpoint, Event Grid does not immediately start sending events. It first sends a validation request to confirm that you own and control the webhook URL.
Validation Flow
Step 1: You create an Event Grid subscription with webhook URL
Step 2: Event Grid sends a SubscriptionValidationEvent:
{
"id": "abc123",
"eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
"data": {
"validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6",
"validationUrl": "https://rp-eastus.eventgrid.azure.net/eventSubscriptions/..."
}
}
Step 3 (Option A – Synchronous Validation):
Your endpoint reads validationCode and returns it:
HTTP 200 OK
{
"validationResponse": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6"
}
Step 3 (Option B – Manual Validation):
Visit validationUrl in a browser within 5 minutes
(for endpoints you cannot modify, like a third-party service)
Step 4: Subscription becomes Active and real events start flowing
Implementing Validation in Your Webhook
C# ASP.NET Core Controller
[HttpPost("events")]
public IActionResult ReceiveEvents([FromBody] object[] events)
{
foreach (var eventObj in events)
{
var eventData = JsonDocument.Parse(eventObj.ToString());
var root = eventData.RootElement;
var eventType = root.GetProperty("eventType").GetString();
// Handle validation handshake
if (eventType == "Microsoft.EventGrid.SubscriptionValidationEvent")
{
var validationCode = root
.GetProperty("data")
.GetProperty("validationCode")
.GetString();
return Ok(new { validationResponse = validationCode });
}
// Handle real events
if (eventType == "Microsoft.Storage.BlobCreated")
{
var subject = root.GetProperty("subject").GetString();
Console.WriteLine($"New blob created: {subject}");
// process the event
}
}
return Ok();
}
Node.js Express Example
app.post('/events', (req, res) => {
const events = req.body;
for (const event of events) {
// Validation handshake
if (event.eventType === 'Microsoft.EventGrid.SubscriptionValidationEvent') {
const validationCode = event.data.validationCode;
return res.json({ validationResponse: validationCode });
}
// Real event processing
console.log('Event type:', event.eventType);
console.log('Subject:', event.subject);
console.log('Data:', JSON.stringify(event.data));
}
res.status(200).send('OK');
});
Event Delivery to Webhooks
Event Grid sends events as an HTTP POST with a JSON array in the body. Even a single event arrives inside an array.
Sample HTTP Request from Event Grid
POST /events HTTP/1.1
Host: myapp.com
Content-Type: application/json
aeg-event-type: Notification
[
{
"id": "d521b1d3-9e8a-4bd0-a3c1-f78a901bc234",
"topic": "/subscriptions/.../storageAccounts/mystorage",
"subject": "/blobServices/default/containers/images/blobs/photo.jpg",
"eventType": "Microsoft.Storage.BlobCreated",
"eventTime": "2024-09-15T10:22:05.000Z",
"data": {
"url": "https://mystorage.blob.core.windows.net/images/photo.jpg",
"contentType": "image/jpeg",
"contentLength": 45678
},
"dataVersion": "1.0"
}
]
HTTP Response Requirements
Your webhook must return a specific HTTP status code for Event Grid to consider delivery successful.| HTTP Status Code | Event Grid Behavior |
|---|---|
| 200 OK | Delivery successful |
| 201 Created | Delivery successful |
| 202 Accepted | Delivery successful |
| 204 No Content | Delivery successful |
| 400 Bad Request | Delivery failed — Event Grid does NOT retry |
| 401 Unauthorized | Delivery failed — retried by Event Grid |
| 404 Not Found | Delivery failed — retried by Event Grid |
| 408 Request Timeout | Delivery failed — retried by Event Grid |
| 500 Internal Server Error | Delivery failed — retried by Event Grid |
| 503 Service Unavailable | Delivery failed — retried by Event Grid |
Return 400 only if the event is genuinely malformed and retrying is pointless. Return 500 or 503 when a temporary failure occurs and a retry might succeed.
Webhook Processing Timeout
Event Grid waits 60 seconds for your webhook to respond. If your webhook takes longer than 60 seconds, Event Grid marks the delivery as failed and retries.For long-running tasks, follow this pattern:
Webhook receives event
|
| Accept the event immediately
| Return 200 OK within a few seconds
|
v
Place event in an internal queue
(Azure Storage Queue or Service Bus)
|
| Return 200 OK → Event Grid satisfied
v
Background worker reads from internal queue
|
| Performs the long operation
| (could take minutes or hours)
v
Operation completed asynchronously
Securing Your Webhook
A public webhook URL is accessible to anyone. You must verify that POST requests come from Event Grid, not from malicious actors.
Option 1 – Webhook Secret Header
Add a secret query parameter or custom header to your webhook URL. Event Grid passes it with every delivery. Your endpoint checks it.
Webhook URL: https://myapp.com/events?secret=my-secret-token-xyz
Your code:
string incomingSecret = Request.Query["secret"];
if (incomingSecret != "my-secret-token-xyz")
return Unauthorized();
Option 2 – Azure AD Authentication
Configure the subscription to use Azure Active Directory to authenticate against the webhook endpoint. The endpoint validates the JWT token in the Authorization header.
Option 3 – IP Allowlisting
Azure publishes the IP ranges that Event Grid uses to deliver events. Allowlist these IP ranges on your firewall or API gateway.
Batching Events to Webhooks
By default, Event Grid sends one event per HTTP request. For high-volume scenarios, enable batch delivery to improve efficiency.+---------------------------+ | Webhook Subscription | | Batching Settings: | | | | Max Events Per Batch: 50 | | Preferred Batch Size: 25KB| +---------------------------+ With batching enabled: Event Grid → one HTTP POST containing up to 50 events at once Your webhook processes all 50 in one request Fewer HTTP round-trips = higher throughput
Configure batching in: Event Grid Subscription → Additional Features → Enable Batching
Webhook vs Azure Service Endpoints
| Aspect | Webhook | Azure Function / Logic App |
|---|---|---|
| Works with non-Azure apps | Yes | No |
| Requires public HTTPS URL | Yes | No |
| Validation handshake needed | Yes | Handled automatically |
| Auto-scales | Depends on your app | Yes |
| Retry on failure | Yes (by Event Grid) | Yes |
