API Reference
Errors

Error Reference

Complete list of API error codes and how to handle them

Error Response Format

All API errors return a JSON response with the following structure:

{
  "detail": "Error message describing what went wrong",
  "error_code": "specific_error_code",
  "request_id": "req_abc123"
}
FieldTypeDescription
detailstringHuman-readable error message
error_codestringMachine-readable error code
request_idstringUnique request identifier for support

HTTP Status Codes

Status CodeMeaning
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - No permission for this resource
404Not Found - Resource doesn't exist
409Conflict - Duplicate resource (e.g., intent_id)
422Unprocessable Entity - Validation error
429Too Many Requests - Rate limit exceeded
500Internal Server Error - Server-side error
503Service Unavailable - Service temporarily down

Client Errors (4xx)

400 Bad Request

Cause: Invalid request parameters

Example:

{
  "detail": "limit_price is required for limit orders",
  "error_code": "missing_limit_price"
}

Solution: Add missing required fields

# Missing limit_price
intent = TradeIntentRequest(
    order_type=OrderType.LIMIT  # Missing limit_price!
)
 
# Correct
intent = TradeIntentRequest(
    order_type=OrderType.LIMIT,
    limit_price=Decimal("175.00")
)

401 Unauthorized

Cause: Invalid or missing API key

Example:

{
  "detail": "Invalid API key",
  "error_code": "unauthorized"
}

Solution: Check your API key

# Verify API key is valid
client = SnipeRouteClient(
    api_key=os.getenv("SNIPEROUTE_API_KEY")
)

403 Forbidden

Cause: API key doesn't have permission

Example:

{
  "detail": "This API key does not have permission for this resource",
  "error_code": "forbidden"
}

Solution: Use the correct API key type (test vs live)

404 Not Found

Cause: Resource doesn't exist

Example:

{
  "detail": "Trade Intent not found",
  "error_code": "not_found"
}

Solution: Verify the resource ID

try:
    intent = await client.get_intent_by_external_id("trade_001")
except NotFoundError:
    print("Intent not found")

409 Conflict

Cause: Duplicate intent_id

Example:

{
  "detail": "Trade Intent with this intent_id already exists",
  "error_code": "duplicate_intent_id"
}

Solution: Use unique intent_id for each submission

import uuid
 
# Generate unique ID
intent_id = f"trade_{uuid.uuid4()}"

422 Unprocessable Entity

Cause: Validation error

Example:

{
  "detail": [
    {
      "loc": ["body", "quantity"],
      "msg": "ensure this value is greater than 0",
      "type": "value_error.number.not_gt"
    }
  ],
  "error_code": "validation_error"
}

Solution: Fix validation errors

# Invalid quantity
quantity=Decimal("0")  # Must be > 0
 
# Correct
quantity=Decimal("10")

429 Too Many Requests

Cause: Rate limit exceeded

Example:

{
  "detail": "Rate limit exceeded. Retry after 60 seconds.",
  "error_code": "rate_limit_exceeded",
  "retry_after": 60
}

Solution: Implement retry with backoff

import asyncio
from sniperoute.exceptions import RateLimitError
 
async def submit_with_retry(client, intent):
    while True:
        try:
            return await client.create_intent(intent)
        except RateLimitError as e:
            retry_after = e.retry_after or 60
            await asyncio.sleep(retry_after)

Server Errors (5xx)

500 Internal Server Error

Cause: Server-side error

Example:

{
  "detail": "Internal server error",
  "error_code": "internal_server_error",
  "request_id": "req_abc123"
}

Solution: Retry with exponential backoff

import asyncio
 
async def submit_with_backoff(client, intent, max_retries=3):
    for attempt in range(max_retries):
        try:
            return await client.create_intent(intent)
        except SnipeRouteAPIError as e:
            if e.status_code >= 500:
                if attempt == max_retries - 1:
                    raise
                wait_time = 2 ** attempt
                await asyncio.sleep(wait_time)
            else:
                raise

503 Service Unavailable

Cause: Service temporarily unavailable

Example:

{
  "detail": "Service temporarily unavailable",
  "error_code": "service_unavailable"
}

Solution: Retry after a delay

Broker-Specific Errors

Insufficient Funds

{
  "detail": "Broker rejected order: Insufficient buying power",
  "error_code": "broker_error",
  "broker_error_code": "insufficient_funds"
}

Solution: Check account balance

Invalid Symbol

{
  "detail": "Broker rejected order: Symbol not found",
  "error_code": "broker_error",
  "broker_error_code": "invalid_symbol"
}

Solution: Verify symbol is valid for the broker

Market Closed

{
  "detail": "Broker rejected order: Market is closed",
  "error_code": "broker_error",
  "broker_error_code": "market_closed"
}

Solution: Check market hours or use extended_hours: true

Trading Halted

{
  "detail": "Broker rejected order: Trading halted for this symbol",
  "error_code": "broker_error",
  "broker_error_code": "halted"
}

Solution: Wait for trading to resume

Validation Errors

Missing Required Field

{
  "detail": [
    {
      "loc": ["body", "limit_price"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

Invalid Field Type

{
  "detail": [
    {
      "loc": ["body", "quantity"],
      "msg": "value is not a valid decimal",
      "type": "type_error.decimal"
    }
  ]
}

Invalid Enum Value

{
  "detail": [
    {
      "loc": ["body", "side"],
      "msg": "value is not a valid enumeration member; permitted: 'buy', 'sell'",
      "type": "type_error.enum"
    }
  ]
}

Error Handling Best Practices

Catch Specific Exceptions
from sniperoute.exceptions import (
    ValidationError,
    AuthenticationError,
    NotFoundError,
    ConflictError,
    RateLimitError
)
 
try:
    response = await client.create_intent(intent)
except ValidationError as e:
    print(f"Validation error: {e.message}")
except ConflictError as e:
    print(f"Duplicate intent_id: {e.message}")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
Log Request IDs

Request IDs help with debugging and support:

try:
    response = await client.create_intent(intent)
except SnipeRouteAPIError as e:
    logger.error(
        f"API error: {e.message}",
        extra={
            "status_code": e.status_code,
            "error_code": e.error_code,
            "request_id": e.request_id  # Include for support
        }
    )
Implement Retry Logic

Retry transient errors (5xx, rate limits):

async def submit_with_retry(client, intent):
    retryable_codes = [429, 500, 502, 503, 504]
 
    for attempt in range(3):
        try:
            return await client.create_intent(intent)
        except SnipeRouteAPIError as e:
            if e.status_code in retryable_codes:
                wait = 2 ** attempt
                await asyncio.sleep(wait)
            else:
                raise  # Don't retry client errors
Validate Before Submitting

Catch validation errors early:

def validate_intent(intent: TradeIntentRequest):
    if intent.order_type == OrderType.LIMIT and not intent.limit_price:
        raise ValueError("limit_price required for limit orders")
 
    if intent.quantity <= 0:
        raise ValueError("quantity must be > 0")
 
# Validate before API call
validate_intent(intent)
response = await client.create_intent(intent)

Getting Help

If you encounter an error you can't resolve:

  1. Check the error message and error_code
  2. Review this documentation
  3. Check the Guides for common solutions
  4. Contact support@sniperoute.io with the request_id

Next Steps