# Errors

> Identify failed requests and choose the right recovery action.

## Error response

Errors include an `error` category, a readable `message`, and a `correlationId`. Some errors also include a machine-readable `code`; validation errors may include `details`.

```json
{
  "error": "invalid_argument",
  "message": "Request doesn't match the schema",
  "correlationId": "request-example"
}
```

Keep the correlation ID when investigating a failed request. Avoid logging your API key or message content.

## Recovery

| Response | What to do |
| --- | --- |
| 400 | Correct missing or invalid fields before trying again. |
| 401 | Check the API key and bearer header. |
| 403 | Check the key's permissions and sending-domain scope. |
| 404 | Check that the resource exists in the key's project. |
| 409 | Resolve the resource conflict before retrying. |
| 422 | The resource is not in a state that allows the request, such as a WhatsApp template that is not approved yet. Check its `code`. |
| 429 | Wait for `Retry-After` when supplied. |
| 5xx | Retry transient failures with backoff; preserve send idempotency keys. |

Inspect both the HTTP status and the `error` or `code`. A subscription quota failure requires an allowance change, not a rapid retry loop.

## Node.js SDK

The SDK returns API responses as `{ data, error }`. Local input validation can throw, so handle both paths.

```typescript
try {
  const { data, error } = await nexiom.emails.send(
    {
      from: 'hello@mail.example.com',
      to: 'reader@example.com',
      subject: 'Welcome',
      text: 'Thanks for joining us.',
    },
    { idempotencyKey: 'welcome-user-123' },
  );

  if (error) {
    console.error(error.message);
  } else {
    console.log(data.messageId);
  }
} catch (error) {
  console.error('Check your request and client configuration.', error);
}
```

---

Source: https://connect.nxiom.com/docs/api/errors
