Docs

Quickstart

Every API on API Runner is reached through one base URL with one Bearer token. Learn it once and you know all of them.

1. Base URL

All requests go to a single host. The path picks the provider and resource.

base url
https://api.apirunner.dev/v1/{provider}/{resource}

2. Authentication

Create a key in the dashboard and send it in the Authorization header. Keys start with apr_live_. Keep them server-side.

header
Authorization: Bearer apr_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

3. Your first request

Current weather for New York, in your language of choice:

curl "https://api.apirunner.dev/v1/weather/current?lat=40.7128&lon=-74.0060&units=metric" \
  -H "Authorization: Bearer YOUR_RUNNER_KEY"

4. Switching providers

Same host, same header — only the path and body change. Here's Claude with the identical setup:

curl -X POST "https://api.apirunner.dev/v1/anthropic/messages" \
  -H "Authorization: Bearer YOUR_RUNNER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet",
    "system": "You are a terse senior engineer.",
    "prompt": "Explain what a 429 means and how to back off.",
    "max_tokens": 300
  }'
RouteAPIStatus
GET/v1/weather/currentWeatherlive
GET/v1/weather/forecastWeatherlive
GET/v1/weather/geocodeWeatherlive
POST/v1/fitness/stepsPedometer & Fitnesslive
GET/v1/fitness/stridePedometer & Fitnesslive
POST/v1/fitness/devices/syncPedometer & Fitnesslive
POST/v1/openai/chat/completionsOpenAI Chatlive
POST/v1/openai/images/generationsOpenAI Imageslive
POST/v1/openai/audio/speechOpenAI Voice & Whisperlive
POST/v1/openai/audio/transcriptionsOpenAI Voice & Whisperlive
POST/v1/gemini/generateGoogle Geminilive
POST/v1/gemini/multimodalGoogle Geminilive
POST/v1/anthropic/messagesAnthropic Claudelive
POST/v1/email/sendEmailsoon
GET/v1/email/messages/{id}Emailsoon
POST/v1/push/sendPush & Webhookssoon
POST/v1/webhooksPush & Webhookssoon
POST/v1/mistral/chat/completionsMistrallive
POST/v1/llama/chat/completionsMeta Llamalive
POST/v1/deepseek/chat/completionsDeepSeeklive
POST/v1/perplexity/askPerplexity Sonarsoon
POST/v1/embeddingsText Embeddingslive
POST/v1/translateTranslatelive
POST/v1/stability/generateStable Diffusionlive
POST/v1/vision/ocrOCR & Documentslive
POST/v1/voice/clonesVoice Cloningsoon
POST/v1/vision/detectObject Detectionlive
POST/v1/vision/remove-backgroundBackground Removallive
GET/v1/geo/forwardAddress Geocodinglive
GET/v1/geo/reverseAddress Geocodinglive
GET/v1/ip/lookupIP Geolocationlive
GET/v1/fx/convertCurrency Rateslive
POST/v1/qrQR Codeslive
GET/v1/air-quality/currentAir Qualitylive
GET/v1/fitness/heart/dailyHeart Rate & Sleepsoon
POST/v1/linksURL Shortenerlive
POST/v1/sms/sendSMSsoon
POST/v1/messaging/postSlack & Discordsoon

5. Status codes

Errors share one shape, whatever the upstream provider:

error body
{
  "error": {
    "type": "rate_limit_exceeded",
    "message": "Limit of 8 requests per 10s reached. Retry after 4s.",
    "request_id": "req_8kq2m4v7xz1p"
  }
}
200OK
Request succeeded. Body is the provider's response, normalized where noted.
400Bad Request
Malformed JSON or unsupported content type.
401Unauthorized
Missing, revoked or invalid Bearer token.
422Unprocessable Entity
Validation failed. `error.fields` lists what to fix.
429Too Many Requests
Rate limit hit. Wait `Retry-After` seconds, then retry with backoff.
502Bad Gateway
Upstream provider failed. Safe to retry idempotent requests.

6. Rate limits & response headers

Every response carries these headers so you can debug without guessing:

response headers
x-request-id: req_8kq2m4v7xz1p
x-runner-latency: 142ms
x-runner-upstream: anthropic
x-ratelimit-limit: 8
x-ratelimit-remaining: 6
retry-after: 4          # only on 429

The playground enforces 8 requests per 10 seconds — click Run quickly a few times to see a real 429.