Items API
Manage items: the specific resources or vendor models within your services.
Create Item
POST /api/v1/items
Request:
{
"name": "GPT-4 Turbo",
"id": "GPT-4-TURBO",
"service_id": "123"
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name. Max 64 characters. |
id | string | Yes | Alphanumeric identifier used in charging requests. Letters, digits, dashes, underscores only. Max 16 characters. |
service_id | string | No | Scope the item to this service. |
is_global | boolean | No | true makes the item available to every service. Send this rather than relying on omitting service_id. |
Response:
{
"id": "GPT-4-TURBO",
"name": "GPT-4 Turbo",
"service_id": "123",
"is_global": false
}
The response describes the item's identity and service scope as saved, so service_id and
is_global match what GET /api/v1/items/{item_id} returns for the same item.
One thing to know:
- Scope is set by
is_global. An item created with neitherservice_idnoris_globalis stored as scoped to no service (is_global: false) and will not appear under any service filter.
List Items
GET /api/v1/items
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
service_id | string | Filter items by service |
Get Item
GET /api/v1/items/{item_id}
An item ID is matched without regard to case, so gpt-4-turbo reaches the item stored as
GPT-4-TURBO. Update Item and Delete Item match it the same way, and every answer carries the ID as
it was stored rather than the casing you sent. Creating a second item whose ID differs only in case
is still refused.
Update Item
PATCH /api/v1/items/{item_id}
Request:
{
"name": "GPT-4 Turbo (Latest)"
}
| Field | Type | Description |
|---|---|---|
name | string | New display name. Omit to leave unchanged. |
service_id | string | Bind the item to this service. Omit to leave unchanged. |
is_global | boolean | true makes the item available to every service and releases the service it was scoped to. |
The response is the full item as it is now stored, in the same shape as Create Item, so a field you did not send comes back with its current value rather than being reported as empty.
An item already bound to a service can only be released to global from here (is_global: true),
not moved straight to a different service. Sending a service_id that names a different service
than the one it is already filed under is refused with a 422; release it to global first, then
bind it to the new one.
Delete Item
DELETE /api/v1/items/{item_id}
Returns 200 OK with {"message": "Item deleted"} on success.
Deleting an item releases its charge code, so the same code can be used for a new item later. When the
code could not be released, the answer carries a warning beside the message naming the code and
saying it is not free yet. The item is deleted either way.
Deletion is refused with a 422 once the code has been configured for pricing anywhere. The pricing
history is kept, so no request on this API frees the code again, and a replacement needs a different
item ID. Any pricing row claims the code, including a Prohibited row and a quota row that carry
no price, and so does a service's per-item vendor cost override.
Items Priced per Dimension
An item priced per dimension has a separate price for each kind of usage you name, such as input
and output tokens. Each dimension is stored under a charge code of its own, the item ID then the
dimension, so dimension IN on item OPUS46 bills as OPUS46-IN. Your integration reports that
code in charging requests. In the API such an item is addressed under /items/models, and
model_id is the field that ties its dimensions together.
Every dimension also appears in List Items as an ordinary item, and
Get Item reads one. Update Item and Delete Item refuse a dimension with a 400: change
it through the item it belongs to, so its dimensions stay in step. For one allowance
shared by every dimension, see
One allowance across a model's dimensions.
Create Item Priced per Dimension
POST /api/v1/items/models
Request:
{
"id": "OPUS46",
"name": "Claude Opus 4.6",
"dimensions": ["IN", "OUT"],
"service_id": "123"
}
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Letters, digits, dashes, underscores only. Max 12 characters, to leave room for the dimension in each charge code. |
name | string | Yes | Display name. Max 55 characters. Each dimension is named after it, such as Claude Opus 4.6 (IN). |
dimensions | array of strings | Yes | 2 to 8 dimensions, each 1 to 4 letters or digits. Stored in capitals. A dimension may appear only once. |
service_id | string | No | Scope the item to this service. |
is_global | boolean | No | true makes the item available to every service. |
As with a single item, an item created with neither service_id nor is_global is scoped to no
service and appears under no service filter.
A charge code holds at most 16 characters. When the item ID and a dimension do not fit together,
the request is refused with a 422 that names the code and says how far to shorten either one.
The request is also refused with a 422 when the item ID or any of its charge codes is already
taken by another item.
Response:
{
"id": "OPUS46",
"name": "Claude Opus 4.6",
"service_id": "123",
"is_global": false,
"items": [
{
"id": "OPUS46-IN",
"name": "Claude Opus 4.6 (IN)",
"service_id": "123",
"is_global": false,
"model_id": "OPUS46",
"dimension": "IN",
"in_use": false
},
{
"id": "OPUS46-OUT",
"name": "Claude Opus 4.6 (OUT)",
"service_id": "123",
"is_global": false,
"model_id": "OPUS46",
"dimension": "OUT",
"in_use": false
}
],
"warning": null
}
items holds one record per dimension, ordered by charge code. in_use is true after the code
has been configured for pricing anywhere, a Prohibited or quota row included, or as a service's
vendor cost override. It stays true after the price is removed. A dimension with in_use: true
cannot be dropped, and its item cannot be deleted.
Get Item Priced per Dimension
GET /api/v1/items/models/{model_id}
Returns the item in the same shape as the create response.
Update Item Priced per Dimension
PATCH /api/v1/items/models/{model_id}
Returns the item as it now stands, in the same shape as the create response.
Request:
{
"dimensions": ["IN", "OUT", "CIN"]
}
| Field | Type | Description |
|---|---|---|
name | string | New display name for every dimension. Omit to leave unchanged. |
service_id | string | Bind the item to this service. Omit to leave unchanged. |
is_global | boolean | true makes the item available to every service and releases the service it was scoped to. |
dimensions | array of strings | The whole set the item carries from now on, 1 to 8 dimensions. Omit to leave unchanged. |
dimensions is matched by code: a dimension already there is kept, a new one is created, and one
left out is deleted. Dropping a dimension that has been configured for pricing anywhere is
refused with a 422 before anything is written, so nothing else in the request is applied either.
The billing engine keeps the pricing history, so clearing the price does not make it removable. As
with a single item, an item bound to a service can only be released to global, not
moved straight to another service.
The update is refused when an added dimension's charge code would not fit in 16 characters or
clashes with an existing item, and when is_global is false with no service_id.
When writing a dimension fails, what was already written is undone: an added dimension is discarded
and a changed one is put back. The request then fails, and its error names the dimension that could
not be written. If a put-back fails too, the error also names the dimensions that no longer agree.
Removing a dropped dimension is the last step and is not undone: when it fails, the other changes
stand, and the error names what was already removed. On success, a warning names a charge code a
dropped dimension could not release.
Delete Item Priced per Dimension
DELETE /api/v1/items/models/{model_id}
Returns 200 OK with {"message": "Item deleted"}, and deletes every dimension with the item.
Deletion is refused with a 422, and nothing is deleted, when any dimension has been configured
for pricing. A replacement then needs a different item ID. A warning in the answer names what
the delete could not release, such as a shared allowance that stops the same ID from carrying one
again.
When removing one dimension fails part way, the request fails, the error names the dimensions already removed, and the item is left incomplete.