EVSignals API
Scan for live +EV signals, pull historical odds, and run backtests across 500+ connected sources through one API.
Start Here
Set your API key, make one filtered signals request, then branch into markets, webhooks, or backtests.
Best First Page
Use quickstart if you want the fastest successful first request instead of a full reference sweep.
Use This Page For
Endpoint paths, example payloads, auth patterns, error handling, and the main API surface in one place.
New here?
Start with account setup, installation, and your first request.
Open QuickstartNeed working code?
Jump straight to copy-paste recipes for common requests and integrations.
View ExamplesBuilding in Python or Node?
Use the SDK guides if you want type-safe clients and retries built in.
Read SDK GuideJust need the main endpoint?
Jump directly to the signals endpoints used in most integrations.
Go To SignalsReal-time Signals
Get notifications when new +EV signals are detected across connected venues.
Historical Data
Access 15+ years of historical market data for backtesting and analysis.
Backtesting Engine
Test your strategies against historical data before deploying capital.
Base URL
https://api.evsignals.com/v1 pip install evsignals import evsignals
client = evsignals.Client(api_key="evs_test_your_api_key_here") signals = client.signals.list(min_ev=0.02)
print(signals.data) Authentication
The EVSignals API uses API keys to authenticate requests. You can view and manage your API keys in your dashboard. Your API keys carry many privileges, so be sure to keep them secure.
API Key Types
-
evs_live_Production keys for live data and trading -
evs_test_Test keys for development and testing
Security Notice
Never expose your API keys in client-side code or public repositories. Use environment variables or a secrets manager.
import evsignals
# Initialize with your API key
client = evsignals.Client(
api_key="evs_test_your_api_key_here"
)
# All subsequent requests are authenticated
signals = client.signals.list() Signals
Signals represent +EV opportunities detected by our algorithms. Each signal includes the expected value, fair probability, current market price, and metadata about the underlying market.
Endpoints
/v1/signals List all signals /v1/signals/{id} Retrieve a signal /v1/signals/scan Scan for opportunities Parameters
min_ev float | Minimum expected value (0.01 = 1%) |
markets array | Filter by market platforms |
status string | Signal status (active, resolved, expired) |
limit integer | Number of results (default: 20, max: 100) |
starting_after string | Cursor for forward pagination (signal ID) |
ending_before string | Cursor for backward pagination (signal ID) |
Pagination
List endpoints use cursor-based pagination. Use starting_after with the last object's ID to fetch the next page.
has_more Boolean indicating if more results exist total_count Total number of matching results # List all +EV signals
signals = client.signals.list(
min_ev=0.02, # Minimum 2% edge
markets=["kalshi", "polymarket"],
status="active",
limit=100
)
for signal in signals.data:
print(f"{signal.market}: {signal.ev_percent}% EV")
print(f" Contract: {signal.contract_name}")
print(f" Fair Value: {signal.fair_value}")
print(f" Current Price: {signal.current_price}") {
"object": "list",
"data": [
{
"id": "sig_abc123",
"object": "signal",
"market": "kalshi",
"contract_name": "Will BTC hit $150k by Dec 2026?",
"ev_percent": 4.2,
"fair_value": 0.65,
"current_price": 0.58,
"confidence": 0.85,
"created_at": "2026-01-15T10:30:00Z",
"expires_at": "2026-12-31T23:59:59Z"
}
],
"has_more": true
} # Scan for new +EV opportunities
scan_result = client.signals.scan(
markets=["kalshi", "polymarket", "predictit"],
categories=["politics", "economics", "sports"],
min_ev=0.015,
max_odds=10.0,
min_liquidity=1000
)
print(f"Found {len(scan_result.opportunities)} opportunities")
for opp in scan_result.opportunities:
print(f" {opp.contract}: {opp.ev_percent:.2f}% edge") {
"object": "scan_result",
"opportunities": [
{
"id": "opp_def456",
"contract": "Chiefs ML vs Ravens",
"market": "kalshi",
"ev_percent": 3.85,
"fair_value": 0.52,
"current_price": 0.47,
"max_odds": 2.13,
"liquidity": 15000,
"expires_at": "2026-02-10T01:00:00Z"
}
],
"total_scanned": 1250,
"scan_duration_ms": 340
} Markets
Markets represent individual prediction market contracts. Access real-time pricing, historical odds data, volume statistics, and market metadata across Kalshi, Polymarket, PredictIt, and more.
Endpoints
/v1/markets List all markets /v1/markets/{id} Retrieve a market /v1/markets/{id}/odds Get odds history Supported Platforms
# Get detailed market information
market = client.markets.retrieve("mkt_abc123")
print(f"Market: {market.name}")
print(f"Platform: {market.platform}")
print(f"Category: {market.category}")
print(f"Resolution Date: {market.resolution_date}")
print(f"Volume: ${market.volume:,.2f}")
# Get odds history
odds_history = client.markets.odds(
"mkt_abc123",
interval="1h",
start_date="2024-01-01"
) {
"id": "mkt_abc123",
"object": "market",
"platform": "kalshi",
"name": "Will BTC hit $150k by Dec 2026?",
"category": "crypto",
"status": "open",
"yes_price": 0.58,
"no_price": 0.42,
"volume": 125000.00,
"resolution_date": "2026-12-31T23:59:59Z",
"created_at": "2026-01-01T00:00:00Z"
} Portfolios
Create and manage portfolios to track your positions, monitor P&L, and automate rebalancing based on your strategy parameters.
Endpoints
/v1/portfolios List portfolios /v1/portfolios Create portfolio /v1/portfolios/{id} Retrieve portfolio /v1/portfolios/{id} Update portfolio /v1/portfolios/{id} Delete portfolio # Create a new portfolio
portfolio = client.portfolios.create(
name="High EV Strategy",
description="Targeting 5%+ edge opportunities",
settings={
"min_ev": 0.05,
"max_position_size": 500,
"markets": ["kalshi", "polymarket"],
"auto_rebalance": True
}
)
print(f"Created portfolio: {portfolio.id}")
# Add a position
position = client.portfolios.add_position(
portfolio.id,
signal_id="sig_xyz789",
amount=100
) {
"id": "pf_abc123",
"object": "portfolio",
"name": "High EV Strategy",
"description": "Targeting 5%+ edge opportunities",
"settings": {
"min_ev": 0.05,
"max_position_size": 500,
"markets": ["kalshi", "polymarket"],
"auto_rebalance": true
},
"total_value": 0,
"positions": [],
"created_at": "2026-01-15T10:30:00Z"
} Backtests
Test your strategies against 15+ years of historical data. Analyze returns, drawdowns, win rates, and Sharpe ratios before deploying real capital.
Endpoints
/v1/backtests Run a backtest /v1/backtests/{id} Get results /v1/backtests/{id}/trades List trades Metrics Returned
# Run a backtest on historical data
backtest = client.backtests.create(
strategy={
"min_ev": 0.03,
"max_odds": 5.0,
"position_sizing": "kelly",
"kelly_fraction": 0.25
},
start_date="2023-01-01",
end_date="2024-01-01",
initial_capital=10000,
markets=["kalshi", "polymarket"]
)
# Wait for completion and get results
result = client.backtests.retrieve(backtest.id)
print(f"Total Return: {result.total_return:.2%}")
print(f"Sharpe Ratio: {result.sharpe_ratio:.2f}")
print(f"Max Drawdown: {result.max_drawdown:.2%}")
print(f"Win Rate: {result.win_rate:.2%}") {
"id": "bt_abc123",
"object": "backtest",
"status": "completed",
"total_return": 0.342,
"sharpe_ratio": 1.85,
"max_drawdown": -0.12,
"win_rate": 0.64,
"total_trades": 156,
"avg_position_size": 245.50,
"start_date": "2023-01-01",
"end_date": "2024-01-01",
"created_at": "2026-01-15T10:30:00Z"
} Webhooks
Receive real-time notifications when events occur. Webhooks are useful for building automated trading systems or alerting workflows.
Event Types
signal.created | New +EV signal detected |
signal.updated | Signal EV or price changed |
signal.resolved | Market resolved, signal complete |
signal.result | Signal outcome determined (win/loss) |
odds.movement | Significant line movement detected |
portfolio.alert | Portfolio threshold triggered |
# Create a webhook endpoint
webhook = client.webhooks.create(
url="https://your-app.com/webhooks/evsignals",
events=[
"signal.created",
"signal.updated",
"signal.resolved",
"portfolio.alert"
],
secret="whsec_xxxxxxxxxxxxx" # Optional, for signature verification
)
print(f"Webhook ID: {webhook.id}")
print(f"Webhook Secret: {webhook.secret}") {
"id": "evt_xyz789",
"type": "signal.created",
"created_at": "2026-01-15T10:30:00Z",
"data": {
"signal": {
"id": "sig_abc123",
"market": "kalshi",
"ev_percent": 4.2,
"contract_name": "Will BTC..."
}
}
} Errors
EVSignals uses conventional HTTP response codes to indicate success or failure. Codes in the 2xx range indicate success, 4xx indicate client errors, and 5xx indicate server errors.
Error Codes
| 400 | Bad Request | The request was malformed or missing required parameters. |
| 401 | Unauthorized | Invalid or missing API key. |
| 403 | Forbidden | The API key does not have permission to perform the request. |
| 404 | Not Found | The requested resource does not exist. |
| 429 | Rate Limited | Too many requests. Please slow down and retry after the indicated time. |
| 500 | Server Error | An error occurred on our servers. Please try again later. |
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "min_ev must be between 0 and 1",
"param": "min_ev",
"doc_url": "https://evsignals.com/docs#errors"
}
} Rate Limits
API requests are rate limited to ensure fair usage. Rate limits vary by endpoint and plan tier.
| Endpoint | Free | Pro | Enterprise |
|---|---|---|---|
| Read (GET) | 100/min | 1,000/min | 10,000/min |
| Write (POST/PUT/DELETE) | 20/min | 100/min | 1,000/min |
| Scan | 5/min | 30/min | 120/min |
| Backtest | 2/min | 10/min | 50/min |
Rate Limit Headers
X-RateLimit-Limit Max requests per window X-RateLimit-Remaining Remaining in current window X-RateLimit-Reset Unix timestamp when window resets Retry-After Seconds to wait (on 429 only) {
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded",
"retry_after": 30
}
}
Headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705329600
Retry-After: 30 Need Higher Limits?
Enterprise plans include custom rate limits. Contact us to discuss your needs.
Start finding +EV opportunities
Get your API key in minutes and start scanning 500+ connected sources for live +EV signals.