Data API Overview

About

The Surf Data API provides typed REST endpoints for crypto market data, project analytics, on-chain queries, and more. Endpoints are billed per request in credits and rate-limited per API key — see Rate Limits and Credits below.

Base URL: https://api.asksurf.ai/gateway

Authentication

All data endpoints require a Bearer token in the Authorization header:

Authorization: Bearer <API_KEY>

How to get your API key

  1. Go to agents.asksurf.ai and sign in with Google or email
  2. Open the Dashboard and click Generate API Key
  3. Copy your key (starts with sk-)

Free tier

  • No sign-up required. Every IP gets 30 free credits per day — try any endpoint without an API key. Resets at 00:00 UTC.
  • Sign up for full access. Generate an API key from the Dashboard, then top up with credit card or crypto (USDC).

Using the key

In code (Data API / Chat API):

curl "https://api.asksurf.ai/gateway/v1/market/price?symbol=BTC" \
  -H "Authorization: Bearer sk-your-key-here"

In the CLI:

surf auth --api-key sk-your-key-here   # saved to OS keychain (or ~/.surf/config.json as fallback)
# or
export SURF_API_KEY=sk-your-key-here

In AI agents (Claude Code, Cursor, etc.): the Surf Skill picks up SURF_API_KEY from your environment automatically. No extra config needed.

Rate Limits

Rate limits are enforced per API key as a sliding 60-second window. Each account holds one bucket regardless of how many keys it has issued.

TierLimitApplies to
Anonymous (no API key)30 credits / day per IPUnauthenticated trial requests. Daily credit budget — there is no separate per-second cap; once the 30 credits are spent the IP is blocked until 00:00 UTC.
Pay-as-you-go (default)100 requests / minute per API keyAuto-assigned to every account on sign-up.
Enterprise / CustomConfigured per contractNegotiated based on your expected peak throughput. Contact us to raise this.

A few specifics:

  • No per-endpoint cap. Every request — regardless of endpoint — counts against the same per-API-key bucket.
  • Burst-friendly. Because the limiter is a sliding 60-second window, you can fire your full quota at once (e.g. all 100 requests in the first second) and then wait for the window to roll forward. There is no separate concurrency cap.
  • Credit cost is independent. Different endpoints cost different amounts of credits — see meta.credits_used on every response. Credits gate your spend; the RPM limit gates your throughput. They are not linked.

When you exceed the limit you get HTTP 429 with error.code: RATE_LIMITED and a message like rate limit exceeded (100 requests per 60s). Back off and retry — the window is continuous, so capacity returns as old requests age out.

Parameter Conventions

Asset Identification

ParamTypeDescriptionExample
symbolstringUppercase ticker symbol(s), comma-separatedBTC, ETH,SOL
qstringFree-text search keywordbitcoin
idstringSurf entity UUID for direct lookup550e8400-...
addressstringOn-chain contract or wallet address. Also accepts ENS names (e.g. vitalik.eth)0xdead...

Time & Aggregation

ParamTypeDescriptionExample
time_rangestring or intLookback window7d, 30d, 365d, max
intervalstringCandlestick / indicator interval1h, 1d, 1w
granularitystringData aggregation granularityday, block, hour

Filtering & Sorting

ParamTypeDescriptionExample
chainstringBlockchain name (canonical long-form only)ethereum, solana, base
currencystringQuote currencyusd, eur, btc
metricstringMetric name (endpoint-specific enum)nupl, tvl
typestringCategory selector (endpoint-specific enum)us-btc-spot
sort_bystringSort fieldvolume_24h, market_cap
orderstringSort directionasc, desc

Pagination

All list endpoints support:

  • limit (int, default: 20, max: 100) — results per page
  • offset (int, default: 0) — pagination offset

Supported Chains

Use canonical long-form names only. Short aliases (eth, sol, matic, etc.) are not accepted.

ChainValue
Ethereumethereum
Polygonpolygon
BNB Chainbsc
Solanasolana
Avalancheavalanche
Arbitrumarbitrum
Optimismoptimism
Fantomfantom
Basebase
Linealinea
Cybercyber

Not all chains are available on every endpoint. Check each endpoint's chain enum for supported values.


Endpoint Notes

Quick reference for data characteristics across endpoint groups. For raw SQL access to the underlying tables, see Onchain SQL.

Exchange

CEX market data from major exchanges. Real-time or near-real-time.

  • price returns last traded price; klines returns OHLCV candlesticks
  • depth is a live order book snapshot — not historical
  • funding-history and long-short-ratio are perp-specific

Market

Aggregated market indicators and rankings.

  • price returns CoinGecko-sourced token prices — hourly snapshots, not tick-level
  • ranking sorts by market cap or volume; use sort_by and order to customize
  • onchain-indicator covers NUPL, SOPR, MVRV and other BTC-centric metrics
  • etf returns daily fund flow data for US BTC/ETH spot ETFs

Token

On-chain token activity. Data refreshes daily (~24h lag).

  • dex-trades: swap events from Uniswap, SushiSwap, Curve, Balancer. USD amounts are one-sided (token_sold value, following DefiLlama methodology). Chains: Ethereum, Base.
  • transfers: ERC-20 + native token transfers with USD pricing. Chains: Ethereum, Base, Arbitrum, BSC, Tron.
  • holders: top holders by balance. Snapshot, not real-time.
  • No aggregator attribution — a 1inch-routed swap shows as the underlying DEX.
  • holders, transfers, and dex-trades support opt-in address-label enrichment via include=labels — see Address Label Enrichment.

Project

Protocol-level DeFi data.

  • defi-metrics: TVL, fees, revenue, yields per protocol. TVL is supply-side only (excludes borrows). CoinGecko-priced — unpriced tokens valued at $0.
  • defi-ranking: sorted protocol list with TVL, fee, and volume data.

News

Aggregated crypto news from multiple sources.

  • feed returns latest articles; detail returns full content by article ID

Wallet

Multi-chain wallet analytics.

  • detail returns wallet balance breakdown across chains
  • labels-batch returns known wallet labels (exchange, fund, whale, etc.)
  • protocols shows DeFi positions held by the wallet
  • net-worth returns historical net worth (daily granularity)
  • transfers and history support opt-in address-label enrichment via include=labels — see Address Label Enrichment.

Onchain

Direct access to on-chain data including raw SQL queries.

  • tx: single EVM transaction lookup by hash (JSON-RPC). Supports opt-in address-label enrichment via include=labels — see Address Label Enrichment.
  • sql: execute arbitrary SQL against 106 ClickHouse tables. See the Onchain SQL guide for table schemas and query patterns.
  • query: structured (no-SQL) query interface for the same tables
  • schema: returns all available table metadata programmatically — use this for dynamic discovery
  • bridge-ranking: cross-chain bridge volume rankings
  • yield-ranking: DeFi pool yields sorted by APY

Prediction Market

Polymarket (on-chain, Polygon) and Kalshi (centralized API) data.

  • All volume figures are one-sided (Paradigm methodology)
  • Polymarket data lag: ~1 hour. Kalshi data lag: ~6 hours.
  • Polymarket open interest is sparse — only rows on days with OI-changing events, not every calendar day
  • positions returns per-wallet position data with PnL
  • ranking returns pre-computed market rankings by volume and OI

Fund

Crypto venture fund data.

  • detail returns fund profile (AUM, portfolio size, investment stage)
  • portfolio returns fund holdings with entry dates
  • ranking sorts funds by AUM or deal count

Full-text search across all entity types. All search endpoints accept a q parameter.

Web

  • fetch: retrieves and parses a web page. Useful for enrichment workflows.

Address Label Enrichment

Six endpoints accept an optional include=labels query parameter that attaches entity-label records to every address in the response. Labels come from Surf's address intelligence service and cover exchanges, protocols, funds, market makers, notable wallets, and ENS-registered addresses.

Supported endpoints:

EndpointAddress field(s) enrichedAttached field(s)
GET /v1/wallet/transfersfrom_address, to_addressfrom_label, to_label
GET /v1/wallet/historyfrom_address, to_addressfrom_label, to_label
GET /v1/token/holdersaddresslabel (full record)
GET /v1/token/transfersfrom_address, to_addressfrom_label, to_label
GET /v1/token/dex-tradestakertaker_label
GET /v1/onchain/txfrom, tofrom_label, to_label

Usage:

curl "https://api.asksurf.ai/gateway/v1/wallet/transfers?\
address=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&\
chain=ethereum&limit=5&include=labels" \
  -H "Authorization: Bearer $SURF_API_KEY"

Example response item (wallet transfer to vitalik.eth with include=labels):

{
  "tx_hash": "0x...",
  "from_address": "0x94a42db1e578eff403b1644fa163e523803241fd",
  "from_label": {
    "address": "0x94a42db1e578eff403b1644fa163e523803241fd",
    "labels": [{ "label": "jizzinmy.eth", "confidence": 1 }]
  },
  "to_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
  "to_label": {
    "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
    "labels": [{ "label": "vitalik.eth", "confidence": 1 }],
    "entity_name": "Vitalik Buterin",
    "entity_type": "individual"
  },
  "amount": "0.0001",
  "amount_usd": 0.23
}

Semantics:

  • Additive by default. Without include=labels, responses are byte-identical to the pre-feature shape — the *_label fields are absent, not null.
  • Addresses with no known labels serialize as null on opt-in (not as empty objects). Filter with if (item.from_label) client-side.
  • Token holders are a special case: entity_name and entity_type are populated unconditionally for backward compatibility. The richer label record is only attached when include=labels is set.
  • Latency impact is small. Labels are cached per-address (~1h) and a 200ms timeout wraps every enrichment call — a slow or failing label backend returns items without labels rather than failing the request.
  • Unknown include values return HTTP 422 listing the valid options.

Error Responses

All endpoints return errors in a consistent format:

{
  "error": {
    "code": "PAID_BALANCE_ZERO",
    "message": "credits exhausted; top up to continue"
  }
}

HTTP Status

StatusMeaning
400Bad request — invalid or missing parameters
401Unauthorized — missing or invalid API key
402Payment required — credits exhausted (see error.code for which pool)
404Not found — the requested entity does not exist
422Validation error — parameter value is out of range or invalid
429Rate limited — back off and retry. See Rate Limits.
502Upstream error — a data source is temporarily unavailable
503Upstream unavailable — retryable
504Upstream timeout — retryable

Error Codes

The error.code field gives a stable machine-readable classification. Switch on error.code, not on the message.

CodeHTTPWhen
INVALID_REQUEST400 / 422Missing required param or invalid value
INVALID_METRIC / INVALID_SOURCE / INVALID_FIELD / INVALID_OPERATOR422Enum or query-shape validation failure
UNAUTHORIZED401Missing or invalid API key
FREE_QUOTA_EXHAUSTED402Anonymous IP used all 30 daily free credits — sign up and use an API key to continue
PAID_BALANCE_ZERO402Authenticated account balance is zero — top up in the Dashboard
INSUFFICIENT_CREDIT402Legacy; older deployments may still return this. New clients should handle FREE_QUOTA_EXHAUSTED and PAID_BALANCE_ZERO
NOT_FOUND404Entity / resource does not exist
RATE_LIMITED429Per-key RPM exceeded — retry after the Retry-After header
UPSTREAM_RATE_LIMITED502Data source returned 429 — retryable
UPSTREAM_UNAVAILABLE503Data source temporarily down — retryable
UPSTREAM_TIMEOUT504Data source timed out — retryable
UPSTREAM_ERROR502Generic upstream failure (catch-all)
QUERY_TIMEOUT504ClickHouse query exceeded the time limit (on POST /onchain/sql) — narrow the query
INTERNAL_ERROR500Server bug — report to support

Credits

Each API call costs a certain number of credits. The cost is returned in every response under meta.credits_used. Check your remaining balance via GET /v1/me/credit-balance.

Data API endpoints are priced in three tiers — Light (1 credit), Standard (2 credits), and Heavy (4 credits) — and re-calling the same endpoint within 3 minutes is free. For the full per-endpoint breakdown and what a credit costs in USD, see Credits & Pricing.

Surf — Crypto Intelligence for AI Agents