API Reference
Webhooks
Overview

Webhooks Overview

Receive real-time Trade Intent status updates via webhooks

What Are Webhooks?

Webhooks are HTTP POST requests that SnipeRoute sends to your server whenever a Trade Intent's status changes. Instead of polling the API for updates, webhooks deliver events in real-time.

Webhooks are the recommended way to track Trade Intent status. They're more efficient than polling and provide instant updates.

How Webhooks Work

1

Configure Webhook URL

Set your webhook endpoint URL in the SnipeRoute dashboard (Settings → Webhooks).

2

Trade Intent Status Changes

When a Trade Intent's status changes (e.g., from pending to filled), SnipeRoute generates a webhook event.

3

SnipeRoute Sends HTTP POST

SnipeRoute sends an HTTP POST request to your webhook URL with the event data.

4

Your Server Processes Event

Your server receives the webhook, verifies the signature, and processes the event.

5

Respond with 200 OK

Your server responds with 200 OK to acknowledge receipt.

Webhook Events

Event TypeDescription
intent.createdTrade Intent successfully created
intent.pendingOrder submitted to broker
intent.filledOrder fully executed
intent.partially_filledOrder partially executed
intent.canceledOrder canceled
intent.rejectedBroker rejected the order
intent.failedRouting or validation failed
Event Payloads

View complete event payload examples

Webhook Payload Structure

All webhook events have the same structure:

{
  "type": "intent.filled",
  "id": "evt_abc123",
  "created_at": "2025-11-30T10:30:00Z",
  "data": {
    "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": [...]
  }
}
FieldTypeDescription
typestringEvent type (e.g., "intent.filled")
idstringUnique event ID (for idempotency)
created_atstringEvent timestamp (ISO 8601)
dataobjectTrade Intent object

Setting Up Webhooks

1. Create Webhook Endpoint

Create an HTTPS endpoint on your server:

from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib
 
app = FastAPI()
 
# Hex-encoded secret from webhook creation
WEBHOOK_SECRET = "your_webhook_secret_from_dashboard"
 
@app.post("/webhooks/sniperoute")
async def handle_webhook(request: Request):
    # Get headers
    signature_header = request.headers.get("sr-signature")
    timestamp = request.headers.get("sr-timestamp")
    event_id = request.headers.get("sr-event-id")
 
    body = await request.body()
 
    # Verify signature (Stripe-style with timestamp)
    if not signature_header or not signature_header.startswith("v1="):
        raise HTTPException(status_code=401, detail="Invalid signature format")
 
    signature = signature_header[3:]  # Remove "v1=" prefix
    message = f"{timestamp}.{body.decode()}"
 
    expected_signature = hmac.new(
        bytes.fromhex(WEBHOOK_SECRET),  # Secret is hex-encoded
        message.encode(),
        hashlib.sha256
    ).hexdigest()
 
    if not hmac.compare_digest(signature, expected_signature):
        raise HTTPException(status_code=401, detail="Invalid signature")
 
    # Parse event
    event = await request.json()
 
    # Handle event
    if event["type"] == "intent.filled":
        print(f"Order filled: {event['data']['intent_id']}")
 
    return {"status": "received"}

2. Configure in Dashboard

1

Go to Settings → Webhooks

2

Add Webhook

Click Add Webhook and enter your HTTPS endpoint URL

3

Select Events

Choose which events to receive (or "All events")

4

Copy Secret

Save the webhook secret for signature verification

5

Test

Click Send Test Event to verify your endpoint works

Security

Signature Verification

⚠️

Always verify webhook signatures to ensure requests come from SnipeRoute and haven't been tampered with.

SnipeRoute signs each webhook with HMAC-SHA256 using your webhook secret (Stripe-style):

Headers sent with each webhook:

sr-signature: v1=<hex-encoded-signature>
sr-timestamp: <unix-timestamp>
sr-event-id: <unique-event-id>

Signed message format: {timestamp}.{payload}

Verification:

import hmac
import hashlib
 
def verify_signature(payload: bytes, timestamp: str, signature_header: str, secret: str) -> bool:
    # Extract signature from header (format: "v1=...")
    if not signature_header.startswith("v1="):
        return False
    signature = signature_header[3:]
 
    # Reconstruct signed message
    message = f"{timestamp}.{payload.decode()}"
 
    # Secret is hex-encoded, decode it first
    expected = hmac.new(
        bytes.fromhex(secret),
        message.encode(),
        hashlib.sha256
    ).hexdigest()
 
    return hmac.compare_digest(signature, expected)
Signature Verification Guide

Complete signature verification examples

Webhook Retries

If your endpoint doesn't respond with 2xx, SnipeRoute will retry:

AttemptDelay
1st retry10 seconds
2nd retry30 seconds
3rd retry2 minutes
4th retry10 minutes
5th retry30 minutes

After 5 failed attempts, the webhook is moved to the dead letter queue and logged in your dashboard.

Best Practices

Respond Quickly

Return 200 OK within 5 seconds. Process events asynchronously if needed.

@app.post("/webhooks/sniperoute")
async def handle_webhook(request: Request):
    # Verify signature
    # Queue event for async processing
    await event_queue.put(await request.json())
    return {"status": "received"}  # Respond immediately
Handle Duplicates

Webhooks may be delivered multiple times. Use event.id for idempotency.

event = await request.json()
event_id = event["id"]
 
if await db.event_already_processed(event_id):
    return {"status": "duplicate"}
 
await process_event(event)
await db.mark_event_processed(event_id)
Use HTTPS

Webhook URLs must use HTTPS (not HTTP) for security.

Monitor Failures

Check the webhook logs in your dashboard to identify delivery issues.

Testing Webhooks Locally

Use ngrok to test webhooks on your local development machine:

# Install ngrok
brew install ngrok
 
# Start your local server
python app.py  # Running on localhost:8000
 
# Expose local server
ngrok http 8000
 
# Use ngrok URL in webhook settings
# https://abc123.ngrok.io/webhooks/sniperoute

Webhook Logs

View webhook delivery logs in your dashboard:

  • Settings → Webhooks → Logs

Logs include:

  • Event type
  • Delivery status (success/failed)
  • Response code
  • Retry attempts
  • Timestamp

Next Steps