> ## Documentation Index
> Fetch the complete documentation index at: https://docs.surfaceapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

> Cross-exchange prediction market data via a single API.

The Surface API gives you programmatic access to Surface's cross-exchange matching system. Look up any [Kalshi contract ticker or Polymarket contract ID](/quickstart#understanding-contract-id) and get the full cluster — every contract in the same cross-exchange group, their resolution rules, and the relationships between them.

Every match passes through a multi-stage validation pipeline. Team, date, line, and side alignment are all checked before a result is accepted. If a candidate doesn't clear the bar, it's rejected rather than returned.

## Base URL

```
https://surfaceapi.com/api/v1
```

## Authentication

All requests require an API key in the `X-API-Key` header.

```bash theme={null}
curl https://surfaceapi.com/api/v1/match/KXMLBGAME-26MAR252005NYYSF-SF \
  -H "X-API-Key: YOUR_API_KEY"
```

Create an account and generate a key at [surfaceapi.com/portal](https://surfaceapi.com/portal).

## Rate limits

The free tier allows **25 new unique cluster lookups per day**.

**Repeat lookups are always free.** Looking up any contract ID within a cluster you've already accessed never counts against your quota.

**404s are also free.** If no match is found for a contract, that request does not consume a quota slot.

Quota resets at **midnight UTC** each day. Two response headers are present on every request:

| Header                    | Description                                |
| ------------------------- | ------------------------------------------ |
| `X-Match-Limit-Remaining` | New unique cluster lookups remaining today |
| `X-Match-Limit-Reset`     | RFC3339 UTC timestamp of the next reset    |

## Errors

All errors use the same envelope:

```json theme={null}
{
  "error": "unauthorized",
  "message": "Invalid or revoked API key."
}
```

On a `429`, three additional fields are included:

```json theme={null}
{
  "error": "daily_limit_reached",
  "message": "Free tier limit of 25 new matches per day reached. Resets at midnight UTC.",
  "limit": 25,
  "used": 25,
  "resets_at": "2026-03-03T00:00:00Z"
}
```

| Status | `error` code          | When                                                    |
| ------ | --------------------- | ------------------------------------------------------- |
| `401`  | `unauthorized`        | Missing, invalid, or revoked API key                    |
| `404`  | `no_match`            | No match found — contract may not yet be in the dataset |
| `429`  | `daily_limit_reached` | Free tier quota exhausted                               |
| `500`  | `internal_error`      | Unexpected server error                                 |
