Concepts
Errors
Errors use normal HTTP status codes and one JSON shape with a stable, dotted code. Branch on code, not on message: messages may be reworded.
Error shape
404 response
{
"error": {
"code": "not_found.event",
"message": "Event not found",
"request_id": "0f8969a6-0968-4d7c-9cbb-de379e8c19c4"
}
}| Field | Description |
|---|---|
error.code | Stable, dotted code from the table below. New codes may be added. |
error.message | A human-readable explanation. For validation errors it names the parameter. |
error.request_id | Same as the X-Request-ID header. Quote it to support. |
All error codes
| HTTP | Code | Meaning | What to do |
|---|---|---|---|
| 401 | auth.missing_key | No X-API-Key header. | Add the header. See authentication. |
| 401 | auth.invalid_key | The key is unknown or revoked. | Check for typos, or create a new key at API keys. |
| 429 | rate_limit.per_second | Too many requests this second. | Wait Retry-After seconds, then retry. |
| 429 | rate_limit.monthly_quota | Your monthly quota is used up. | Retry-After is the seconds until the quota resets (start of next month, UTC). |
| 400 | validation.invalid_parameter | A parameter has the wrong type or is out of range, or a required one is missing. | Fix the parameter named in message, e.g. limit: Input should be less than or equal to 200. |
| 400 | validation.invalid_cursor | The cursor is malformed or was made with other filters. | Restart from the first page without cursor. |
| 400 | validation.missing_parameter | /matches got neither url nor venue and id. | Send one of the two. |
| 400 | validation.invalid_url | The url is not a Kalshi or Polymarket link. | Send a kalshi.com or polymarket.com link. |
| 400 | validation.invalid_id | A /prices id is not a venue:contract_id pair. | Use e.g. kalshi:KXPRESNOMD-28-GN. |
| 400 | validation.too_many_ids | More than 100 ids in one /prices call. | Split into batches of 100. |
| 404 | not_found.event | No event with that slug. | Search with /events. |
| 404 | not_found.market | No venue market with that id, or TPM does not track it yet. | Check the venue and id with /markets. |
| 503 | upstream.unavailable | A service TPM depends on is briefly unavailable. | Retry with exponential backoff. |
Retry safely
- Retry
429after theRetry-Afterheader (seconds). - Retry
503and network errors with exponential backoff: 1 s, 2 s, 4 s, up to about a minute. - Do not retry other
4xxerrors unchanged; fix the request first.
Retry helper
import os
import time
import requests
BASE = "https://api.thepredictionmarkets.com/api/public/v1"
HEADERS = {"X-API-Key": os.environ["TPM_API_KEY"]}
def get(path, params=None, attempts=5):
delay = 1
for _ in range(attempts):
resp = requests.get(BASE + path, params=params, headers=HEADERS, timeout=20)
if resp.status_code == 429:
time.sleep(int(resp.headers.get("Retry-After", "1")))
continue
if resp.status_code >= 500:
time.sleep(delay)
delay = min(delay * 2, 60)
continue
body = resp.json()
if not resp.ok:
err = body["error"]
raise RuntimeError(f"{err['code']} ({err['request_id']}): {err['message']}")
return body
raise RuntimeError("gave up after retries")Related
Build with TPM
Get your free API key
One key gives you Kalshi and Polymarket events, prices with freshness, price history, cross-venue gaps and the live quotes WebSocket.