Error Codes Guide

When an API request fails, Neutron returns a structured error response with a status code, error code, and message.

Error Response Format

{
  "resultStatus": "error",
  "code": "2005",
  "error": "transaction 5e25d2f4-... already in final state usercanceled",
  "errorMetadata": {
    "params": "{\"State\":\"usercanceled\",\"TxnID\":\"5e25d2f4-...\"}"
  }
}

HTTP Status Codes

CodeMeaningCommon Cause
200SuccessRequest completed successfully
400Bad RequestInvalid parameters, missing fields, or business logic error
401UnauthorizedInvalid or expired access token
403ForbiddenInsufficient permissions
404Not FoundResource doesn't exist
429Rate LimitedToo many requests -- implement backoff
500Server ErrorInternal error -- retry after a delay

Common Error Codes

Authentication Errors

CodeMessageResolution
1001Invalid API keyCheck your X-Api-Key header
1002Invalid signatureVerify your HMAC-SHA256 computation
1003Token expiredRe-authenticate to get a new token

Transaction Errors

CodeMessageResolution
2001Insufficient balanceCheck wallet balance before creating
2002Invalid amountAmounts must be positive; BTC amounts are in BTC, not sats
2003Invalid methodCheck supported payment methods
2005Transaction in final stateCannot confirm/cancel a completed or expired transaction
2006Transaction expiredCreate a new transaction
2007Invalid destinationCheck address format

Webhook Errors

CodeMessageResolution
3001Invalid callback URLMust be a valid HTTPS URL
3002Webhook already existsUse update endpoint or delete and recreate

Retry Strategy

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');
}

Common Mistakes

ProblemSolution
Amounts in satoshis instead of BTCUse BTC: 0.00000100 = 100 sats
Setting amount on both sidesSet amtRequested on source OR dest, not both
Missing trailing slash on wallet endpointUse /api/v2/account/{id}/wallet/ with trailing slash
Confirming an expired transactionCreate a new transaction