> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blujay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Debugging

> Trace a request, find out why a message didn't arrive, and fix the most common problems.

## Trace a request

Every response carries a trace ID in the `X-Trace-ID` header, and as `trace_id` in JSON bodies. Send your own `X-Request-ID` header too, and Blujay echoes it as `client_request_id` in error responses and most success responses (not on send responses; see [Making requests](/making-requests.md#tracing-requests)). Log both.

```bash theme={null}
curl -i https://api.blujay.io/v1/me \
  -H "Authorization: Bearer blu_your_api_key" \
  -H "X-Request-ID: my-job-1042"
```

```http theme={null}
HTTP/2 200
x-trace-id: trc_9d1f0a7c2b4e
ratelimit-limit: 600
ratelimit-remaining: 599
ratelimit-reset: 42
```

Webhook events for a message you sent through the API carry the `trace_id` of the request that sent it, so you can match a send to its delivery updates.

When you contact [support@blujay.io](mailto:support@blujay.io), include the trace ID, your request ID, the endpoint and the time. See [Support](/support.md).

## Follow one message

1. Read it: `GET /v1/messages/{message_id}`. Check `status` and `service`. A failed message has a `failure_code` only for a few causes you can act on; the full reason is in the `message.failed` webhook as `failure.code`. See [Track a message](/messaging/lifecycle.md#failures).
2. Find its events. Each webhook event you received for the message carries its `message_id` and `event_id`. With an `event_id`, list every delivery attempt: `GET /v1/webhook-subscriptions/{subscription_id}/deliveries?event_id=evt_abc123`. There is no lookup from a message to its events, so if you received nothing, list the subscription's recent deliveries and look for the `message_id`. See [Delivery and retries](/webhooks/delivery.md).
3. If your endpoint missed an event, fix it and [replay the event](/webhooks/delivery.md#replay-an-event).

## Common problems

| Symptom | Likely cause | Fix |
| - | - | - |
| `401` on every call | Missing `Bearer`, a typo in the key, or a revoked key | Check the header is `Authorization: Bearer blu_…`. See [`UNAUTHORIZED`](/errors/unauthorized). |
| `400` [`FIRST_MESSAGE_LINK_NOT_ALLOWED`](/errors/first-message-link-not-allowed) | A link, or text that looks like a web address, in a first message | Send the link as a follow-up after the person replies. See [Sending rules](/messaging/sending-rules.md). |
| `400` [`PRE_REPLY_CONTENT_BLOCKED`](/errors/pre-reply-content-blocked) or [`PRE_REPLY_LENGTH_EXCEEDED`](/errors/pre-reply-length-exceeded) | A link, photo, file or contact card, or a text over 300 characters, before the contact replied | Send a short text and wait for the reply. Not retryable. See [Sending rules](/messaging/sending-rules.md). |
| `400` [`PRE_REPLY_LIMIT_REACHED`](/errors/pre-reply-limit-reached) | 6 texts in a row with no response from the contact | Wait for them to respond. `pre_reply_override: true` sends one more, once. |
| `403` [`CONTACT_NOT_VERIFIED`](/errors/contact-not-verified) | Free Plan: the person hasn't texted your number first and been verified in the app | Verify them in the app, or move to a Dedicated number. See [Plans](/plans.md). |
| `403` [`CONTACT_MUST_TEXT_FIRST`](/errors/contact-must-text-first) | AI Agent: the person hasn't texted this number yet | Wait for them to text first. See [Plans](/plans.md). |
| `403` [`RECIPIENT_SUPPRESSED`](/errors/recipient-suppressed) | The person opted out | Don't retry. See [Opt-outs](/opt-outs.md). |
| `429` [`RATE_LIMIT_EXCEEDED`](/errors/rate-limit-exceeded) on sends | A sending limit on the number | Wait for `Retry-After`, check `limits` on [`GET /v1/phone-numbers`](/phone-numbers). |
| `404` [`NOT_FOUND`](/errors/not-found) for an ID you received a moment ago | The ID belongs to another workspace, or the wrong key is in use | Check `GET /v1/me` shows the workspace you expect. |
| `422` [`FROM_NUMBER_REQUIRED`](/errors/from-number-required) | Blujay couldn't pick a number for a direct chat | Pass `from` explicitly. A group chat always needs `from`. |
| Message stuck at `sent` | SMS never reports delivery; iMessage and RCS report it when the phone receives it | Treat `sent` as final for SMS. See [Track a message](/messaging/lifecycle.md). |
| `message.failed` with `failure.code: recipient_unavailable` | You required iMessage and the person can't receive it | Send with Auto, or check first with [iMessage, RCS or SMS](/messaging/choosing-a-service.md). |
| No webhooks arriving | Subscription disabled, wrong events, a filtered phone number, or your endpoint returning non-`2xx` | Check the subscription and its deliveries list. |
| Every webhook signature fails | Wrong secret, secret not base64-decoded, or a parsed body | See [Verify signatures](/webhooks/verify-signatures.md#troubleshooting). |
| The same event arrives twice | Delivery is at least once | Deduplicate by `event_id`. |
| `409` [`IDEMPOTENCY_REQUEST_MISMATCH`](/errors/idempotency-request-mismatch) | The same `Idempotency-Key` reused for a different request, for example on another chat | Make keys unique per business event. See [Idempotency](/idempotency.md#route-families). |

## Next steps

> **[Errors](/errors.md)**
>
> Every error code and how to fix it.

> **[FAQ](/faq.md)**
>
> Quick answers to common questions.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.