Skip to content

Process inbound emails into tickets (GET)

GET
/cron/inbound-email
curl --request GET \
--url https://example.com/api/cron/inbound-email

Added by HO-8159. Drives the bounded inbound-email worker: claims inbound_emails rows that are received or processing with an EXPIRED five-minute lease, routes each to one accessible project, creates the ticket and sends the sender a receipt. The Mailgun intake route (POST /inbound-email) persists an email and returns 200 without routing it, so nothing else turns a ledger row into a ticket. At most three attempts per email; past the ceiling the row is terminal processing_failed. Bounds are overridable per environment with INBOUND_EMAIL_SWEEP_LIMIT (default/max 25 rows) and INBOUND_EMAIL_SWEEP_DEADLINE_MS (default 45000). Protected by CRON_SECRET via the x-cron-secret header ONLY — a token query parameter is rejected (secrets do not belong in URLs).

Inbound sweep result

Media type application/json
object
ok
required

False when any row errored or the ledger selection itself failed. A truncated batch is NOT a failure — the next hourly fire takes the rest.

boolean
sweep
required
object
scanned
required

Eligible ledger rows the selection returned.

integer
claimed
required

Rows this sweep took the five-minute lease on.

integer
ticket_created
required
integer
routing_failed
required
integer
processing_failed
required

Rows terminalized because the three-attempt ceiling was passed.

integer
skipped_in_progress
required

Rows another worker holds a LIVE lease on.

integer
skipped_duplicate
required

Rows already terminal.

integer
receipts
required

Receipt outcomes by name (sent, failed, delivery_unknown, skipped, errored). A bad receipt never undoes ticket_created.

object
key
additional properties
integer
errors
required
integer
truncated
required

The batch cap or the internal deadline stopped the sweep with work left over.

boolean
bounds
required
object
limit
required
integer
deadline_ms
required
number

Missing or invalid CRON_SECRET