The Neutron API uses standard HTTP status codes and returns consistent JSON error responses to help you quickly identify and resolve issues.
| Code | Category | Description |
|---|
| 200 | ✅ Success | Request completed successfully |
| 400 | ❌ Bad Request | The request was malformed or missing required fields |
| 401 | 🔒 Unauthorized | Authentication failed — invalid API key, signature, or expired token |
| 403 | 🚫 Forbidden | Valid credentials but insufficient permissions (e.g., accessing another account's resources) |
| 404 | ❓ Not Found | The requested resource doesn't exist (transaction, webhook, account, etc.) |
| 429 | ⏳ Rate Limited | Too many requests — see Rate Limiting |
| 500 | 💥 Server Error | Something went wrong on our end — retry with exponential backoff |
All error responses return JSON with an error field, and optionally a message field with more detail:
{
"error": "unauthorized",
"message": "invalid token or token expired"
}
Some endpoints return a simpler format:
{
"error": "invalid api signature"
}
| Error | HTTP Code | Cause | Solution |
|---|
invalid API key or signature | 401 | Missing or incorrect X-Api-Key or X-Api-Signature headers | Verify your API key and regenerate the HMAC-SHA256 signature — see Signature Generation |
invalid api signature | 401 | The signature doesn't match the expected value | Ensure you're signing the string {apiKey}&payload={payload} with your API secret using HMAC-SHA256 |
invalid token or token expired | 401 | The JWT access token has expired or is malformed | Request a new token via POST /api/v2/authentication/token-signature. Tokens have a limited lifespan — check the expiredAt field |
| Error | HTTP Code | Cause | Solution |
|---|
failed to get account | 400 | Invalid account ID format | Verify the account ID (format: ne01-xxxx...) |
you are not authorized to view this account | 401 | Trying to access an account you don't own | You can only access your own account or subaccounts where you're the parent |
Permission denied | 403 | Subaccount accessing parent resources or vice versa | Ensure the token matches the account being accessed |
| Error | HTTP Code | Cause | Solution |
|---|
unauthorized | 401 | Missing or invalid Bearer token | Include a valid JWT in the Authorization: Bearer {token} header |
not found | 404 | Transaction ID doesn't exist | Verify the transaction ID from the create response |
bad request | 400 | Invalid transaction parameters | Check required fields: sourceReq and destReq with valid ccy, method, and reqDetails |
| Error | HTTP Code | Cause | Solution |
|---|
unauthorized | 401 | Missing or invalid authentication | Include a valid Bearer token |
not found | 404 | Webhook ID doesn't exist | List your webhooks via GET /api/v2/webhook to find valid IDs |
- Always check the HTTP status code first — it tells you the error category
- Parse the JSON
error and message fields for specifics
- Implement token refresh logic — tokens expire, so catch 401s and re-authenticate automatically
- Use idempotent retries for 5xx errors — server errors are usually transient; retry with exponential backoff
- Don't retry 4xx errors without fixing the request — these indicate a problem with your input
- Log error responses — include the full response body in your logs for debugging
- Set up webhooks to track transaction failures asynchronously instead of polling