When an API request fails, Neutron returns a structured error response with a status code, error code, and message.
{
"resultStatus": "error",
"code": "2005",
"error": "transaction 5e25d2f4-... already in final state usercanceled",
"errorMetadata": {
"params": "{\"State\":\"usercanceled\",\"TxnID\":\"5e25d2f4-...\"}"
}
}
| Code | Meaning | Common Cause |
|---|
| 200 | Success | Request completed successfully |
| 400 | Bad Request | Invalid parameters, missing fields, or business logic error |
| 401 | Unauthorized | Invalid or expired access token |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 429 | Rate Limited | Too many requests -- implement backoff |
| 500 | Server Error | Internal error -- retry after a delay |
| Code | Message | Resolution |
|---|
| 1001 | Invalid API key | Check your X-Api-Key header |
| 1002 | Invalid signature | Verify your HMAC-SHA256 computation |
| 1003 | Token expired | Re-authenticate to get a new token |
| Code | Message | Resolution |
|---|
| 2001 | Insufficient balance | Check wallet balance before creating |
| 2002 | Invalid amount | Amounts must be positive; BTC amounts are in BTC, not sats |
| 2003 | Invalid method | Check supported payment methods |
| 2005 | Transaction in final state | Cannot confirm/cancel a completed or expired transaction |
| 2006 | Transaction expired | Create a new transaction |
| 2007 | Invalid destination | Check address format |
| Code | Message | Resolution |
|---|
| 3001 | Invalid callback URL | Must be a valid HTTPS URL |
| 3002 | Webhook already exists | Use update endpoint or delete and recreate |
For 5xx errors and 429 rate limits, implement exponential backoff:
async function apiCall(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (err) {
if (err.status >= 500 || err.status === 429) {
await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
continue;
}
throw err;
}
}
throw new Error('Max retries exceeded');
}
| Problem | Solution |
|---|
| Amounts in satoshis instead of BTC | Use BTC: 0.00000100 = 100 sats |
| Setting amount on both sides | Set amtRequested on source OR dest, not both |
| Missing trailing slash on wallet endpoint | Use /api/v2/account/{id}/wallet/ with trailing slash |
| Confirming an expired transaction | Create a new transaction |