Skip to content

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.

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.

  1. Run the receiver with STORMEDO_PROJECT_ID and PUBLIC_WEBHOOK_URL. The project ID is the data.project_id returned by a successful send using your project’s API key, such as the quickstart.
  2. Set PUBLIC_WEBHOOK_URL to 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.
  3. 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.
  4. 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.

Plain text
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 204

Read 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.

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.

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.