API Reference
Trade Intents
Get by External ID

Get Trade Intent by External ID

Retrieve a Trade Intent using your intent_id

API: GET https://api.sniperoute.io/api/v1/intents/by-external-id/{intent_id}

Request

Path Parameters

ParameterTypeRequiredDescription
intent_idstringYesYour external intent identifier

Headers

HeaderValueRequired
AuthorizationBearer your_api_keyYes

Response

Success (200 OK)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "intent_id": "trade_001",
  "symbol": "AAPL",
  "side": "buy",
  "quantity": 10,
  "order_type": "market",
  "status": "filled",
  "broker_id": "alpaca_abc123",
  "orders": [
    {
      "id": "660e8400-e29b-41d4-a716-446655440000",
      "broker_order_id": "order_123",
      "status": "filled",
      "fills": [
        {
          "quantity": 10,
          "price": 175.50,
          "filled_at": "2025-11-30T10:30:00Z"
        }
      ],
      "created_at": "2025-11-30T10:29:59Z",
      "updated_at": "2025-11-30T10:30:00Z"
    }
  ],
  "created_at": "2025-11-30T10:29:59Z",
  "updated_at": "2025-11-30T10:30:00Z"
}

Error (4xx/5xx)

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

Examples

curl https://api.sniperoute.io/api/v1/intents/by-external-id/trade_001 \
  -H "Authorization: Bearer sk_live_abc123..."

Response Fields

FieldTypeDescription
idstring (UUID)Internal Trade Intent UUID
intent_idstringYour external intent identifier
symbolstringTrading symbol
sidestring"buy" or "sell"
quantitynumberNumber of shares/units
order_typestring"market", "limit", "stop", or "stop_limit"
limit_pricenumber | nullLimit price (if applicable)
stop_pricenumber | nullStop price (if applicable)
time_in_forcestring"day", "gtc", "ioc", or "fok"
extended_hoursbooleanExtended hours trading enabled
statusstringSee Status Values
broker_idstringConnected broker account ID
ordersarrayList of broker orders
created_atstring (ISO 8601)Creation timestamp
updated_atstring (ISO 8601)Last update timestamp

Status Values

StatusDescription
pendingOrder submitted to broker, awaiting execution
filledOrder fully executed
partially_filledOrder partially executed
canceledOrder canceled before full execution
rejectedBroker rejected the order
failedRouting or validation failed

Error Codes

Status CodeError CodeDescription
401unauthorizedInvalid or missing API key
404not_foundTrade Intent with this intent_id not found
500internal_server_errorServer error

Why Use This Endpoint?

This endpoint is more convenient than /intents/{id} because:

  • You don't need to track the internal UUID
  • You can use your own intent_id directly
  • It's the same identifier you used when creating the intent

Best Practice: Use this endpoint (/by-external-id/{intent_id}) for querying Trade Intents in your application.

Use Cases

Check Order Immediately After Creation

import asyncio
from sniperoute import SnipeRouteClient
from sniperoute.models import TradeIntentRequest, OrderSide, OrderType
from decimal import Decimal
 
async def create_and_check():
    client = SnipeRouteClient()
 
    # Create intent
    intent = TradeIntentRequest(
        intent_id="trade_001",
        symbol="AAPL",
        side=OrderSide.BUY,
        quantity=Decimal("10"),
        order_type=OrderType.MARKET,
        broker_id="alpaca_abc123"
    )
 
    response = await client.create_intent(intent)
    print(f"Created: {response.intent_id}")
 
    # Check status using same intent_id
    status = await client.get_intent_by_external_id("trade_001")
    print(f"Status: {status.status}")
 
asyncio.run(create_and_check())

Wait for Fill

import asyncio
 
async def wait_for_fill(client, intent_id, timeout=60):
    """Poll until order fills or times out."""
    start_time = asyncio.get_event_loop().time()
 
    while True:
        intent = await client.get_intent_by_external_id(intent_id)
 
        if intent.status == "filled":
            print("Order filled!")
            return intent
 
        elif intent.status == "rejected":
            print("Order rejected")
            return intent
 
        elif asyncio.get_event_loop().time() - start_time > timeout:
            raise TimeoutError("Order did not fill within timeout")
 
        await asyncio.sleep(1)  # Poll every second
 
# Usage
filled_intent = await wait_for_fill(client, "trade_001")
⚠️

Polling vs Webhooks: While polling works, webhooks are more efficient for real-time updates.

Track Multiple Intents

async def track_intents(client, intent_ids):
    """Check status of multiple intents."""
    results = {}
 
    for intent_id in intent_ids:
        try:
            intent = await client.get_intent_by_external_id(intent_id)
            results[intent_id] = intent.status
        except Exception as e:
            results[intent_id] = f"Error: {e}"
 
    return results
 
# Usage
status_map = await track_intents(
    client,
    ["trade_001", "trade_002", "trade_003"]
)
 
for intent_id, status in status_map.items():
    print(f"{intent_id}: {status}")

Get Fill Details

async def get_fill_details(client, intent_id):
    """Get detailed fill information."""
    intent = await client.get_intent_by_external_id(intent_id)
 
    if intent.status != "filled":
        print(f"Order not filled yet. Status: {intent.status}")
        return
 
    total_quantity = 0
    total_value = 0.0
 
    for order in intent.orders:
        for fill in order.fills:
            total_quantity += fill.quantity
            total_value += fill.quantity * fill.price
 
            print(f"Fill: {fill.quantity} @ ${fill.price} at {fill.filled_at}")
 
    avg_price = total_value / total_quantity if total_quantity > 0 else 0
    print(f"\nTotal: {total_quantity} shares at avg price ${avg_price:.2f}")
 
# Usage
await get_fill_details(client, "trade_001")

Next Steps