API reference
Generate structured site specs and run OpenAI-compatible chat completions over HTTP.
Authentication
Every request carries an API key as a bearer token. Create keys under Dashboard → API keys; the full key is shown once at creation and only its prefix and last four digits are stored afterwards. For per-application instructions — Claude Code, Codex, Cursor and the rest — see Setup.
Authorization: Bearer sk_live_YOUR_API_KEY_HERE
A missing or unrecognised key returns unauthorized. A valid key without the required scope returns forbidden. Send keys from a server you control — never from a browser.
POST /v1/generate
Requests must be Content-Type: application/json. The body is strict: unknown keys are rejected rather than ignored, and no string may contain < or >.
{
"brief": "A neighbourhood bakery in Portland serving sourdough…",
"targetPages": ["home", "about", "menu"],
"maxRounds": 2
}The model and channel are chosen server-side from your plan and the platform's channel health; there is no model override. Requires the generate scope.
200 response
spec.theme.fontPairing is one of inter-inter, playfair-inter, dm-serif-dm-sans, space-grotesk-ibm-plex-sans, lora-source-sans, poppins-work-sans; spec.theme.tone is one of professional, friendly, bold, minimal, playful. A spec holds 1–8 pages, each with 1–12 sections drawn from hero, features, about, testimonials, pricing, faq, contact, cta, and gallery.
{
"spec": {
"businessName": "Grain & Gather Bakery",
"tagline": "Handcrafted sourdough in the heart of Portland",
"theme": {
"primaryColor": "#8B4513",
"accentColor": "#D2691E",
"fontPairing": "serif-clean",
"tone": "warm"
},
"pages": [
{
"slug": "home",
"title": "Home",
"sections": [
{ "type": "hero", "heading": "Fresh bread…", "subheading": "…", "ctaText": "…" },
{ "type": "features", "heading": "…", "items": […] }
]
}
]
},
"usage": {
"input_tokens": 512,
"output_tokens": 1843,
"cached_tokens": 0
},
"credits_charged": 42,
"balance_after": 9958,
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}credits_charged is the settled amount for this call and balance_after your remaining balance. Both are also written to your usage and ledger history.
POST /v1/chat/completions
OpenAI-compatible chat completions. Requests must be Content-Type: application/json. Requires the chat scope.
{
"model": "gemini-2.0-flash-exp",
"messages": [
{"role": "user", "content": "What is the capital of France?"}
],
"max_tokens": 100
}The model field selects from models your plan permits. Use GET /v1/models for the full list. Streaming responses are not yet supported.
200 response
{
"id": "chatcmpl-550e8400-e29b-41d4-a716-446655440000",
"object": "chat.completion",
"created": 1640995200,
"model": "gemini-2.0-flash-exp",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The capital of France is Paris."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 8,
"total_tokens": 20
}
}Unlike /v1/generate, credits charged and balance are not returned in the body. Check your usage dashboard for billing details.
Endpoint types
Chat models are reachable through three wire formats over the same channels and the same billing: POST /v1/chat/completions, POST /v1/responses, and POST /v1/messages — the Anthropic Messages API, which Claude Code and the Anthropic SDKs speak, and which accepts an x-api-key header as well as a bearer token. Which format you send is independent of what a model runs on upstream. Other endpoint labels on the prices page describe provider capabilities; this gateway currently exposes chat and site generation, and a listed capability does not create an additional gateway endpoint. Request-priced capabilities will be billed per completed job rather than per token when they are enabled. They are separate from the chat routes, which route only token-priced channels.
Media endpoints
Image and video generation are currently unavailable. The safety gate returns 503 channel_unavailable for POST /v1/images, POST /v1/videos, and the dashboard media action while output moderation and provider checks are being completed. These endpoints will be documented here again after generated outputs are screened and the full flow has passed verification.
Chat and site generation remain available through the endpoints documented above. Do not build a paid integration against the media routes until the availability status changes.
GET /v1/models
Lists models available to your plan. Each model has an id (the public model name you pass in chat completion requests), object: "model", and an owned_by string. Requires the chat scope.
When known, context_window reports the model's capacity in tokens.gensite-v1 supports up to 1,000,000 tokens when a suitable model is available to your plan. Large conversations move to models with enough room for the conversation and the requested answer. The returned capacity can be lower when those models are unavailable; output limits and credits still apply.
{
"object": "list",
"data": [
{
"id": "gemini-2.0-flash-exp",
"object": "model",
"created": 1640995200,
"owned_by": "system"
}
]
}Idempotency
Idempotency-Key is required on /v1/generate and optional on /v1/chat/completions — at most 200 characters, and unique per logical request (a UUID works). If absent on chat completions, a server-generated UUID is used.
- Replaying a key with the same body returns the original stored response and charges nothing more.
- Reusing a key with a different body returns
idempotency_conflict. - A request still in flight under that key also returns
idempotency_conflict; retry after the first one settles.
This makes retries after a timeout safe: reuse the same key and you either get the original result or a conflict, never a second charge.
Errors
Every non-2xx response uses one shape. Log the request id — it identifies the call in your usage history and in support requests.
{
"error": {
"code": "insufficient_credits",
"message": "insufficient credits: need 50, balance 12",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}| Code | HTTP | Meaning |
|---|---|---|
| unauthorized | 401 | Missing, malformed, or revoked API key. |
| forbidden | 403 | The key is valid but lacks the required scope. |
| invalid_request | 400 | Body failed validation. The message names the field. |
| rate_limited | 429 | Per-key requests-per-minute exceeded. See Retry-After. |
| insufficient_credits | 402 | Balance too low to cover the estimated cost. |
| idempotency_conflict | 409 | The key is in use by another request or was used for a different body. |
| channel_unavailable | 503 | No healthy channel for your plan right now. |
| generation_failed | 502 | The model returned nothing valid after retries. |
| not_found | 404 | No such resource. |
| model_not_found | 404 | Unknown model, or one your plan cannot use. |
| not_ready | ||
| content_policy_violation | 400 | Prompt was flagged by content moderation. |
| context_length_exceeded | 400 | The conversation is longer than the model's context window. Shorten or compact it. |
| internal_error | 500 | Unexpected server fault. Safe to retry. |
Rate limits
Limits are per API key, measured in requests per minute, and set by your plan. Exceeding one returns rate_limited with HTTP 429 and a Retry-After header giving whole seconds to wait.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
{"error":{"code":"rate_limited","message":"Rate limit exceeded.","request_id":"…"}}Honour Retry-After rather than retrying immediately. Rate-limited calls are rejected before any model call, so they cost no credits.
Credits
Usage is billed in credits, where 1 credit = $0.0001 of provider cost (10,000 credits = $1.00). A call computes provider cost from input, output, and cached tokens, multiplies by the channel's credit multiplier, and rounds up to the next whole credit.
- Credits are held on an estimate before generation and settled to the actual amount afterwards; a failed generation releases the hold.
- Too low a balance returns
insufficient_creditsbefore any model call. - Channels on a zero multiplier — including BYOK channels using your own provider key — charge 0 credits.
Balance, plan, and per-request charges are visible under Dashboard → Usage.
Example
curl -sS -X POST https://gensite.tech/v1/generate \
-H "Authorization: Bearer sk_live_YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"brief": "A neighbourhood bakery in Portland serving sourdough…",
"targetPages": ["home", "about", "menu"],
"maxRounds": 2
}'