# PayPerQ (PPQ) API > PayPerQ is a unified AI API gateway with 500+ models including Chat, Image, Video, Embeddings, STT, TTS, private (TEE) inference, and more from all major providers. OpenAI-compatible endpoints, pay-per-use pricing (no subscriptions), and cryptocurrency payment support for Bitcoin, Bitcoin lightning, USDT, USDC, XMR, LTC, and any other cryptocurrency. PayPerQ provides a single API that gives you access to models from OpenAI, Anthropic, Google, xAI, Mistral, Meta, Deepseek, Qwen, and more — all through an OpenAI-compatible interface. You pay only for what you use with no minimum spend or monthly commitment. Top up your balance with crypto (Bitcoin Lightning, BTC, Monero, Litecoin, Liquid BTC), Nostr Wallet Connect (NWC) auto-topup, or a credit or debit card via Stripe. The API works with any tool that supports the OpenAI API format: Claude Code, OpenCode, Cursor, Cline, Aider, Roo, OpenWebUI, Goose, and thousands more. ## API Basics - **Chat, Image, Video & Embeddings API Base URL**: `https://api.ppq.ai` - **Audio API Base URL**: `https://ppq.ai/api/v1` - **Authentication**: `Authorization: Bearer YOUR_API_KEY` (keys are prefixed with `sk-`) - **Schema**: OpenAI-compatible — use the OpenAI SDK with a custom `base_url` - **Streaming**: Supported via SSE (Server-Sent Events) for chat completions To get an API key, sign up at https://ppq.ai and visit https://ppq.ai/api-docs to generate one. ### Quickstart (Python) ```python import requests api_key = "sk-YOUR_API_KEY" url = "https://api.ppq.ai/v1/chat/completions" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {api_key}" } data = { "model": "claude-sonnet-4-5", "messages": [{"role": "user", "content": "Hello, how are you?"}] } response = requests.post(url, json=data, headers=headers) print(response.json()) ``` ### Quickstart (cURL) ```bash curl https://api.ppq.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "claude-sonnet-4-5", "messages": [{"role": "user", "content": "Hello, how are you?"}] }' ``` ### Using the OpenAI SDK ```python from openai import OpenAI client = OpenAI( api_key="sk-YOUR_API_KEY", base_url="https://api.ppq.ai/v1" ) response = client.chat.completions.create( model="claude-sonnet-4-5", messages=[{"role": "user", "content": "Hello!"}] ) print(response.choices[0].message.content) ``` ## Endpoints ### Chat Completions - `POST https://api.ppq.ai/v1/chat/completions` — Send messages to any supported LLM - `POST https://api.ppq.ai/chat/completions` — Alias (same behavior, without `/v1` prefix) - `POST https://api.ppq.ai/v1/responses` / `POST https://api.ppq.ai/responses` — OpenAI Responses API (drop-in replacement, see [Responses API](#responses-api)) ### Online Mode (Web Search) Any model can search the web in real time by including a `plugins` array in the request: ```bash curl -X POST https://api.ppq.ai/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "claude-sonnet-4-5", "plugins": [{"id": "web", "max_results": 5}], "messages": [{"role": "user", "content": "What is the weather in Omaha, Nebraska right now?"}] }' ``` - **Plugin parameters**: `id` (required, use `"web"`) and `max_results` (number of web results to retrieve and inject into context, default: 5) - **Search providers**: Models from Perplexity, OpenAI (GPT-5+), and Anthropic (Claude) use their provider's native web search. All other models use Exa.AI ($0.02/request, in addition to token costs). ### Responses API PPQ exposes a drop-in replacement for OpenAI's Responses API — the newer agentic-loop endpoint that supersedes Chat Completions for tool-using and reasoning workflows. Same auth, billing, balance enforcement, and model catalog as `/chat/completions`. Use it from clients that natively expect the Responses schema (e.g. the OpenAI SDK's `client.responses.create()` method, agent frameworks built on Responses, OpenAI Agents SDK). - `POST https://api.ppq.ai/v1/responses` — Submit a Responses-API request - `POST https://api.ppq.ai/responses` — Alias (same behavior, without `/v1` prefix) Request fields (only `model` and `input` are required; everything else is optional): | Field | Type | Description | |-------|------|-------------| | `model` | string | Any model that works on `/chat/completions` (e.g. `openai/gpt-5.5`, `claude-sonnet-4-5`). | | `input` | string \| array | Prompt as plain text, or an array of role-tagged message/content items (text, images, files). | | `instructions` | string | System-level guidance prepended to the conversation. | | `max_output_tokens` | number | Cap on tokens generated for the response. | | `temperature` | number | Sampling temperature, `0`–`2`. | | `top_p` | number | Nucleus sampling. | | `tools` | array | Tool definitions the model can call (functions, web_search, file_search, code_interpreter, MCP, etc.). | | `tool_choice` | string \| object | Constrain tool selection (`"auto"`, `"none"`, `"required"`, or `{ type, name }`). | | `parallel_tool_calls` | boolean | Allow concurrent tool calls in one turn. | | `reasoning` | object | Reasoning-model controls (e.g. `{ "effort": "low" \| "medium" \| "high" }`). | | `response_format` | object | Structured-output schema (JSON schema or `json_object`). | | `previous_response_id` | string | Continue from a prior stored response. | | `store` | boolean | Persist the response upstream for later retrieval. | | `metadata` | object | Up to 16 user-supplied key/value tags (strings/numbers/booleans). | | `stream` | boolean | Stream the response as Server-Sent Events. | | `include` | array | Request additional output fields in the response. | | `truncation` | string | Context-window truncation strategy. | | `user` | string | End-user identifier for abuse tracking. | Response shape: ```json { "id": "resp_…", "object": "response", "model": "openai/gpt-5.5", "status": "completed", "output": [ /* array of output items: messages, tool calls, reasoning, … */ ], "output_text": "concatenated assistant text", "usage": { "input_tokens": 12, "output_tokens": 34, "total_tokens": 46 }, "created_at": 1709234567 } ``` Streaming events (SSE, when `"stream": true`): `response.created`, `response.in_progress`, `response.output_item.added`, `response.content_part.added`, `response.output_text.delta`, `response.output_text.done`, `response.output_item.done`, `response.completed`, `response.failed`. The terminal `response.completed` event carries the final `usage` block (input / output / cached tokens and cost) that PPQ uses for billing. For the canonical schema, see OpenAI's reference at https://platform.openai.com/docs/api-reference/responses — PPQ accepts the same payloads. ```bash curl -N -X POST https://api.ppq.ai/v1/responses \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "openai/gpt-5.5", "input": "Say hi", "stream": true }' ``` ```python from openai import OpenAI client = OpenAI(api_key="sk-YOUR_API_KEY", base_url="https://api.ppq.ai/v1") response = client.responses.create( model="openai/gpt-5.5", input="Hello, how are you?", ) print(response.output_text) ``` Notes: - `private/*` models are not supported on this endpoint — use the local TEE proxy described below for end-to-end-encrypted requests. - Insufficient balance returns `402 Payment Required`, identical to `/chat/completions`. ### Private (TEE) Models Private models run inside **Trusted Execution Environments** — hardware-attested secure enclaves on NVIDIA confidential-computing GPUs (powered by [Tinfoil](https://tinfoil.sh)). The request body is encrypted **in your process** with HPKE before it ever reaches PPQ's servers, decrypted only inside the attested enclave, and the response is encrypted on the way back. PPQ can only see ciphertext and routing metadata — never prompts or completions. To use private models, run the open-source proxy locally (or inside your client), then point any OpenAI-compatible client at the proxy. The proxy handles attestation, HPKE key exchange, and encryption — you can't hit `https://api.ppq.ai/v1/chat/completions` with a `private/*` model directly. - **Proxy repo**: https://github.com/PayPerQ/ppq-private-mode-proxy - **Blog — intro**: https://ppq.ai/blog/introducing-tee-models - **Blog — how to use via API / OpenClaw**: https://ppq.ai/blog/using-private-tee-models-with-openclaw ```bash # Start the local proxy (port 8787); needs Node.js 18+ PPQ_API_KEY=sk-YOUR_API_KEY npx ppq-private-mode # Send a standard OpenAI chat completion — the proxy encrypts it for you curl http://127.0.0.1:8787/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"private/kimi-k2-5","messages":[{"role":"user","content":"Hello"}]}' ``` ```python from openai import OpenAI # Point the OpenAI SDK at your local proxy (the proxy forwards to PPQ encrypted) client = OpenAI(base_url="http://127.0.0.1:8787/v1", api_key="unused") response = client.chat.completions.create( model="private/kimi-k2-5", messages=[{"role": "user", "content": "Hello"}], ) print(response.choices[0].message.content) ``` Proxy env vars: `PPQ_API_KEY` (required), `PORT` (default `8787`), `PPQ_API_BASE` (default `https://api.ppq.ai`), `DEBUG`. **Available private model IDs** (fetch latest with `GET /v1/models?type=all` and filter for `private/`): - `private/kimi-k2-5` — Kimi K2.5, native multimodal, strong coding (recommended for agentic / OpenClaw) - `private/deepseek-r1-0528` — DeepSeek R1, reasoning & analysis - `private/gpt-oss-120b` — GPT-OSS 120B, budget-friendly general use - `private/llama3-3-70b` — Llama 3.3 70B, fast / multilingual - `private/qwen3-vl-30b` — Qwen3-VL 30B, vision-language & OCR - `private/glm-5-1`, `private/gemma4-31b` — additional TEE models - `private/kimi-k2-6` — Kimi K2.6, latest Kimi release, native multimodal, strong coding Weights are identical to the standard counterparts; the only difference is the enclave + end-to-end encryption. Each session includes a cryptographic attestation — a proof that the enclave is running the exact code it claims to, on genuine secure hardware. ### Image Generation - `POST https://api.ppq.ai/v1/images/generations` — Generate, edit, upscale, or remove backgrounds on images (synchronous) - `POST https://api.ppq.ai/v1/images/edits` — OpenAI-spec compatibility endpoint for clients like OpenWebUI, LibreChat, and the OpenAI SDKs. Accepts `multipart/form-data` with an `image` file, `prompt`, and `model`. Same response shape and pricing as `/v1/images/generations`. If you're coding directly against PPQ, stay on `/v1/images/generations` with `image_url` instead. - 40+ models from OpenAI (GPT Image), Google (Imagen), Black Forest Labs (Flux, Kontext), xAI (Grok Imagine), ByteDance (SeedDream), Recraft, Qwen, plus upscalers (Clarity, Topaz, Aura SR) and background removal (rembg) - Parameter support **varies per model** — fetch per-model capability badges from `GET https://api.ppq.ai/v1/models?type=image` or browse https://ppq.ai/image-models Request parameters (not every model accepts every field): - `model` (required) — one of the IDs returned by `GET /v1/models?type=image` - `prompt` — text description. Required for generation/edit models; ignored by pure upscalers and background removers. - `image_url` — source image URL. Required for upscalers, background removal, and explicit image-to-image/edit models; optional on many generation models to enable editing or variation. - `n` — number of images, 1–4 (default: 1). Also accepted as `num_images`. - `size` — aspect ratio (e.g. `"1:1"`, `"16:9"`, `"9:16"`). Also accepted as `aspect_ratio`. (Not the OpenAI-style `"1024x1024"`.) - `resolution` — output resolution tier for models that support it (e.g. `"1K"`, `"2K"`, `"4K"`). - `quality` — quality tier; allowed values are model-specific (e.g. `low|medium|high`). - `negative_prompt` — text describing what to avoid. - `output_format` — `"png"`, `"jpeg"`, or `"webp"`. ```bash curl -X POST https://api.ppq.ai/v1/images/generations \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "nano-banana-2", "prompt": "A serene mountain landscape at sunset", "resolution": "1K", "n": 1 }' ``` ```python import requests response = requests.post( "https://api.ppq.ai/v1/images/generations", headers={"Authorization": "Bearer sk-YOUR_API_KEY", "Content-Type": "application/json"}, json={"model": "nano-banana-2", "prompt": "A serene mountain landscape at sunset", "resolution": "1K"} ) data = response.json() print(data["data"][0]["url"]) # Signed URL served by PPQ (valid 24h) ``` Response shape: ```json { "created": 1709234567, "model": "nano-banana-2", "cost": 0.0805, "data": [ { "url": "https://api.ppq.ai/v1/media/gen_abc123/0?sig=...&exp=...", "content_type": "image/png" } ] } ``` `url` is a signed PPQ URL (valid 24h). Download the bytes before expiry for long-term storage. Key image model IDs (flat aliases — no `fal-ai/` prefix): - `nano-banana-2`, `nano-banana-pro`, `nano-banana-2-edit` — Google Gemini image - `gpt-image-1`, `gpt-image-1.5` — OpenAI GPT Image - `imagen3`, `imagen4-preview` — Google Imagen - `flux-2-pro`, `flux-2-flex`, `flux-2-pro-i2i`, `flux-pro` — Black Forest Labs Flux - `flux-kontext-pro`, `flux-kontext-max` — Flux Kontext (editing) - `seedream-4.5`, `seedream-4.5-edit` — ByteDance SeedDream - `qwen-image`, `qwen-image-i2i` — Qwen Image - `recraft-v3`, `recraft-v3-svg` — Recraft (raster + SVG) - `grok-imagine`, `grok-imagine-edit` — xAI Grok Imagine - `kling-o1-image`, `fast-sdxl` — additional generation models - `rembg` — background removal - `clarity-upscaler`, `topaz-upscale`, `aura-sr` — upscalers Always fetch the current list and per-model capabilities with `GET /v1/models?type=image` — models and aliases change regularly. ### Video Generation - `POST https://api.ppq.ai/v1/videos` — Submit a video generation job (async, returns HTTP 202) - `GET https://api.ppq.ai/v1/videos/{id}` — Poll for status and retrieve the result (returns 202 while processing, 200 when done) - 25+ models from Google (Veo), Kling, Runway, Luma, MiniMax (Hailuo), ByteDance (Seedance), xAI (Grok Imagine), and more - Supports both text-to-video and image-to-video (dedicated `-i2v` model variants) Request parameters (support varies per model): - `model` (required) — one of the IDs returned by `GET /v1/models?type=video` - `prompt` (required) — text description of the video - `aspect_ratio` — e.g. `"16:9"`, `"9:16"`, `"1:1"` (default: `"16:9"`) - `duration` — seconds (e.g. `"5"`, `"10"`). Allowed values are model-specific. - `quality` — resolution/quality tier (e.g. `"720p"`, `"1080p"`). Model-specific. - `image_url` — required for image-to-video (`-i2v`) models; a publicly accessible image URL Video generation is **asynchronous**: the POST returns a job ID with HTTP 202 and an `estimated_cost`; poll the GET endpoint every 5–10s until status is `"completed"` or `"failed"`. ```bash # Submit a video generation job curl -X POST https://api.ppq.ai/v1/videos \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "kling-2.1-pro", "prompt": "A golden retriever running on a beach at sunset", "aspect_ratio": "16:9", "duration": "5" }' # 202 response: {"id": "gen_abc123", "model": "kling-2.1-pro", "status": "pending", "created": 1709234567, "estimated_cost": 0.2875} # Poll for completion curl https://api.ppq.ai/v1/videos/gen_abc123 \ -H "Authorization: Bearer sk-YOUR_API_KEY" # 200 when done: {"id": "gen_abc123", "status": "completed", "data": {"url": "https://api.ppq.ai/v1/media/gen_abc123/0?sig=...&exp=...", "content_type": "video/mp4"}, "cost": 0.2875} ``` ```python import requests, time headers = {"Authorization": "Bearer sk-YOUR_API_KEY", "Content-Type": "application/json"} # Submit job resp = requests.post("https://api.ppq.ai/v1/videos", headers=headers, json={"model": "kling-2.1-pro", "prompt": "A golden retriever running on a beach at sunset", "aspect_ratio": "16:9", "duration": "5"}) job = resp.json() # Poll until complete while job["status"] not in ("completed", "failed"): time.sleep(5) job = requests.get(f"https://api.ppq.ai/v1/videos/{job['id']}", headers=headers).json() print(job["data"]["url"]) # Signed PPQ URL to the generated video (valid 24h) ``` Key video model IDs (flat aliases — no `fal-ai/` prefix): Text-to-video: - `veo3`, `veo3-fast` — Google Veo 3 (Quality / Fast), 8s - `kling-2.1-pro`, `kling-2.1-master`, `kling-2.1-standard`, `kling-2.5-turbo`, `kling-3.0` — Kling - `runway-gen4`, `runway-aleph` — Runway - `luma-dream-machine` — Luma - `hailuo-02-pro`, `hailuo-02-standard` — MiniMax Hailuo - `seedance-2`, `seedance-2-fast`, `seedance-v1-lite` — ByteDance Seedance - `grok-imagine-video-t2v` — xAI Grok Imagine Video - `pika-v2.2`, `pixverse-v4.5`, `mochi-v1`, `haiper-video-v2`, `wan-t2v`, `minimax-video`, `kling-o3-standard`, `kling-o3-pro`, `kling-v1-standard` Image-to-video (require `image_url`): - `veo3-i2v`, `veo3-fast-i2v` — Google Veo 3 I2V - `kling-2.1-pro-i2v`, `kling-o3-standard-i2v`, `kling-o3-pro-i2v`, `kling-v1-standard-i2v` - `hailuo-02-pro-i2v`, `hailuo-02-standard-i2v`, `hailuo-02-fast-i2v` - `seedance-2-i2v`, `seedance-2-fast-i2v` - `luma-dream-machine-i2v`, `haiper-video-v2-i2v`, `wan-i2v`, `wan-v2.2-i2v`, `minimax-i2v`, `pika-i2v`, `pika-pikaffects`, `pixverse-i2v` - `grok-imagine-video-i2v`, `grok-imagine-video-v2v` Always fetch the current list and pricing with `GET /v1/models?type=video` — model availability and aliases change regularly. ### Data Enrichment - `GET https://api.ppq.ai/v1/data/endpoints` — List all available data endpoints with pricing (no auth required) - `POST https://api.ppq.ai/v1/data/api/{provider}/{action}` — Call a data enrichment endpoint - `GET https://api.ppq.ai/v1/data/api/{provider}/{action}` — Call a data GET endpoint (e.g. place details) - `GET https://api.ppq.ai/v1/data/x/{path}` — Call an X/Twitter endpoint (all X/Twitter endpoints use the `/v1/data/x/` prefix, not `/v1/data/api/`, and are GET-only) - All enrichment endpoints require `Authorization: Bearer YOUR_API_KEY` - Each call deducts from your PPQ credit balance (endpoint price × markup) Covers people search, company lookup, web scraping, Google Maps, Reddit, email verification, X/Twitter data, and social media enrichment. For full parameter documentation and request/response schemas for each endpoint, see: https://ppq.ai/data-providers Available providers and endpoints. Prices shown are base upstream costs; the actual amount deducted from your PPQ balance includes a billing margin. Call `GET /v1/data/endpoints` for the live final-deduction price per endpoint. | Endpoint | Method | Price (base) | |----------|--------|--------------| | `/v1/data/api/google-maps/text-search/full` | POST | $0.08 | | `/v1/data/api/google-maps/text-search/partial` | POST | $0.02 | | `/v1/data/api/google-maps/nearby-search/full` | POST | $0.08 | | `/v1/data/api/google-maps/nearby-search/partial` | POST | $0.02 | | `/v1/data/api/google-maps/place-details/full` | GET | $0.05 | | `/v1/data/api/google-maps/place-details/partial` | GET | $0.02 | | `/v1/data/api/apollo/people-search` | POST | $0.02 | | `/v1/data/api/apollo/org-search` | POST | $0.02 | | `/v1/data/api/apollo/people-enrich` | POST | $0.0495 | | `/v1/data/api/apollo/org-enrich` | POST | $0.0495 | | `/v1/data/api/exa/search` | POST | $0.01 | | `/v1/data/api/exa/find-similar` | POST | $0.01 | | `/v1/data/api/exa/contents` | POST | $0.002 | | `/v1/data/api/exa/answer` | POST | $0.01 | | `/v1/data/api/firecrawl/scrape` | POST | $0.0126 | | `/v1/data/api/firecrawl/search` | POST | $0.0252 | | `/v1/data/api/clado/contacts-enrich` | POST | $0.20 | | `/v1/data/api/clado/linkedin-scrape` | POST | $0.04 | | `/v1/data/api/serper/news` | POST | $0.04 | | `/v1/data/api/serper/shopping` | POST | $0.04 | | `/v1/data/api/reddit/search` | POST | $0.02 | | `/v1/data/api/reddit/post-comments` | POST | $0.02 | | `/v1/data/api/whitepages/person-search` | POST | $0.44 | | `/v1/data/api/whitepages/property-search` | POST | $0.44 | | `/v1/data/api/hunter/email-verifier` | POST | $0.03 | | `/v1/data/api/influencer/enrich-by-email` | POST | $0.40 | | `/v1/data/api/influencer/enrich-by-social` | POST | $0.40 | | `/v1/data/x/tweets/search` | GET | $0.01 | | `/v1/data/x/tweets/by/id` | GET | $0.01 | | `/v1/data/x/tweets/user` | GET | $0.01 | | `/v1/data/x/tweets/replies` | GET | $0.01 | | `/v1/data/x/tweets/quote_tweets` | GET | $0.01 | | `/v1/data/x/tweets/retweeted_by` | GET | $0.01 | | `/v1/data/x/users/search` | GET | $0.01 | | `/v1/data/x/users/by/id` | GET | $0.01 | | `/v1/data/x/users/by/username` | GET | $0.01 | | `/v1/data/x/users/followers` | GET | $0.01 | | `/v1/data/x/users/following` | GET | $0.01 | | `/v1/data/x/lists/by/id` | GET | $0.01 | ```bash # Discover all endpoints and prices curl https://api.ppq.ai/v1/data/endpoints # Search for people (Apollo) curl -X POST https://api.ppq.ai/v1/data/api/apollo/people-search \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{"q_keywords": "software engineer", "person_locations": ["San Francisco"], "per_page": 5}' # Scrape a web page (Firecrawl) curl -X POST https://api.ppq.ai/v1/data/api/firecrawl/scrape \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{"url": "https://example.com"}' # Semantic web search (Exa) curl -X POST https://api.ppq.ai/v1/data/api/exa/search \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{"query": "AI agent startups 2025", "numResults": 10}' ``` ```python import requests api_key = "sk-YOUR_API_KEY" headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"} # People search via Apollo resp = requests.post( "https://api.ppq.ai/v1/data/api/apollo/people-search", headers=headers, json={"q_keywords": "software engineer", "person_locations": ["San Francisco"], "per_page": 5} ) print(resp.json()) # Enrich a person's profile resp = requests.post( "https://api.ppq.ai/v1/data/api/apollo/people-enrich", headers=headers, json={"email": "tim@apple.com"} ) print(resp.json()) ``` ### Embeddings - `POST https://api.ppq.ai/v1/embeddings` — Generate vector embeddings for text input - OpenAI SDK compatible — use `client.embeddings.create()` with your PPQ API key - Parameters: `model` (required), `input` (required — string or array of strings), `encoding_format` (optional: "float" or "base64"), `dimensions` (optional) - A wide selection of embedding models from major providers is supported. Fetch the current list with `GET /v1/models?type=embedding` ```python from openai import OpenAI client = OpenAI(api_key="sk-YOUR_API_KEY", base_url="https://api.ppq.ai/v1") # Single text response = client.embeddings.create( model="openai/text-embedding-3-small", input="The quick brown fox jumps over the lazy dog" ) print(response.data[0].embedding[:5]) # First 5 dimensions print(f"Total tokens: {response.usage.total_tokens}") # Batch (multiple texts in one request) response = client.embeddings.create( model="openai/text-embedding-3-small", input=["First document", "Second document", "Third document"] ) for item in response.data: print(f"Index {item.index}: {len(item.embedding)} dimensions") ``` ```bash curl -X POST https://api.ppq.ai/v1/embeddings \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "openai/text-embedding-3-small", "input": "The quick brown fox jumps over the lazy dog" }' ``` Key embedding models include: - `openai/text-embedding-3-small` — Fast and affordable (1536 dimensions, supports custom dimensions) - `openai/text-embedding-3-large` — Higher quality (3072 dimensions, supports custom dimensions) ### Models - `GET https://api.ppq.ai/v1/models` — List available models with pricing info - Filter by modality with the `type` query parameter: - `GET /v1/models` — Chat models only (default) - `GET /v1/models?type=image` — Image generation models only - `GET /v1/models?type=video` — Video generation models only - `GET /v1/models?type=image,video` — Image and video models - `GET /v1/models?type=embedding` — Embedding models only - `GET /v1/models?type=all` — All models across all modalities (chat, image, video, audio, embedding) - Filter popular models: `GET /v1/models?popular=true` ### Speech-to-Text (STT) - `POST https://ppq.ai/api/v1/audio/transcriptions` — Transcribe audio to text - Powered by Deepgram Nova-3 - Supported formats: mp3, mp4, mpeg, mpga, m4a, wav, webm (max 25MB) - Models: `nova-3` (default), `nova-2` - Response formats: json, text, srt, vtt, verbose_json - Parameters: `file` (required), `model`, `response_format`, `language` (e.g. "en", "es", "multi" for auto-detect), `prompt` ```python from openai import OpenAI client = OpenAI(api_key="sk-YOUR_API_KEY", base_url="https://ppq.ai/api/v1") with open("audio.mp3", "rb") as f: transcription = client.audio.transcriptions.create( model="nova-3", file=f, response_format="json" ) print(transcription.text) ``` ### Text-to-Speech (TTS) - `POST https://ppq.ai/api/v1/audio/speech` — Convert text to speech - `GET https://ppq.ai/api/v1/audio/voices` — List all available voices - `GET https://ppq.ai/api/v1/audio/voices?language=pt` — Filter voices by ISO 639-1 language code - Powered by DeepGram Aura 2 and ElevenLabs (Multilingual v2, Flash v2.5, v3) - Parameters: `input` (required), `model` (required), `voice` (optional), `language` (optional — ISO 639-1 code e.g. "en", "pt", "es", "fr", "de", "it") - Max input: 2000 characters for DeepGram, 5000 for ElevenLabs - When `language` is provided without `voice`, the API auto-selects a compatible voice. When both are provided, returns 422 if the voice does not support the language. - Fetch available models with `GET https://ppq.ai/api/v1/audio/models` ```python from openai import OpenAI client = OpenAI(api_key="sk-YOUR_API_KEY", base_url="https://ppq.ai/api/v1") # Auto-select voice by language response = client.audio.speech.create( model="deepgram_aura_2", input="Hello, welcome to PayPerQ!", extra_body={"language": "en"} ) response.stream_to_file("output.mp3") # ElevenLabs multilingual response = client.audio.speech.create( model="eleven_multilingual_v2", input="Olá, bem-vindo ao PayPerQ!", extra_body={"language": "pt"} ) response.stream_to_file("output_pt.mp3") ``` ## Models PPQ offers 500+ models from major providers. Fetch the current list with pricing dynamically: ```bash curl https://api.ppq.ai/v1/models ``` Key providers include: - **OpenAI**: GPT-5, GPT-4o, o3, o4-mini - **Anthropic**: Claude Opus 4.6, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Haiku 4.5 - **Google**: Gemini 2.5 Pro, Gemini 2.5 Flash, Gemini 3 Pro - **xAI**: Grok 3, Grok 3 Mini - **Mistral**: Mistral Large, Codestral - **Meta**: Llama 3, Llama 3.1 - **Deepseek**: Deepseek-R1, Deepseek-V3 - **Qwen**: Qwen 3 Model availability and pricing change over time. Always use the `GET /v1/models` endpoint for current information. ## Errors & Status Codes The API returns standard HTTP status codes with JSON error bodies: ```json { "status": "error", "statusCode": 401, "message": "Unauthorized" } ``` Common status codes: - **400** — Bad Request (malformed JSON or invalid parameters) - **401** — Unauthorized (missing or invalid API key) - **402** — Payment Required (insufficient credit balance) - **500** — Internal Server Error There is no explicit rate limiting — usage is controlled by your credit balance. If your balance is insufficient for a request, you'll receive a 402 response. ## Billing & Topups PayPerQ uses a **pay-per-query** model — no subscriptions, no monthly fees. You add credits to your account and each API call deducts from your balance based on the model and token usage. ### Account Management - `POST https://api.ppq.ai/accounts/create` — Create a new account (returns credit_id and api_key) - `POST https://api.ppq.ai/credits/balance` — Check your current balance (body: `{"credit_id": "YOUR_CREDIT_ID"}`) ### Crypto Topup Endpoints All topup endpoints accept `Authorization: Bearer YOUR_API_KEY` and a JSON body with `amount` and `currency`. - `POST https://api.ppq.ai/topup/create/btc-lightning` — Bitcoin Lightning - Currencies: USD, BTC, SATS - USD limits: $0.10–$1,000 | SATS limits: 100–1,000,000 - Expiration: 15 minutes | Bonus: 5% Lightning fee bonus - `POST https://api.ppq.ai/topup/create/btc` — Bitcoin on-chain - Currencies: USD, BTC - USD limits: $10–$10,000 - Expiration: 60 minutes - `POST https://api.ppq.ai/topup/create/ltc` — Litecoin - Currencies: USD, LTC - USD limits: $2–$1,000 - Expiration: 60 minutes - `POST https://api.ppq.ai/topup/create/lbtc` — Liquid Bitcoin - Currencies: USD, LBTC - USD limits: $2–$10,000 - Expiration: 60 minutes - `POST https://api.ppq.ai/topup/create/xmr` — Monero - Currencies: USD, XMR - USD limits: $5–$10,000 - Expiration: 60 minutes ### Topup Utilities - `GET https://api.ppq.ai/topup/status/{invoice_id}` — Check invoice payment status - `GET https://api.ppq.ai/topup/payment-methods` — List all supported payment methods with limits ### NWC Auto-Topup (Nostr Wallet Connect) Connect a Nostr Wallet Connect (NWC) compatible Lightning wallet to automatically top up your balance when it falls below a threshold. Compatible wallets include Alby Hub, LNBits, Primal, and others. All NWC endpoints require `Authorization: Bearer YOUR_API_KEY` and `x-credit-id: YOUR_CREDIT_ID` headers. - `POST https://api.ppq.ai/nwc-auto-topup/connect` — Connect an NWC wallet for automatic top-ups - Parameters: `nwc_url` (required), `threshold_usd` (optional, default: 10, min: 5), `topup_amount_usd` (optional, default: 10) - Wallet must support the `pay_invoice` NIP-47 capability - `GET https://api.ppq.ai/nwc-auto-topup` — Get current NWC auto-topup settings - `DELETE https://api.ppq.ai/nwc-auto-topup/connection` — Disconnect wallet and disable auto-topup ### Query History Retrieve a paginated log of past queries for your account. - `GET https://api.ppq.ai/queries/history` — Get query history Auth: `Authorization: Bearer YOUR_API_KEY`, `api-key: YOUR_API_KEY` header, or `?credit_id=YOUR_CREDIT_ID` query param. When authenticated via API key, results are scoped to that key by default. Pass `all_keys=true` to see all queries on the account. Query parameters: - `page` — Page number (default: 1) - `page_count` — Results per page, max 100 (default: 20) - `start_date` / `end_date` — ISO 8601 timestamps for date range filtering - `model` — Filter by model name - `query_source` / `query_type` — Filter by source or type - `all_keys=true` — When authed via API key, include all keys on the account - `api_key` — When authed via credit_id, filter to a specific API key string Response fields per record: `timestamp`, `model`, `input_count`, `output_count`, `price_in_usd`, `query_type`, `query_source`, `api_key_id`, `isOnline`, `isFreeModel`. Response also includes a `pagination` object with `page`, `page_count`, `total`, `total_pages`. ### API Key Management Manage keys programmatically — create, list, update, and revoke API keys, with optional spending caps, auto-reset periods, and expirations. **Auth**: All API-key endpoints require the `x-credit-id: YOUR_CREDIT_ID` header (not a bearer token — these are account-level operations). Base URL: `https://api.ppq.ai`. - `GET /keys` — List all API keys on the account - Query: `include_disabled` (default `false`), `show_key` (default `false` — include the full `api_key` value) - `POST /keys` — Create a new key. Response includes the full `api_key` **once** — store it securely. - Body: `name` (required, 1–25 chars, unique per account), `usage_limit_usd` (optional, min $0.01, `null` for unlimited), `reset_period` (`"daily"` | `"weekly"` | `"monthly"` — requires `usage_limit_usd`), `expire_at` (ISO 8601, must be future) - `GET /keys/{id}` — Get a single key by MongoDB `_id`. Query: `show_key` (default `false`) - `PATCH /keys/{id}` — Update `name`, `usage_limit_usd`, `reset_period`, or `expire_at`. Pass `null` to clear a field. Changing `reset_period` resets `current_period_usage_usd` to $0. - `DELETE /keys/{id}` — Revoke the key (soft-delete, immediate, not reversible) Key fields returned: `_id`, `name`, `api_key` (only when `show_key=true` or on create), `usage_limit_usd`, `current_period_usage_usd`, `total_usage_all_time_usd`, `reset_period`, `reset_at`, `expire_at`, `created_at`, `updated_at`, `deleted_at`. ```bash # List keys curl https://api.ppq.ai/keys \ -H "x-credit-id: YOUR_CREDIT_ID" # Create a monthly $25-cap key that expires Jan 1, 2027 curl -X POST https://api.ppq.ai/keys \ -H "Content-Type: application/json" \ -H "x-credit-id: YOUR_CREDIT_ID" \ -d '{ "name": "prod-agent", "usage_limit_usd": 25, "reset_period": "monthly", "expire_at": "2027-01-01T00:00:00Z" }' # Revoke curl -X DELETE https://api.ppq.ai/keys/KEY_ID \ -H "x-credit-id: YOUR_CREDIT_ID" ``` ### Example: Create a Lightning topup ```bash curl -X POST https://api.ppq.ai/topup/create/btc-lightning \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount": 1000, "currency": "SATS"}' ``` Fiat payments (credit/debit card) are also available via Stripe on the website at https://ppq.ai. ## 402 Payments (L402 / Lightning) PPQ supports **HTTP 402 Payment Required** for pay-per-request access — no account or API key needed. Currently implemented via **L402** (Bitcoin Lightning). ### How it works 1. Send a request to any 402-enabled endpoint **without** an `Authorization` header. 2. The server responds `402 Payment Required` with a `WWW-Authenticate: Payment` header containing a challenge and a Lightning invoice. 3. Pay the Lightning invoice with any Lightning wallet. 4. Replay the original request with the payment credential: `Authorization: L402 :`. The server verifies and returns the data. 402-compatible clients like [`lnget`](https://github.com/lightninglabs/lnget) and [`mppx`](https://github.com/wevm/mppx) automate the challenge–pay–replay loop. ### Supported endpoints | Category | Endpoint | Method | Pricing | |----------|----------|--------|---------| | Data Enrichment | `/v1/data/api/*` | GET / POST | Fixed per-endpoint (see [Data Enrichment](#data-enrichment)) | | Data Enrichment (X/Twitter) | `/v1/data/x/*` | GET | Fixed per-endpoint (see [Data Enrichment](#data-enrichment)) | | Image Generation | `/v1/images/generations` | POST | Varies by model, size, quality | | Image Editing (OpenAI-spec) | `/v1/images/edits` | POST | Same as image generation | | Video Generation | `/v1/videos` | POST | Varies by model, duration, resolution | ### Example: Data enrichment (curl) ```bash # 1. Request without auth — get a 402 challenge with a Lightning invoice curl -i -X POST https://api.ppq.ai/v1/data/api/apollo/people-search \ -H "Content-Type: application/json" \ -d '{"q_keywords": "software engineer", "per_page": 5}' # Response: 402 Payment Required # WWW-Authenticate: Payment id="...", method="lightning", ... # 2. Pay the invoice, then replay with the payment credential curl -X POST https://api.ppq.ai/v1/data/api/apollo/people-search \ -H "Content-Type: application/json" \ -H "Authorization: L402 :" \ -d '{"q_keywords": "software engineer", "per_page": 5}' ``` ### Example: Image generation (lnget) ```bash # lnget handles the 402 challenge and Lightning payment automatically lnget -X POST \ -d '{"model": "gpt-image-1", "prompt": "a sunset over mountains", "size": "1:1"}' \ --content-type application/json \ --max-cost 500 \ https://api.ppq.ai/v1/images/generations ``` ### Example: Video generation (lnget) ```bash # Submit a video generation job — returns 202 with a signed status URL lnget -X POST \ -d '{"model": "kling-2.1-standard", "prompt": "ocean waves at sunset", "duration": "5", "aspect_ratio": "16:9", "quality": "720p"}' \ --content-type application/json \ --max-cost 500 \ https://api.ppq.ai/v1/videos # Poll the status_url from the response (no auth needed — the URL is signed) lnget "" ``` ### Notes - For **video generation**, the 202 response includes a `status_url` — a signed URL you can poll without authentication until the video is ready. - For **image generation**, the response includes signed media URLs that can be fetched without authentication. - All signed URLs expire after 24 hours. - If you have a PPQ API key, you can still use it via `Authorization: Bearer sk-...` — the 402 flow is only triggered when no API key is provided. ## Important Notes - **Different base URLs**: Chat, Image, Video, and Embeddings APIs use `https://api.ppq.ai`; audio APIs (STT/TTS) use `https://ppq.ai/api/v1` - **OpenAI SDK compatibility**: Set `base_url="https://api.ppq.ai/v1"` for chat/images/embeddings, `base_url="https://ppq.ai/api/v1"` for audio - **Async video generation**: Video generation is asynchronous — submit a job, then poll for completion. Images are synchronous. - **Dynamic model list**: Always fetch available models from `/v1/models` rather than hardcoding — models are added and updated regularly - **Streaming**: Chat completions support `"stream": true` for SSE streaming responses ## Documentation - [API Documentation](https://ppq.ai/api-docs): Full interactive API docs with code examples - [Image Models Reference](https://ppq.ai/image-models): All image models with per-model capability badges (prompt, image_url, quality, resolution, etc.) and code examples - [Data Enrichment Reference](https://ppq.ai/data-providers): Full parameter docs for all 39 data enrichment endpoints - [Blog](https://ppq.ai/blog): Additional guides and announcements ## Integration Guides - [Claude Code](https://ppq.ai/blog/using-claude-code-with-payperq) - [OpenCode](https://ppq.ai/blog/using-opencode-with-payperq) - [Cursor](https://ppq.ai/blog/using-cursor-with-payperq) - [Cline](https://ppq.ai/blog/using-cline-with-payperq) - [Aider](https://ppq.ai/blog/using-aider-with-payperq) - [Roo](https://ppq.ai/blog/using-roo-with-payperq) - [OpenWebUI](https://ppq.ai/blog/using-openwebui-with-payperq) - [Goose](https://ppq.ai/blog/using-goose-with-payperq)