Receive Stormedo deliveries
Use this procedure for an endpoint you control. For a third-party API, supply that API’s destination credentials through forwarded headers; you do not need to modify its server to accept Stormedo signatures.
Choose a runnable receiver
Section titled “Choose a runnable receiver”- Express webhook receiver: Node.js, Express, and the JavaScript SDK.
- FastAPI webhook receiver: Python, FastAPI, and the Python SDK.
Both examples verify the original request bytes, parse the JSON event, and print it in your terminal. They return 204 to acknowledge the delivery. You can run them without setting up a database.
Configure the destination
Section titled “Configure the destination”- Run the receiver with
STORMEDO_PROJECT_IDandPUBLIC_WEBHOOK_URL. The project ID is thedata.project_idreturned by a successful send using your project’s API key, such as the quickstart. - Set
PUBLIC_WEBHOOK_URLto the complete HTTPS URL you will submit to Stormedo, including its path and any query string. Use the same canonical URL in both places. Trailing slashes and query strings matter. - Expose the endpoint at that public URL. Stormedo cannot reach
localhost, a private IP, or a private network. For local development, use a public HTTPS tunnel to the local receiver and configure its HTTPS URL as the expected audience. - Reuse one verifier per process. It retrieves public project keys and caches them. Receiving does not require your publisher API key.
Do not reconstruct the trusted audience from an arbitrary Host, Forwarded, or X-Forwarded-* header. A reverse proxy may terminate TLS or rewrite paths; the verifier still needs the original public destination URL.
Process in this order
Section titled “Process in this order”raw HTTP bytes and exactly one of each signing header → verify signature, project, URL, method, request ID, time, and body → parse the JSON event → log the received event → return 204Read no more than 256 KiB. Register raw-body handling before JSON middleware. Parsing and serializing JSON again changes the bytes even when the data looks identical.
The signature is short lived. Verify at ingress before putting work into another queue. If you acknowledge after writing to your own durable queue, that queue and its consumers become responsible for finishing the business operation.
Make duplicates safe before adding business logic
Section titled “Make duplicates safe before adding business logic”The examples log each verified delivery, including repeats. Before replacing the log with a business action, validate the event fields and make repeated delivery safe.
Use the verified request ID to deduplicate attempts. Store it and the business change in the same transaction, with a unique constraint. On a duplicate, acknowledge after confirming the original transaction committed. Roll back both records if processing fails.
Replay creates a new Stormedo request ID. To deduplicate the business event across replays too, include a stable event ID in the payload and give it a unique constraint. Keep deduplication records for as long as a repeated event would be harmful, including your manual replay window.
A database transaction cannot atomically commit an external network call. For that case, use the destination API’s idempotency key or a transactional outbox. See Idempotency.
Choose the response deliberately
Section titled “Choose the response deliberately”| Outcome | Receiver response | What happens next |
|---|---|---|
| Work committed, or a known duplicate | 204 |
Stormedo marks delivery successful. |
| Missing/duplicated signing header or invalid event | 400 |
Terminal failure; correct the publisher or receiver before replay. |
| Invalid signature, project, audience, time, or body | 401 |
Terminal failure; investigate configuration or tampering. |
| Public-key fetch temporarily unavailable | 503 |
Retryable if the request has attempts remaining. |
| Temporary database or processing failure | 500 or 503 |
Retryable if attempts remain. Do not commit the deduplication row. |
Every 2xx is success, including 202. Return it only after the side effect or your own durable handoff has committed. Stormedo does not inspect your response body for an application-level error.
Send and inspect
Section titled “Send and inspect”Submit the example’s event with at least a few attempts configured. Keep the returned data.id, open it in Requests, and check the completed attempt’s status code. A brief initial 404 in the read API can mean history is still catching up.
Use delivery troubleshooting for failures and the signing protocol when implementing another language.