CloudEvents: Test Azure Event Grid Webhooks with Beeceptor
In this tutorial, you will test Azure Event Grid CloudEvents webhooks with Beeceptor. You will see how Beeceptor answers the webhook validation handshake automatically, test two workflows (inspecting events live in the dashboard and forwarding them to a POST-only backend), and simulate delivery failures such as rate limits and timeouts.
CloudEvents is an open specification for describing event data. Services like Azure Event Grid, GCP Eventarc, and AWS EventBridge use it to format events consistently across systems. The specification defines common fields for the event envelope:
id: A unique string for each event.source: A URI identifying which system published the event.specversion: The specification version (usually1.0).type: The kind of event that occurred, such asMicrosoft.Storage.BlobCreated.data: The application payload, like order details or uploaded file metadata.
CloudEvents can arrive in two ways over HTTP:
- Structured mode: The full event, including metadata and
data, arrives as a single JSON object in the request body withContent-Type: application/cloudevents+json. - Binary mode: Metadata values arrive as HTTP headers (such as
ce-idandce-type), while the request body contains only the raw application payload.
Try a Live CloudEvents Endpoint
Create a mock server in seconds to test handshakes and inspect incoming payloads in real time.
Why Use CloudEvents?
Managed by the Cloud Native Computing Foundation (CNCF), CloudEvents standardizes event delivery across platforms. Common uses include:
- Routing events across cloud providers (such as Azure Event Grid, GCP Eventarc, and AWS EventBridge) into internal services without custom payload adapters.
- Filtering at gateways or proxies using standard envelope headers (
ce-type,ce-source) without parsing the request body. - Correlating events across services using standard attributes like
timeandtraceparent. - Testing event publishers and verifying payload schemas before downstream consumer services are deployed.
The Webhook Handshake Problem
Before a cloud platform delivers events to a webhook, it checks whether the endpoint wants to receive them. This check is the abuse protection handshake.
When you create a webhook subscription in Azure Event Grid, Azure sends an HTTP OPTIONS request to your URL:
OPTIONS /api/events HTTP/1.1
Host: your-endpoint.free.beeceptor.com
WebHook-Request-Origin: eventgrid.azure.net
WebHook-Request-Rate: 120
Azure expects your server to respond with HTTP 200 or 204 and matching response headers:
HTTP/1.1 204 No Content
Allow: POST
WebHook-Allowed-Origin: eventgrid.azure.net
WebHook-Allowed-Rate: 120
If your server returns 404 Not Found, 405 Method Not Allowed, or omits the WebHook-Allowed-Origin header, Azure cancels the setup and refuses to create the subscription.
Most backend frameworks (like Spring, Express, or FastAPI) are written with a single POST /api/events handler. When pointing a cloud subscription directly at a development service, registration fails because nothing responds to OPTIONS.
Beeceptor answers this handshake automatically. When an OPTIONS request arrives with a WebHook-Request-Origin header, Beeceptor returns 204 No Content with the required WebHook-Allowed-Origin and Allow: POST headers, satisfying the CloudEvents specification without custom code.
The handshake validates that the endpoint agrees to receive event deliveries. It does not validate the CloudEvent envelope or the application's payload schema, and it does not authenticate subsequent event requests. Inspecting an event live in Beeceptor's dashboard lets you see what arrived; it does not establish that the event matches your application's contract. Configure any required authentication separately.
Step 1: Create a Beeceptor Endpoint
Start by creating a new endpoint in Beeceptor:
- Open Beeceptor and sign in.
- Enter an endpoint name, such as
cloud-events-demo. - Click Create Endpoint.
Beeceptor provides a unique subdomain:
https://cloud-events-demo.free.beeceptor.com
Keep the dashboard open in your browser so you can watch incoming requests.
Note: Replace
cloud-events-demowith your chosen endpoint name in all curl commands and configuration steps below.
Step 2: Test the Validation Handshake
You do not need a cloud account to verify that Beeceptor answers the handshake. Run this curl command from your terminal:
curl -i -X OPTIONS https://cloud-events-demo.free.beeceptor.com/api/events \
-H "WebHook-Request-Origin: eventgrid.azure.net" \
-H "WebHook-Request-Rate: 120"
In your terminal, curl -i prints the HTTP response headers:
HTTP/2 204
allow: POST
webhook-allowed-origin: eventgrid.azure.net
webhook-allowed-rate: 120
access-control-max-age: 86400
access-control-allow-origin: *
access-control-allow-methods: GET, PUT, POST, PATCH, DELETE, HEAD, QUERY, OPTIONS
Now switch to your Beeceptor dashboard. You will see the incoming OPTIONS /api/events request with a green 204 badge. Click View Headers on the response side to inspect the response headers:
{
"access-control-allow-origin": "*",
"access-control-max-age": "86400",
"access-control-allow-methods": "GET, PUT, POST, PATCH, DELETE, HEAD, QUERY, OPTIONS",
"webhook-allowed-origin": "eventgrid.azure.net",
"allow": "POST",
"webhook-allowed-rate": "120"
}
The response echoes the requested origin in webhook-allowed-origin and allows POST, satisfying the CloudEvents Webhook specification.
Step 3: Configure an Event Acknowledgment Rule
When Azure Event Grid or any CloudEvents producer delivers an event, it expects an HTTP 200 OK response to confirm delivery. Creating this acknowledgment rule first ensures Beeceptor is ready to accept deliveries the moment you register your subscription.
Configure a mock rule in Beeceptor:
- In your Beeceptor dashboard, click Mock Rules in the top navigation bar.
- Click New Rule.
- Under When following condition is matched:
- Set Method to
POST. - Set Request condition to
Request path exactly matchesand enter/api/events.
- Set Method to
- Under Do the following (for response):
- Set Return HTTP status as to
200. - Set the Response body to:
{"status": "ACCEPTED"}
- Set Return HTTP status as to
- Click Save.
With this rule active, Beeceptor responds to incoming CloudEvents deliveries with 200 OK and streams each event directly into your dashboard.
Step 4: Register in Azure Event Grid (Optional)
If you have an Azure account, you can connect real events to Beeceptor. Azure Event Grid Basic includes 100,000 free operations per month. Publishing events and attempting deliveries both count toward usage, and associated Azure resources may incur separate charges. Check Azure Event Grid pricing and your account usage before testing.
Tip: If you do not have an Azure account, skip directly to Step 5: Send and Inspect Events Live in the Dashboard to test with
curl.
You can create the subscription using either the Azure Portal or the Azure CLI:
Option A: Using the Azure Portal
- In the Azure Portal, open your Event Grid Topic (or navigate to an Azure Storage account and select the Events tab).
- Click + Event Subscription.
- Under Event Schema, select Cloud Event Schema v1.0.
- Under Endpoint Details:
- Set Endpoint Type to Web Hook.
- Click Configure an endpoint.
- In the Subscriber Endpoint field, enter your Beeceptor URL:
https://cloud-events-demo.free.beeceptor.com/api/events
- Click Confirm Selection.
- Click Create.
Azure sends the OPTIONS request to Beeceptor, receives the validation headers, and marks the subscription as active. Because your acknowledgment rule is already configured from Step 3, incoming event deliveries will immediately receive a 200 OK.
Option B: Using the Azure CLI
Alternatively, you can create the same subscription from your terminal:
az eventgrid event-subscription create \
--name "beeceptor-events" \
--source-resource-id "/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.EventGrid/topics/{topic}" \
--endpoint "https://cloud-events-demo.free.beeceptor.com/api/events" \
--event-delivery-schema "cloudeventschemav1_0"
Step 5: Send and Inspect Events Live in the Dashboard
Once the endpoint and acknowledgment rule are active, you can publish events and inspect them directly in Beeceptor's dashboard.
Send a Sample CloudEvent
Trigger an event from your Azure resource (such as uploading a file to Azure Storage), or simulate an incoming CloudEvent with curl. This payload matches Microsoft's official Blob Storage CloudEvents schema:
curl -i -X POST https://cloud-events-demo.free.beeceptor.com/api/events \
-H "Content-Type: application/cloudevents+json" \
-d '{
"specversion": "1.0",
"type": "Microsoft.Storage.BlobCreated",
"source": "/subscriptions/sub-123/resourceGroups/rg-prod/providers/Microsoft.Storage/storageAccounts/reports",
"id": "evt-771829",
"time": "2026-11-12T10:00:00Z",
"datacontenttype": "application/json",
"data": {
"url": "https://reports.blob.core.windows.net/invoices/inv-001.pdf",
"contentLength": 42100,
"contentType": "application/pdf"
}
}'
In your terminal, curl -i displays the 200 OK response:
HTTP/2 200
content-type: application/json
{
"status": "ACCEPTED"
}
Inspect Incoming Events Live in the Dashboard
Switch to your Beeceptor dashboard. As deliveries arrive, each CloudEvent streams directly into the live request console:
- Click a request to inspect the formatted JSON body, raw payload, and nested fields inside
data. In structured mode (used by the sample request above), envelope attributes such asid,source,specversion, andtypereside directly inside the JSON body. - Click View Headers to inspect HTTP transport headers. When publishers send events using binary mode rather than structured mode, CloudEvents attributes appear here as
ce-id,ce-type,ce-source, andce-specversionheaders while the body contains only the application payload. - Review delivery details including timestamps, HTTP methods, client IPs, and response codes.
Inspecting deliveries in real time lets you verify event formats instantly, without standing up a database or message queue during development.
Tip: Free endpoints display incoming requests live while the dashboard is open. If you need persistent 10-day retention, search filtering, and the Request History API, see HTTP Request History (available on Team plans).
Route Events to a POST-Only Backend
When your backend service is deployed, you might find that it only supports POST and fails the initial OPTIONS handshake. You do not need to rewrite application code. You can use Beeceptor Routing in front of your service.
Beeceptor answers the OPTIONS handshake at the Beeceptor endpoint, then forwards incoming POST requests directly to your backend.
Mock rules always take evaluation priority over routing. If your Step 3 POST /api/events mock rule remains active, Beeceptor will return its mock response instead of proxying traffic upstream.
To configure request forwarding:
- In your Beeceptor dashboard, open Mock Rules and disable (or delete) the
POST /api/eventsrule created in Step 3. - In the top navigation bar, click Routing.
- Select Forward Requests.
- In the Target Domain field, enter your upstream service address (or use Beeceptor's live echo service
https://echo.free.beeceptor.comto test forwarding without a deployed backend):https://your-service.acme.example - Click Save.
With this configuration:
- When Azure sends the
OPTIONShandshake, Beeceptor answers it directly at the Beeceptor endpoint with204 No Contentwithout contacting your backend. - When Azure delivers
POST /api/eventsCloudEvents, Beeceptor proxies the request directly to your target domain because no active mock rule intercepts it. - Beeceptor logs all forwarded requests and backend responses in the dashboard, giving you visibility into webhook traffic during end-to-end tests.
Test Forwarding with curl
Send the sample CloudEvent again using the curl command from Step 5. Because the mock rule is disabled, Beeceptor forwards the request directly to your target domain.
In your dashboard console, you can review the forwarded request along with the response status and payload returned by the upstream service.
Tip: If you prefer to route specific paths rather than the entire endpoint, open Mock Rules, click the dropdown arrow next to New Rule, and select New Callout Rule. Set the behavior to Wait for target response (synchronous), enter your target URL, and set payload to Forward original payload.
Simulate Failures and Retries
Cloud event publishers retry failed deliveries with exponential backoff. You can test error handling and recovery before deploying to production.
To simulate failures without rule conflicts, re-enable the existing POST /api/events mock rule from Step 3 (or create it if you deleted it during routing) and edit its response:
Simulate Rate Limiting (429)
To test how your sender handles rate limiting:
- In your Beeceptor dashboard, navigate to Mock Rules.
- Locate the existing
POST /api/eventsrule and click Edit (ensure the rule is enabled). - Set Return HTTP status as to
429. - Add a response header: click Response headers, enter
Retry-Afteras the header name and30as the value. - In Response body, update the payload to:
{"error": "RATE_LIMITED","message": "Too many requests. Please retry in 30 seconds."}
- Click Save.
Send the sample CloudEvent again using the curl command from Step 5. In your terminal, curl -i displays the 429 status and header:
HTTP/2 429
retry-after: 30
content-type: application/json
{
"error": "RATE_LIMITED",
"message": "Too many requests. Please retry in 30 seconds."
}
When clients and cloud emitters inspect the 429 Too Many Requests response, they can read the Retry-After: 30 header and pause further deliveries until the window expires.
Simulate Timeouts
Most cloud emitters enforce a 30-second delivery timeout:
- In Mock Rules, edit the same
POST /api/eventsrule and locate the Response delayed by field. - Enter
35(adding a 35-second delay to the response). - Click Save.
- Send the sample event again with
curl(or trigger an event in Azure). - Observe how the terminal waits for 35 seconds. In production, a cloud emitter drops the connection after 30 seconds, marks the delivery attempt as failed, and schedules a retry with exponential backoff.
Tip: Once you finish testing failure scenarios, remember to reset the delay to
0and status code to200, or disable the mock rule so normal forwarding resumes.
Summary
Cloud webhooks often fail during local testing because backends only implement POST, while event publishers require an initial OPTIONS handshake before delivering events.
Beeceptor bridges this gap with two workflows:
- Inspect events locally: Beeceptor answers the
OPTIONShandshake automatically and streams incoming CloudEvents into your live dashboard. You can inspect transport headers (ce-*), verify JSON payloads, and test cloud publishers without running a local consumer or database. - Forward to a POST-only backend: Beeceptor answers the handshake at the Beeceptor endpoint and forwards incoming
POSTrequests directly to your backend, letting you connect to cloud publishers without modifying application code.
When you need to test resilience, edit your mock rules to simulate rate limits (429 with Retry-After) and response timeouts, verifying that publishers retry as expected.