{
	"openai": {
		"label": "OpenAI",
		"api_base": "https://api.openai.com/v1",
		"models_path": "/models",
		"chat_path": "/chat/completions",
		"adapter": "openai_compatible",
		"auth": "bearer",
		"extra_headers": {},
		"key_optional": false,
		"key_prefix": "sk-",
		"max_tokens_param": "max_completion_tokens",
		"key_url": "https://platform.openai.com/api-keys",
		"billing_url": "https://platform.openai.com/settings/organization/billing/overview",
		"status_url": "https://status.openai.com/",
		"terms_url": "https://openai.com/policies/services-agreement/",
		"privacy_url": "https://openai.com/policies/privacy-policy/",
		"structured_output": "json_schema",
		"structured_output_param": "response_format",
		"models_public": false,
		"error_notes": "Body {error:{message,type,param,code}}. Invalid key: 401 type=invalid_request_error code=invalid_api_key ('Incorrect API key provided'); no key: 401 'Missing bearer authentication in header', code=null. Billing: 429 code=credit_balance_exhausted | organization_spend_limit_exceeded | project_spend_limit_exceeded | organization_usage_limit_exceeded (type may be insufficient_quota) - do NOT retry, switch on error.code not the status. Rate limit: 429 type=rate_limit_error (code slow_down when ramping too fast), honour Retry-After. Overload: 503 type=service_unavailable_error code=server_is_overloaded; 500 server error. 403 = unsupported country/region. max_tokens is deprecated in favour of max_completion_tokens and incompatible with o-series.",
		"images": true,
		"images_path": "/images/generations",
		"embeddings": true,
		"embeddings_dimensions": true
	},
	"anthropic": {
		"label": "Anthropic (Claude)",
		"api_base": "https://api.anthropic.com/v1",
		"models_path": "/models",
		"chat_path": "/messages",
		"adapter": "anthropic",
		"auth": "x-api-key",
		"extra_headers": {
			"anthropic-version": "2023-06-01"
		},
		"key_optional": false,
		"key_prefix": "sk-ant-",
		"max_tokens_param": "max_tokens",
		"key_url": "https://platform.claude.com/settings/keys",
		"billing_url": "https://platform.claude.com/settings/billing",
		"status_url": "https://status.claude.com/",
		"terms_url": "https://www.anthropic.com/legal/commercial-terms",
		"privacy_url": "https://www.anthropic.com/legal/privacy",
		"structured_output": "json_schema",
		"structured_output_param": "output_config.format",
		"models_public": false,
		"error_notes": "Body {type:'error',error:{type,message},request_id}. Invalid key: 401 authentication_error ('API key is invalid.'; missing: 'x-api-key header is required'). Billing: 402 billing_error; a customer-set org/workspace spend limit returns 400 invalid_request_error; a usage-tier monthly spend cap returns 429 rate_limit_error WITHOUT retry-after and keeps failing until access resumes. Permission: 403 permission_error. Rate limit: 429 rate_limit_error (retry-after). Overload: 529 overloaded_error; 500 api_error; 504 timeout_error. Structured output is output_config.format {type:'json_schema',schema} (GA, no beta header); forced tool use (tool_choice any/tool) is REFUSED with 400 by claude-opus-5-5 and claude-fable-5-1, so do not use the tool_use trick on current models. max_tokens is required."
	},
	"gemini": {
		"label": "Google Gemini",
		"api_base": "https://generativelanguage.googleapis.com/v1beta",
		"models_path": "/models",
		"chat_path": "/models/{model}:generateContent",
		"adapter": "gemini",
		"auth": "x-goog-api-key",
		"extra_headers": {},
		"key_optional": false,
		"key_prefix": "",
		"max_tokens_param": "maxOutputTokens",
		"schema_field": "responseJsonSchema",
		"key_url": "https://aistudio.google.com/app/apikey",
		"billing_url": "https://aistudio.google.com/app/plan_information",
		"status_url": "https://aistudio.google.com/status",
		"terms_url": "https://ai.google.dev/gemini-api/terms",
		"privacy_url": "https://policies.google.com/privacy",
		"structured_output": "response_schema",
		"structured_output_param": "generationConfig.responseJsonSchema (+ responseMimeType 'application/json')",
		"models_public": false,
		"error_notes": "Body {error:{code,message,status,details[]}}. Invalid key on generateContent/models: HTTP 400 status=INVALID_ARGUMENT with details[].reason=API_KEY_INVALID (NOT 401) - match on reason. No key: 403 PERMISSION_DENIED 'unregistered callers'. Docs table: 401 authentication, 402 payment_required = Prepay credit balance depleted (do not retry), 400 failed_precondition = e.g. billing disabled, 403 permission_denied. Rate/quota: 429 RESOURCE_EXHAUSTED (rate_limit_exceeded per-minute, quota_exceeded daily). Overload/outage: 503 UNAVAILABLE (service_unavailable), 500 INTERNAL, 504 DEADLINE_EXCEEDED. Model list names are prefixed 'models/' and paginate (pageSize, nextPageToken). maxOutputTokens goes inside generationConfig. responseSchema (OpenAPI subset) is marked deprecated in the API reference; responseJsonSchema accepts standard JSON Schema; a newer generationConfig.responseFormat.text {mimeType, schema} also exists.",
		"images": true,
		"embeddings": true
	},
	"mistral": {
		"label": "Mistral AI",
		"api_base": "https://api.mistral.ai/v1",
		"models_path": "/models",
		"chat_path": "/chat/completions",
		"adapter": "openai_compatible",
		"auth": "bearer",
		"extra_headers": {},
		"key_optional": false,
		"key_prefix": "",
		"max_tokens_param": "max_tokens",
		"key_url": "https://console.mistral.ai/api-keys",
		"billing_url": "https://console.mistral.ai/billing",
		"status_url": "https://status.mistral.ai/",
		"terms_url": "https://legal.mistral.ai/terms/commercial-terms-of-service/",
		"privacy_url": "https://legal.mistral.ai/terms/privacy-policy/",
		"structured_output": "json_schema",
		"structured_output_param": "response_format",
		"models_public": false,
		"error_notes": "Invalid or missing key: 401 body {\"detail\":\"Invalid API Key\"} (measured - FastAPI-style, NOT the OpenAI {error:{}} envelope). Mistral publishes no per-status error table in its API reference (measured 2026-09-25); treat 402/429 as billing/rate, 5xx as outage, and parse both {detail} and {message} shapes. response_format supports {type:'json_object'} and {type:'json_schema'}.",
		"embeddings": true
	},
	"deepseek": {
		"label": "DeepSeek",
		"api_base": "https://api.deepseek.com",
		"models_path": "/models",
		"chat_path": "/chat/completions",
		"adapter": "openai_compatible",
		"auth": "bearer",
		"extra_headers": {},
		"key_optional": false,
		"key_prefix": "",
		"max_tokens_param": "max_tokens",
		"key_url": "https://platform.deepseek.com/api_keys",
		"billing_url": "https://platform.deepseek.com/top_up",
		"status_url": "https://status.deepseek.com/",
		"terms_url": "https://cdn.deepseek.com/policies/en-US/deepseek-open-platform-terms-of-service.html",
		"privacy_url": "https://cdn.deepseek.com/policies/en-US/deepseek-privacy-policy.html",
		"structured_output": "json_object",
		"structured_output_param": "response_format",
		"models_public": false,
		"error_notes": "Invalid key: 401 'Authentication Fails' - JSON {error:{message,type:'authentication_error',code:'invalid_request_error'}} with a key; plain-text body 'Authentication Fails (governor)' with no key (measured). 402 Insufficient Balance (top up). 400 invalid format, 422 invalid parameters. Rate limit: 429. Overload: 503 Server Overloaded; 500 server error. JSON mode only (response_format {type:'json_object'}), no schema-constrained output. Also serves an Anthropic-format API at https://api.deepseek.com/anthropic. Prices have peak (Mon-Fri 01-04 & 06-10 UTC) and off-peak (half) rates."
	},
	"openrouter": {
		"label": "OpenRouter",
		"api_base": "https://openrouter.ai/api/v1",
		"models_path": "/models",
		"chat_path": "/chat/completions",
		"adapter": "openai_compatible",
		"auth": "bearer",
		"extra_headers": {},
		"key_optional": false,
		"key_prefix": "",
		"max_tokens_param": "max_tokens",
		"key_url": "https://openrouter.ai/settings/keys",
		"billing_url": "https://openrouter.ai/settings/credits",
		"status_url": "https://status.openrouter.ai/",
		"terms_url": "https://openrouter.ai/terms",
		"privacy_url": "https://openrouter.ai/privacy",
		"structured_output": "json_schema",
		"structured_output_param": "response_format",
		"models_public": true,
		"error_notes": "Body {error:{code,message,metadata?}}. Invalid key: 401 (measured body {\"error\":{\"message\":\"User not found.\",\"code\":401}}). 402 insufficient credits (without Retry-After = not a wait-and-retry case). 403 forbidden/guardrail/moderation. 408 timeout. 429 rate limited (Retry-After may be present). 502 chosen model down / invalid upstream response; 503 no provider meets routing requirements. error.metadata.error_type carries a typed code (e.g. payment_required) and provider_code the upstream code (omitted on 5xx). /models is public (200 without a key); use GET /key to validate a key.",
		"embeddings": true,
		"embeddings_models_path": "/embeddings/models"
	},
	"custom": {
		"label": "Custom (OpenAI-compatible)",
		"api_base": "http://localhost:11434/v1",
		"models_path": "/models",
		"chat_path": "/chat/completions",
		"adapter": "openai_compatible",
		"auth": "none-or-bearer",
		"extra_headers": {},
		"key_optional": true,
		"key_prefix": "",
		"max_tokens_param": "max_tokens",
		"api_base_examples": {
			"ollama": "http://localhost:11434/v1",
			"lm_studio": "http://localhost:1234/v1"
		},
		"key_url": "",
		"billing_url": "",
		"status_url": "",
		"terms_url": "",
		"privacy_url": "",
		"structured_output": "json_object",
		"structured_output_param": "response_format",
		"models_public": true,
		"error_notes": "Server-dependent. Ollama's OpenAI-compatible API ignores the key (docs: api_key 'required but ignored') and supports /v1/models and response_format; LM Studio serves GET /v1/models and /v1/chat/completions on port 1234. Treat connection refused/timeout as 'server not running' rather than an outage; json_object is the conservative default - json_schema support varies by server and model.",
		"embeddings": true
	}
}
