Integrate Chalk signals, coverage data, and paper bets into your own tools. Webhooks push halftime alerts to your endpoint the moment a filter matches.
Every request must include your API key in the X-API-Key header. Generate a key in Settings. One key per account — revoke or regenerate anytime.
curl https://chalk.is/api/v1/syndicate/signals \
-H 'X-API-Key: chalk_sk_...'All endpoints require a Syndicate subscription. Pro-tier keys receive a 403 Forbidden response.
60/min
Burst limit
5,000/day
Daily quota
10 retries
Webhook delivery
Every response includes rate-limit headers:
X-RateLimit-Limit-Minute: 60
X-RateLimit-Remaining-Minute: 58
X-RateLimit-Limit-Day: 5000
X-RateLimit-Remaining-Day: 4847
X-RateLimit-Reset: 1711843200When you hit a limit, the response is 429 Too Many Requests with a Retry-After header in seconds.
All paths are relative to https://chalk.is/api/v1/syndicate
| Method | Path | Description |
|---|---|---|
| GET | /me | API key owner info and rate limit status |
| GET | /signals | Today's halftime signals |
| GET | /signals/{game_id} | Single game signal detail |
| GET | /games | Today's games with status |
| GET | /games/{game_id} | Game detail |
| GET | /games/{game_id}/coverage | Cover dynamics and betting signal data |
| GET | /games/{game_id}/lines | 2H line history for a game |
| GET | /paper-bets | List your paper bets |
| POST | /paper-bets | Place a new paper bet |
| POST | /paper-bets/resolve | Resolve pending bets for finished games |
| DELETE | /paper-bets/{bet_id} | Cancel a pending paper bet |
| PATCH | /paper-bets/{bet_id} | Update line, amount, or odds on a pending bet |
| GET | /webhooks | Get webhook endpoint status |
| POST | /webhooks | Register a webhook endpoint |
| PUT | /webhooks | Update webhook URL (new signing secret) |
| DELETE | /webhooks | Remove webhook endpoint |
| POST | /webhooks/test | Send a test payload to your webhook |
| POST | /webhooks/rotate-secret | Rotate signing secret without changing URL |
| GET | /filters | List your filters and published edges |
API key owner info and rate limit status
Today's halftime signals
Single game signal detail
Today's games with status
Game detail
Cover dynamics and betting signal data
2H line history for a game
List your paper bets
Place a new paper bet
Resolve pending bets for finished games
Cancel a pending paper bet
Update line, amount, or odds on a pending bet
Get webhook endpoint status
Register a webhook endpoint
Update webhook URL (new signing secret)
Remove webhook endpoint
Send a test payload to your webhook
Rotate signing secret without changing URL
List your filters and published edges
GET/signals
date string # YYYY-MM-DD, default today
league string # "cbb" or "nba", default "cbb"GET/games
date string # YYYY-MM-DD, default today
league string # "cbb" or "nba", default "cbb"POST/paper-bets
game_id string # Game identifier (from /games)
side string # "HOME", "AWAY", "OVER", or "UNDER"
line number # Spread or total line (e.g. -3.5)
bet_type string # "2h_spread", "fg_spread", "total_over", "total_under", "1h_spread"
amount number # Wager amount in units
odds integer # American odds (e.g. -110)POST/paper-bets/resolve
game_id string # Optional — resolve only bets for this game.
# Omit to resolve all pending bets with finished games.PATCH/paper-bets/{bet_id}
line number # Optional — new spread/total line
amount number # Optional — new wager amount
odds integer # Optional — new American oddsPOST/webhooks
url string # HTTPS endpoint to receive webhook payloadsPUT/webhooks
url string # New HTTPS endpoint (generates new signing secret)Register an HTTPS endpoint via POST /webhooks or in Settings to receive a signed POST when a filter matches at halftime. Each delivery includes two verification headers:
X-Chalk-Signature — HMAC-SHA256 hex digest of {timestamp}.{payload}X-Chalk-Timestamp — Unix epoch seconds when the payload was generated{
"event": "signal.matched",
"timestamp": "2026-03-31T01:15:00Z",
"data": {
"game_id": "805081125660",
"home_team": "Kansas",
"away_team": "Duke",
"league": "cbb",
"halftime_score": { "home": 28, "away": 37 },
"halftime_margin": 9,
"regime": "trailing",
"signal": "BEARISH",
"model_implied_2h": -1.2,
"market_2h_line": -5.5,
"edge_pts": 4.3,
"filter": {
"id": "a1b2c3d4-...",
"name": "Power4 Trailing Bearish"
},
"game_url": "https://chalk.is/game/805081125660?src=webhook"
}
}Reject any request where the signature does not match or the timestamp is more than 5 minutes old.
Python
import hmac, hashlib
def verify_signature(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
f"{timestamp}.".encode() + payload,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)TypeScript
import { createHmac, timingSafeEqual } from "crypto";
function verifySignature(
payload: string,
signature: string,
timestamp: string,
secret: string,
): boolean {
const expected = createHmac("sha256", secret)
.update(`${timestamp}.${payload}`)
.digest("hex");
return timingSafeEqual(
Buffer.from(`sha256=${expected}`),
Buffer.from(signature),
);
}After 10 consecutive delivery failures, the webhook is automatically disabled. Re-enable it in Settings after fixing your endpoint.
| Code | Name | Description |
|---|---|---|
| 401 | Unauthorized | Missing or invalid API key. Check the X-API-Key header. |
| 403 | Forbidden | Valid key but insufficient tier. Syndicate required for API access. |
| 404 | Not Found | Resource does not exist. Verify the game ID or endpoint path. |
| 422 | Validation Error | Request parameters failed validation. Check the error detail. |
| 429 | Rate Limited | Too many requests. Back off and check X-RateLimit-Reset header. |