Request Tracing & Rescue
Every request to EDITH is tagged with a trace ID that follows it through every internal hop — the API, background queues, scheduled jobs, and the database. You can supply your own trace ID so a single identifier spans both your platform and ours, and you (or our support team) can replay the complete flow of any request later.
Overview
A trace ID is a single value that identifies one request end-to-end. EDITH attaches it to every log line it writes while handling your request, across:
Your platform → EDITH API → send queue → scheduled jobs → database → webhooks
│ │
└──────────────────────── one trace ID the whole way ─────────────────────────┘
This is a continuity model: the same ID is reused across every hop rather than minted fresh at each step, so one search reconstructs the entire journey.
There are two things you can do with it:
- Send your own trace ID — so your logs and ours share one identifier (cross-platform referencing).
- Trace the complete flow — look up everything that happened for a request, even when a
ref_idis missing or an expected event never arrived.
1. Send your own trace ID
If you already trace requests inside your own systems, send your trace ID to EDITH and we adopt it verbatim. The same ID then appears in our logs, so you can line up your records against ours without any translation step.
The trace headers
You can supply your trace ID with either traceparent or X-Trace-Id — both are first-class. Use whichever matches your stack:
| Header | Use it when | Behaviour |
|---|---|---|
traceparent | Your services speak W3C Trace Context | We extract the 32-character trace-id and reuse it. Echoed back as both X-Trace-Id and traceparent. |
X-Trace-Id | You have your own request-ID scheme | We adopt the value verbatim and reuse it. Echoed back as X-Trace-Id. |
Cf-Ray | (automatic) You're behind Cloudflare and sent neither header above | We adopt Cloudflare's ray ID (e.g. a014d142dff87fed-IAD) verbatim. |
If you send both traceparent and X-Trace-Id, the traceparent trace-id wins. If you send none, EDITH generates a fresh 32-character hex trace ID for the request.
The traceparent format
traceparent is the W3C Trace Context standard header:
00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
│ │ │ │
│ │ │ └─ flags (2 hex)
│ │ └─ parent span-id (16 hex)
│ └─ trace-id (32 hex) ← this is what we keep
└─ version (2 hex)
EDITH keeps the trace-id (the second field). A traceparent is only accepted when every field is the right length and hexadecimal, and the trace-id is not all zeros — otherwise it's ignored and we fall back to the next header.
How your request's trace ID is chosen
1. valid `traceparent`? → use its 32-hex trace-id
2. else `X-Trace-Id`? → use it verbatim
3. else `Cf-Ray`? → use it verbatim
4. otherwise → generate a new 32-hex trace ID
What EDITH returns
Every response carries the trace ID back to you:
| Response header | When |
|---|---|
X-Trace-Id | Always — echoes the trace ID used for the request. |
traceparent | Only when the trace ID is a 32-hex value (e.g. you sent a traceparent, or we generated one). A legacy X-Trace-Id or Cf-Ray value is not re-emitted as a traceparent. |
Capture these on your side and store them with your own request records.
Example
Send your own W3C trace context:
curl -X POST https://api.sparrowmailer.com/v1/email/send \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" \
-H "Content-Type: application/json" \
-d '{ "...": "..." }'
The response echoes the same trace ID:
HTTP/1.1 200 OK
X-Trace-Id: 4bf92f3577b34da6a3ce929d0e0e4736
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-9a2f1c7b6d4e8a01-01
Or send your own ID with X-Trace-Id — it's adopted verbatim and echoed back:
curl -i -X POST https://api.sparrowmailer.com/v1/email/send \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Trace-Id: order-12345-attempt-2" \
-H "Content-Type: application/json" \
-d '{ "...": "..." }'
X-Trace-Id: order-12345-attempt-2
Send nothing, and EDITH generates one for you — still returned on X-Trace-Id:
curl -i -X POST https://api.sparrowmailer.com/v1/email/send \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "...": "..." }'
X-Trace-Id: 1f9d6c2a4b7e4f0a8c3d5e6f7a8b9c0d
Best practices
- Log the
X-Trace-Idfrom every EDITH response next to your own request record. This is the single value that lets anyone — you or our support — reconstruct what happened. - Send your own trace ID on every request —
traceparentif your stack speaks W3C Trace Context, orX-Trace-Idif you have your own ID scheme. Either way, one trace ID spans your service and EDITH, so a single ID search works across both platforms. - The trace ID is observability-only. We accept it verbatim and never use it for auth or access decisions, so it's safe to set from your edge, gateway, or client.
2. Trace the complete flow (Quick Rescue)
When a ref_id is missing, a webhook never arrived, or an email's status is unclear, the trace ID lets you pull up everything EDITH did for that request — across the API, the send queue, scheduled jobs, and the database — in one search.
On your side
Search your own logs for the X-Trace-Id you captured from the response. Because we reuse the same ID, that value also identifies the request inside EDITH — so your timeline and ours line up directly.
On our side (support lookup)
EDITH ships structured logs to Loki. Every line includes a traceId field, so a trace ID reconstructs the full flow.
Support / on-call lookup. In Loki, scope to the
edithnamespace and filter by the trace ID:{namespace="edith"} |= "4bf92f3577b34da6a3ce929d0e0e4736"Or match the field precisely after JSON parsing:
{namespace="edith"} | json | traceId="4bf92f3577b34da6a3ce929d0e0e4736"Logs are also labelled
application="edith-application"andenvironment=<env>, which you can add to narrow the scope.
What the logs tell you
Each log line for the request carries:
| Field | Meaning |
|---|---|
traceId | The trace ID — the same value across every hop. |
origin | Where the trace entered EDITH (request for HTTP, plus queue and scheduled-job origins for async work). |
parentTraceId | Present on async children, linking background work back to the request that started it. |
Reading the lines in time order replays the journey: API request → queued for sending → delivery attempt → status update → webhook dispatch. When a ref_id is unavailable, this is the reliable way to find the email and explain what happened.
Requesting a rescue
If you can't resolve an issue from your own logs, open a support request and include the X-Trace-Id from the relevant EDITH response. That one value is enough for us to pull the complete end-to-end flow.
Related
- Email Logs — look up emails by
ref_id; use the trace ID whenref_idis missing. - Webhooks — when an event doesn't arrive, trace the request to see what EDITH did.
- W3C Trace Context — the
traceparentspecification.