Set a model key
Send key, use, or both. Saving a key without use sets use: project. The provider is asked one read-only question (list models) first: a refusal is 400 invalid_model_key; if the provider cannot be reached the key is saved with verified: false. use: project needs a saved key (400); use: platform needs the plan feature platformModels (402 feature_not_in_plan) and keeps the saved key. Runs on the project's own key have no model charge from Boxline. 10 writes a minute per project (429). Every change is logged, never with a value.
/v1/project/model-keys/{provider}Request
| Method and path | PUT/v1/project/model-keys/{provider} |
|---|---|
| Base URL | https://api.boxline.dev |
| Authentication | Your API key in the x-api-key header (or Authorization: Bearer). The examples read it from BOXLINE_API_KEY. |
| Rate limit | Yes. See Rate limits for the numbers and headers. |
Path parameters
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
providerrequired | string | – | anthropic, openai, xai, google | Anthropic Claude, OpenAI, Grok (xAI), Google Gemini. Grok and Gemini have no computer use (mode computer is 400). |
Body
JSON with content-type: application/json. Required.
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
key | string | – | – | The provider's API key (no spaces or control characters). Write-only. 20 to 400 characters. |
use | string | – | project, platform | Whose key a model call uses, the project's own (project, no model charge from Boxline) or the platform's. |
curl -X PUT "https://api.boxline.dev/v1/project/model-keys/$MODEL_KEY_ID" \ -H "x-api-key: $BOXLINE_API_KEY" \ -H "content-type: application/json" \ -d '{"key": "sk-proj-…"}'import { Boxline } from "@boxline/sdk";const bx = new Boxline(); // reads BOXLINE_API_KEY and BOXLINE_API_URLconst item = await bx.project.setModelKey("openai", { key: process.env.OPENAI_API_KEY! });console.log(item.use, item.preview, item.verified);from boxline import Boxlinebx = Boxline() # reads BOXLINE_API_KEY and BOXLINE_API_URLitem = bx.project.set_model_key("openai", key=os.environ["OPENAI_API_KEY"])print(item["use"], item["preview"], item["verified"])Responses
200 OK
The provider's item now.
Fields
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
provider | string | – | anthropic, openai, xai, google | Anthropic Claude, OpenAI, Grok (xAI), Google Gemini. Grok and Gemini have no computer use (mode computer is 400). |
use | string | – | project, platform | Whose key a model call uses, the project's own (project, no model charge from Boxline) or the platform's. |
useEffective | string | – | project, platform | Whose key a model call uses, the project's own (project, no model charge from Boxline) or the platform's. |
hasKey | boolean | – | – | |
preview | string | null | – | – | The last 4 characters of the key. |
verified | boolean | null | – | – | The provider accepted the key when it was saved (false: it could not be reached). |
createdAt | string | null | – | – | Format: date-time. |
updatedAt | string | null | – | – | Format: date-time. |
updatedVia | string | null | – | console, api_key, support, null | |
lastUsedAt | string | null | – | – | Format: date-time. |
platformAvailable | boolean | – | – | The server holds a key for the provider and the plan includes platformModels. |
{ "provider": "anthropic", "use": "project", "useEffective": "project", "hasKey": false, "preview": "…", "verified": false, "createdAt": "2026-09-29T10:00:00.000Z", "updatedAt": "2026-09-29T10:00:00.000Z", "updatedVia": "console", "lastUsedAt": "2026-09-29T10:00:00.000Z", "platformAvailable": false}Errors
Errors have a matching HTTP status and the same body. code is stable, so check it in your code; message is for people. See Errors and request ids.
| Status | Codes | When |
|---|---|---|
| 400 Bad Request | invalid_request, invalid_json, invalid_cursor, invalid_idempotency_key, invalid_extension, variables_with_extensions, terms_not_accepted, invalid_reset_token, invalid_confirmation_code, wrong_password, no_password, invalid_next, invalid_oauth_token | The request is not valid. |
| 401 Unauthorized | unauthorized | Missing or invalid API key. |
| 402 Payment Required | feature_not_in_plan, spend_limit, out_of_credit, plan_limit, spend_limit, out_of_credit, organization, project, plan, credit | The plan does not include this, a monthly allowance or spending limit is used up, the organization has no credit left, or the plan allows no more of this. spend_limit and out_of_credit carry error.details.limit: organization, project, plan or credit. |
| 429 Too Many Requests | rate_limited, concurrency_limit | Too many requests, or the organization's concurrent sessions (its plan's) or the project's concurrencyCap are in use. |
{ "error": { "code": "not_found", "message": "session not found", "requestId": "req_4fJx0aQm2Lk9Pz7N" }}Learn more
These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.