Quick Start

Get up and running in 3 steps:

1. Get your API key

Sign up to get your API key instantly. Then purchase credits or redeem a voucher to get started.

2. Make your first query

Query NO₂ air quality data for Paris, January 2023:

bash
curl "https://api.tilequery.com/api/v1/climate/query?\
lat_min=48.5&lat_max=49.2&\
lon_min=2.0&lon_max=2.8&\
time_start=1672531200&time_end=1675209600&\
pollutants=no2" \
  -H "X-API-Key: sk_live_your_key_here"

3. Parse the response

json
{
  "status": "success",
  "query_time_ms": 787,
  "tiles_scanned": 2,
  "credits_used": 2,
  "credits_remaining": 198,
  "output": "lat,lon,time,no2\n48.6,2.1,1672531200,32.5\n..."
}

Authentication

All API requests require an API key. You can pass it in two ways:

Header (recommended)

http
X-API-Key: sk_live_your_key_here

Query parameter

http
GET /api/v1/climate/query?api_key=sk_live_your_key_here&...

Security note: API keys are hashed with SHA-256 before storage. We never store your raw key.

Credits

Each query costs credits based on the data it touches:

Formula
credits = geographic_tiles × time_months × pollutants
FactorDescriptionExample
geographic_tiles Number of 5°×5° grid tiles that cover your lat/lon bounds Paris region: 2 tiles
time_months Number of months in your time range Jan 2023: 1 month
pollutants Number of pollutants queried no2: 1 pollutant

Your remaining balance is returned in every response as credits_remaining. If you don't have enough credits, the API returns 402 Payment Required.

Query Endpoint

GET /api/v1/climate/query

Query climate data for a geographic region and time range.

Parameters

ParameterTypeRequiredDescription
lat_min float required Minimum latitude (-90 to 90)
lat_max float required Maximum latitude (-90 to 90)
lon_min float required Minimum longitude (-180 to 180)
lon_max float required Maximum longitude (-180 to 180)
time_start int64 required Start time as Unix timestamp (seconds)
time_end int64 required End time as Unix timestamp (seconds)
pollutants string optional Comma-separated list. Values: no2, pm2p5. Default: no2

Response

json
{
  "status": "success",
  "query_time_ms": 787,
  "tiles_scanned": 2,
  "credits_used": 2,
  "credits_remaining": 6498,
  "output": "lat,lon,time,no2\n48.6,2.1,1672531200,32.5\n48.7,2.2,1672531200,28.1\n..."
}

The output field contains CSV-formatted data with columns for latitude, longitude, Unix timestamp, and pollutant values.

Health Check

GET /health

Check if the API is running. No authentication required.

json
{
  "status": "ok",
  "s3_configured": true,
  "query_binary": "/app/query_qkpt2"
}

Redeem Voucher

POST /api/v1/redeem

Redeem a voucher code to add free credits to your account. Requires authentication.

Request Body

json
{
  "code": "WELCOME-2025-ABC"
}

Response

json
{
  "status": "success",
  "credits_added": 500,
  "credits_remaining": 500,
  "description": "Welcome bonus"
}
StatusMeaning
200Voucher redeemed successfully
404Invalid voucher code
409Voucher already redeemed
410Voucher has expired

Buy Credits

POST /api/v1/checkout

Create a Stripe checkout session to purchase credits.

Request Body

json
{
  "package": "starter",
  "api_key_id": "your-api-key-uuid"
}
FieldTypeDescription
package string One of: starter (€10), professional (€50), enterprise (€200)
api_key_id string Your API key UUID (from account setup)

Response

json
{
  "checkout_url": "https://checkout.stripe.com/c/pay/..."
}

Redirect the user to checkout_url to complete payment. Credits are added automatically after successful payment.

Code Examples

Python

python
import requests

API_KEY = "sk_live_your_key_here"
BASE_URL = "https://api.tilequery.com"

response = requests.get(
    f"{BASE_URL}/api/v1/climate/query",
    headers={"X-API-Key": API_KEY},
    params={
        "lat_min": 48.5, "lat_max": 49.2,
        "lon_min": 2.0, "lon_max": 2.8,
        "time_start": 1672531200,  # 2023-01-01
        "time_end": 1675209600,    # 2023-02-01
        "pollutants": "no2"
    }
)

data = response.json()
print(f"Query took {data['query_time_ms']}ms")
print(f"Credits remaining: {data['credits_remaining']}")
print(data["output"][:200])

JavaScript (Node.js)

javascript
const API_KEY = "sk_live_your_key_here";
const BASE_URL = "https://api.tilequery.com";

const params = new URLSearchParams({
  lat_min: 48.5, lat_max: 49.2,
  lon_min: 2.0, lon_max: 2.8,
  time_start: 1672531200,
  time_end: 1675209600,
  pollutants: "no2"
});

const res = await fetch(
  `${BASE_URL}/api/v1/climate/query?${params}`,
  { headers: { "X-API-Key": API_KEY } }
);

const data = await res.json();
console.log(`Query took ${data.query_time_ms}ms`);
console.log(`Credits remaining: ${data.credits_remaining}`);

cURL

bash
# Query PM2.5 in London, March 2023
curl "https://api.tilequery.com/api/v1/climate/query?\
lat_min=51.3&lat_max=51.7&\
lon_min=-0.5&lon_max=0.3&\
time_start=1677628800&time_end=1680307200&\
pollutants=pm2p5" \
  -H "X-API-Key: sk_live_your_key_here"

Error Handling

The API uses standard HTTP status codes:

StatusMeaningAction
200 Success Parse the response data
400 Bad Request Check your query parameters
401 Unauthorized Check your API key
402 Payment Required Insufficient credits — buy more
500 Server Error Retry after a moment; contact support if persistent

Error response format

json
{
  "error": "Insufficient credits",
  "credits_remaining": 3,
  "credits_required": 8
}