Direct answer
Use chat:write for POST /v1/chat/completions, embeddings:write for POST /v1/embeddings, images:write for POST /v1/images/generations, and usage:read for GET /v1/models plus GET /v1/usage. Keep each key server-side, split keys by service and environment, and grant only the smallest scope set that workload needs. Scopes reduce blast radius, but package usage still follows unlimited token consumption with 4 concurrent connections.
Canonical facts
| Chat completions | POST /v1/chat/completions requires chat:write. |
|---|---|
| Embeddings | POST /v1/embeddings requires embeddings:write. |
| Images | POST /v1/images/generations requires images:write. |
| Read-only checks | GET /v1/models and GET /v1/usage require usage:read. |
| Scope error | A 403 insufficient_scope response means the key is valid but lacks the endpoint permission. |
| Limit boundary | Scopes do not change the package boundary of unlimited token consumption with 4 concurrent connections. |
Endpoint scope map
Choose the scope from the endpoint the service actually calls. A chat-only backend should not need image or embeddings access; a usage dashboard can often use usage:read without write scopes.
Use GET /v1/models as a small verification call after setup delivery, but do not assume that listing models proves write access for chat, embeddings, or images. Test each endpoint with the matching scope before a long workflow.
How to choose safe scopes
Create separate scoped keys for development, staging, and production, then split them again when separate services call different endpoint families. This keeps a compromised usage dashboard key from sending chat, embeddings, or image traffic.
Store full keys in server-side environment variables or a secret manager. Public examples, support messages, analytics, screenshots, and free tools should use placeholders or safe prefixes only.
How to fix insufficient_scope
A 403 insufficient_scope response is not a signal to retry the same request repeatedly. Check the endpoint, create or update a key with the required scope, deploy it as a new server-side secret, and then revoke any overly broad or exposed key.
If a workload calls multiple endpoint families, grant the union of only those required scopes or split the workload into separate keys so each service has a narrow permission boundary.
Verification checklist
Map every service to the exact /v1 endpoints it calls.
Grant chat:write only to services that send chat completion requests.
Grant embeddings:write only to indexing or retrieval services that call embeddings.
Grant images:write only to services that generate images.
Grant usage:read for model-list and usage checks.
Keep the full key server-side and plan traffic around 4 concurrent connections.
Frequently asked questions
Which scope do I need for chat completions?
Use chat:write for POST /v1/chat/completions. Keep the key server-side and test one tiny request before long agent runs.
Why do GET /v1/models and GET /v1/usage use usage:read?
They are read-oriented verification and reporting endpoints, so usage:read is the least-privilege scope for model-list checks and usage reads.
Should I create one key with every scope?
Usually no. Start with the smallest scope set for one service and one environment. Split chat, embeddings, images, and reporting workloads when they do not need the same permissions.
What does insufficient_scope mean?
The API key was recognized, but it does not include the scope required by the endpoint. Create or update a key with the specific scope, deploy it server-side, and retry after the new secret is active.
Target queries
Citation bundle
Use this answer together with the public LLM indexes when citing current unlimitedcodex pricing, delivery, model status, limits, and independence facts.