Debugging
Using trace IDs for request tracing and troubleshooting.
Every API response and webhook payload includes a trace ID for end-to-end debugging. This guide covers how to use trace IDs and troubleshoot common issues. See Error Codes for the complete error reference.
Trace IDs
Section titled “Trace IDs”Every API response includes a trace ID in the X-Trace-ID response header, following the W3C Trace Context standard. Error responses and webhook payloads also include trace_id in the response body.
# The response includes the trace ID header< X-Trace-ID: 2eff5df5c6f688733c007523c4d61cd9{ "success": false, "error": { "status": 400, "code": 1001, "message": "Missing required field" }, "trace_id": "2eff5df5c6f688733c007523c4d61cd9"}W3C Trace Context
Section titled “W3C Trace Context”The trace ID is the 32-character hex trace-id segment of the W3C traceparent header. Its structure is:
traceparent: 00-<trace-id>-<parent-id>-<flags> │ │ │ └─ 2-hex flags (e.g. 01 for sampled) │ │ └─ 16-hex span/parent ID │ └─ 32-hex trace ID (returned as X-Trace-ID) └─ version (currently 00)The trace_id field in error bodies and webhook envelopes is the same 32-hex value. You can feed it straight into any OpenTelemetry-compatible tracing backend (Datadog, Honeycomb, Jaeger, Grafana Tempo, etc.) to join your spans with Linq’s internal spans — ask support to enable cross-account trace sharing if you need to inspect Linq-side spans.
Inbound headers are ignored. Per W3C security guidance for public APIs, the Linq API generates a fresh trace context for every request. Any client-supplied traceparent or tracestate headers are discarded and replaced. This prevents forged trace IDs and trace-ID collision across tenants.
Request correlation
Section titled “Request correlation”To correlate an API request with your own records:
- Store the returned
X-Trace-IDand map it to your internal request/job ID - Log both together so you can cross-reference during support tickets
- Capture it on webhook receipt too — the same trace ID flows through downstream
message.sent/message.deliveredevents
const response = await client.chats.create({ from: '+12223334444', to: ['+15556667777'], message: { parts: [{ type: 'text', value: 'Hello!' }] },});
// Log the trace ID with your internal ID for correlationconsole.log(`Internal ID: ${internalId}, Trace ID: ${response._response.headers.get('x-trace-id')}`);response = client.chats.with_raw_response.create( from_="+12223334444", to=["+15556667777"], message={"parts": [{"type": "text", "value": "Hello!"}]},)
print(f"Internal ID: {internal_id}, Trace ID: {response.headers['x-trace-id']}")Async processing and webhook correlation
Section titled “Async processing and webhook correlation”Many operations are processed asynchronously after the API responds. The initial HTTP response tells you the request was accepted; the final outcome arrives via webhooks.
The trace_id threads the full request lifecycle:
- You call
POST /v3/chats/{id}/messages→ response body andX-Trace-IDheader carrytrace_id: abc123... - The message is queued and dispatched to Apple/carrier networks
- You receive a
message.sentwebhook whose envelopetrace_idmatchesabc123... - On delivery, a
message.deliveredwebhook — sametrace_id - On read,
message.read— sametrace_id - On failure, a
message.failedwebhook — sametrace_idplus the finalcode/message
Recommended pattern: store the trace_id alongside the message in your database at step 1, then key webhook-handler updates off trace_id (or event_id for deduplication) so late-arriving events always land on the correct record.
Note: Webhook envelope
trace_idis always present. The innerdataobject may also echomessage_id,chat_id, andevent_idfor more granular joins. Useevent_idfor deduplication,trace_idfor end-to-end correlation.
Common issues
Section titled “Common issues”| Symptom | Likely cause | Solution |
|---|---|---|
401 Unauthorized | Missing or invalid bearer token | Check Authorization: Bearer header — see Authentication |
400 E.164 format | Phone number format wrong | Use + prefix with country code: +12223334444 — see error 1002 |
403 Phone number denied | Phone not assigned to your account | Verify phone assignment with your Linq representative |
409 Chat still creating | Duplicate concurrent create requests | Wait and retry, or use idempotency keys |
429 Rate limit | Per-pair cap, sandbox daily cap, or capability check limit | Wait the Retry-After interval, then check for retry loops or missing caching — see Rate Limits |
5xx Infrastructure | Transient server error | Retry with exponential backoff — see 3xxx server errors |
| Webhook not received | Endpoint unreachable or returning non-2xx | Check endpoint URL, SSL cert, and firewall rules — see Webhooks |
No message.delivered / message.read after send | Message fell back to SMS/MMS | SMS and MMS don’t support delivery or read receipts — see Protocol capabilities |
| Duplicate webhooks | At-least-once delivery | Deduplicate using event_id — see Webhook delivery |
Reporting issues
Section titled “Reporting issues”When contacting Linq support, always include:
- The trace ID from the API response
- The timestamp of the request
- The endpoint you called
- The response you received (status code and body)
This allows the support team to look up the exact request in their systems.