Appearance
Events (Inbound)
About 654 wordsAbout 2 min
Inbound events are webhooks received via POST /ingest/{token}. GetHook persists every event with its full payload, headers, and delivery history.
Event lifecycle
received → queued → delivering → delivered
│
├── retry_scheduled (HTTP 4xx/5xx or timeout)
│ └── queued → delivering → ...
│
└── dead_letter (5 failed attempts)
Any terminal state (delivered, dead_letter) can be replayed:
replayed → new event created with status: queuedEvent statuses
| Status | Description |
|---|---|
received | Accepted at ingest, not yet queued |
queued | Ready for the delivery worker to pick up |
delivering | Worker is actively attempting delivery |
delivered | Successfully delivered (HTTP 2xx from destination) |
retry_scheduled | Failed delivery, scheduled for retry |
dead_letter | All 5 delivery attempts failed |
replayed | Original event superseded by a replay |
Event retention
Events are automatically deleted after your account's retention window has elapsed. Terminal events (delivered, dead_letter, replayed) are eligible for deletion; in-flight events (queued, delivering, retry_scheduled) are never deleted.
| Plan | Default retention |
|---|---|
| Free / Starter | 3 days |
| Pro | 30 days |
| Enterprise | 90 days |
Retention is configured via the
retention_daysfield on the account. The scheduler runs the cleanup once per hour.
To preserve events beyond your retention window, use the Exports API to download a copy before they expire.
Retry schedule
| Attempt | Delay after previous failure |
|---|---|
| 1 | Immediate |
| 2 | +30 seconds |
| 3 | +2 minutes |
| 4 | +10 minutes |
| 5 | +1 hour |
| → DLQ | After attempt 5 fails |
List inbound events
GET /v1/eventsAuthentication: Bearer
Returns the 50 most recent inbound events for the account.
Response 200 OK
{
"data": [
{
"id": "e1e2e3e4-e5f6-7890-abcd-ef1234567890",
"account_id": "a1a2a3a4-...",
"direction": "inbound",
"source_id": "s1s2s3s4-...",
"event_type": "payment.succeeded",
"external_event_id": "evt_stripe_abc123",
"status": "delivered",
"attempts_count": 1,
"received_at": "2024-01-15T10:00:00Z",
"created_at": "2024-01-15T10:00:00Z",
"next_attempt_at": null
}
]
}curl example
curl -s http://localhost:8080/v1/events \
-H "Authorization: Bearer $API_KEY" | jq .# Pretty-print just status and event type
curl -s http://localhost:8080/v1/events \
-H "Authorization: Bearer $API_KEY" | \
jq '.data[] | {id, event_type, status, attempts_count}'Get inbound event
Returns a single event with its full payload and all delivery attempts.
GET /v1/events/{id}Authentication: Bearer
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | UUID | The event ID |
Response 200 OK
{
"data": {
"event": {
"id": "e1e2e3e4-...",
"account_id": "a1a2a3a4-...",
"direction": "inbound",
"source_id": "s1s2s3s4-...",
"event_type": "payment.succeeded",
"external_event_id": "evt_stripe_abc123",
"body": "{\"amount\": 2000, \"currency\": \"usd\"}",
"headers": {
"Content-Type": "application/json",
"X-Event-Type": "payment.succeeded"
},
"payload_hash": "sha256:abc123...",
"status": "delivered",
"attempts_count": 1,
"received_at": "2024-01-15T10:00:00Z",
"next_attempt_at": null
},
"attempts": [
{
"id": "at1at2at3-...",
"event_id": "e1e2e3e4-...",
"destination_id": "d1d2d3d4-...",
"attempt_number": 1,
"outcome": "success",
"response_status": 200,
"response_body": "ok",
"attempted_at": "2024-01-15T10:00:05Z",
"duration_ms": 142
}
]
}
}Attempt outcomes
| Outcome | Description |
|---|---|
success | Destination returned HTTP 2xx |
http_4xx | Destination returned 4xx (not retried — client error) |
http_5xx | Destination returned 5xx (retried) |
timeout | Request timed out (retried) |
network_error | TCP/DNS failure (retried) |
cancelled | Worker shutdown during delivery |
Errors
| Status | Cause |
|---|---|
400 | {id} is not a valid UUID |
404 | Event not found or belongs to a different account |
curl example
curl -s http://localhost:8080/v1/events/e1e2e3e4-... \
-H "Authorization: Bearer $API_KEY" | jq .Replay inbound event
Marks the original event as replayed and creates a new event in queued status with the same payload and headers.
POST /v1/events/{id}/replayAuthentication: Bearer
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | UUID | The event ID to replay |
Response 202 Accepted
{
"data": {
"original_event_id": "e1e2e3e4-...",
"replay_event_id": "e9e8e7e6-...",
"status": "queued"
}
}The new replay_event_id event will be delivered using current routing rules (routes active at the time of replay, not at the time of original ingestion).
Errors
| Status | Cause |
|---|---|
400 | {id} is not a valid UUID |
404 | Event not found or belongs to a different account |
curl example
curl -s -X POST http://localhost:8080/v1/events/e1e2e3e4-.../replay \
-H "Authorization: Bearer $API_KEY" | jq .Common replay scenarios
# Replay all dead-letter events
curl -s http://localhost:8080/v1/events \
-H "Authorization: Bearer $API_KEY" | \
jq -r '.data[] | select(.status == "dead_letter") | .id' | \
while read id; do
echo "Replaying $id..."
curl -s -X POST http://localhost:8080/v1/events/$id/replay \
-H "Authorization: Bearer $API_KEY" | jq -r '.data.replay_event_id'
done