Delivery
Events
POST /events is the ingestion endpoint on the Express API. Its local default origin is http://127.0.0.1:3000.
Request body
curl --fail-with-body --max-time 10 \
--request POST http://127.0.0.1:3000/events \
--header 'Content-Type: application/json' \
--data '{
"tenantId": "REPLACE_WITH_TENANT_UUID",
"type": "order.shipped",
"payload": { "orderId": "order_123" }
}'const response = await fetch("http://127.0.0.1:3000/events", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
tenantId: "REPLACE_WITH_TENANT_UUID",
type: "order.shipped",
payload: { orderId: "order_123" },
}),
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) {
throw new Error(`Event rejected: ${response.status}`);
}
console.log(await response.json());import json
import urllib.request
body = json.dumps({
"tenantId": "REPLACE_WITH_TENANT_UUID",
"type": "order.shipped",
"payload": {"orderId": "order_123"},
}).encode("utf-8")
request = urllib.request.Request(
"http://127.0.0.1:3000/events",
data=body,
headers={"Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(request, timeout=10) as response:
print(json.load(response))REPLACE_WITH_TENANT_UUID with an existing tenant ID. Webhooks go to the worker’s configured RECEIVER_URL. Swipe or scroll within the code to read long lines.| Field | Requirement |
|---|---|
tenantId | Existing tenant UUID. |
type | Nonempty string, at most 200 characters. |
payload | Required JSON value; null is accepted. |
There is no destination field or ingestion idempotency key in this contract. Repeating an ingestion request can create another event.
Response and errors
On success, 201 returns eventId, outboxId and storedIn (postgres or s3). It confirms persistence, before queue publication or delivery.
| Status | Meaning |
|---|---|
| 201 | Event and outbox transaction committed. |
| 400 | Schema validation failed; Express also rejects malformed JSON. |
| 404 | Tenant does not exist. |
| 429 | Ingestion token bucket exhausted; Retry-After reports seconds. |
| 500 | Internal failure. |
| 413 | Request exceeds Express’s 2 MB JSON-body limit. |
Large payloads
Payload JSON above SQS_MAX_MESSAGE_BYTES (default 262144 bytes) is uploaded to S3 before the database transaction. The event and queue message retain a pointer instead of the oversized inline payload. This is a project threshold, not a claim about the current SQS service maximum.
The event and outbox entry commit atomically in PostgreSQL. S3 upload and the database transaction are separate operations.