curl --request PATCH \
--url https://openrouter.ai/api/v1/keys/{hash} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"disabled": false,
"include_byok_in_limit": true,
"limit": 75,
"limit_reset": "daily",
"name": "Updated API Key Name"
}
'import requests
url = "https://openrouter.ai/api/v1/keys/{hash}"
payload = {
"disabled": False,
"include_byok_in_limit": True,
"limit": 75,
"limit_reset": "daily",
"name": "Updated API Key Name"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
disabled: false,
include_byok_in_limit: true,
limit: 75,
limit_reset: 'daily',
name: 'Updated API Key Name'
})
};
fetch('https://openrouter.ai/api/v1/keys/{hash}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://openrouter.ai/api/v1/keys/{hash}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'disabled' => false,
'include_byok_in_limit' => true,
'limit' => 75,
'limit_reset' => 'daily',
'name' => 'Updated API Key Name'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://openrouter.ai/api/v1/keys/{hash}"
payload := strings.NewReader("{\n \"disabled\": false,\n \"include_byok_in_limit\": true,\n \"limit\": 75,\n \"limit_reset\": \"daily\",\n \"name\": \"Updated API Key Name\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://openrouter.ai/api/v1/keys/{hash}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"disabled\": false,\n \"include_byok_in_limit\": true,\n \"limit\": 75,\n \"limit_reset\": \"daily\",\n \"name\": \"Updated API Key Name\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://openrouter.ai/api/v1/keys/{hash}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"disabled\": false,\n \"include_byok_in_limit\": true,\n \"limit\": 75,\n \"limit_reset\": \"daily\",\n \"name\": \"Updated API Key Name\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"byok_usage": 17.38,
"byok_usage_daily": 17.38,
"byok_usage_monthly": 17.38,
"byok_usage_weekly": 17.38,
"created_at": "2025-08-24T10:30:00Z",
"creator_user_id": "user_2dHFtVWx2n56w6HkM0000000000",
"disabled": false,
"expires_at": null,
"hash": "f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943",
"include_byok_in_limit": true,
"label": "Updated API Key Name",
"last_used_at": "2026-09-15T15:45:00Z",
"limit": 75,
"limit_remaining": 49.5,
"limit_reset": "daily",
"name": "Updated API Key Name",
"updated_at": "2025-08-24T16:00:00Z",
"usage": 25.5,
"usage_daily": 25.5,
"usage_monthly": 25.5,
"usage_weekly": 25.5,
"workspace_id": "0df9e665-d932-5740-b2c7-b52af166bc11"
}
}Update an API key
Update an existing API key. Authenticate with a management key.
Set workspace_id to move the key to another workspace. The key keeps its value, and any other fields in the same request are applied atomically with the move. Guardrail selections move with the key; other workspace-scoped settings (presets, BYOK keys, broadcast destinations, routing rules) do not. A move between workspaces with incompatible restrictions is refused with 403. In an organization, if the key’s creator is not a member of a non-default target workspace, the request fails with 409; add them to the workspace first.
The request body accepts only the fields listed below, and unrecognized fields are ignored. If the body contains none of the accepted fields, the request fails with 400 and the message No update fields provided.
curl --request PATCH \
--url https://openrouter.ai/api/v1/keys/{hash} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"disabled": false,
"include_byok_in_limit": true,
"limit": 75,
"limit_reset": "daily",
"name": "Updated API Key Name"
}
'import requests
url = "https://openrouter.ai/api/v1/keys/{hash}"
payload = {
"disabled": False,
"include_byok_in_limit": True,
"limit": 75,
"limit_reset": "daily",
"name": "Updated API Key Name"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
disabled: false,
include_byok_in_limit: true,
limit: 75,
limit_reset: 'daily',
name: 'Updated API Key Name'
})
};
fetch('https://openrouter.ai/api/v1/keys/{hash}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://openrouter.ai/api/v1/keys/{hash}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'disabled' => false,
'include_byok_in_limit' => true,
'limit' => 75,
'limit_reset' => 'daily',
'name' => 'Updated API Key Name'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://openrouter.ai/api/v1/keys/{hash}"
payload := strings.NewReader("{\n \"disabled\": false,\n \"include_byok_in_limit\": true,\n \"limit\": 75,\n \"limit_reset\": \"daily\",\n \"name\": \"Updated API Key Name\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://openrouter.ai/api/v1/keys/{hash}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"disabled\": false,\n \"include_byok_in_limit\": true,\n \"limit\": 75,\n \"limit_reset\": \"daily\",\n \"name\": \"Updated API Key Name\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://openrouter.ai/api/v1/keys/{hash}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"disabled\": false,\n \"include_byok_in_limit\": true,\n \"limit\": 75,\n \"limit_reset\": \"daily\",\n \"name\": \"Updated API Key Name\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"byok_usage": 17.38,
"byok_usage_daily": 17.38,
"byok_usage_monthly": 17.38,
"byok_usage_weekly": 17.38,
"created_at": "2025-08-24T10:30:00Z",
"creator_user_id": "user_2dHFtVWx2n56w6HkM0000000000",
"disabled": false,
"expires_at": null,
"hash": "f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943",
"include_byok_in_limit": true,
"label": "Updated API Key Name",
"last_used_at": "2026-09-15T15:45:00Z",
"limit": 75,
"limit_remaining": 49.5,
"limit_reset": "daily",
"name": "Updated API Key Name",
"updated_at": "2025-08-24T16:00:00Z",
"usage": 25.5,
"usage_daily": 25.5,
"usage_monthly": 25.5,
"usage_weekly": 25.5,
"workspace_id": "0df9e665-d932-5740-b2c7-b52af166bc11"
}
}Authorizations
API key as bearer token in Authorization header
Path Parameters
The hash identifier of the API key to update
"f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943"
Body
Whether to disable the API key
false
Whether to include BYOK usage in the limit
true
New spending limit for the API key in USD
75
New limit reset type for the API key (daily, weekly, monthly, or null for no reset). Resets happen automatically at midnight UTC, and weeks are Monday through Sunday.
daily, weekly, monthly, null "daily"
New name for the API key
"Updated API Key Name"
Move the API key to this workspace. The key keeps its value; guardrail selections move with it, while other workspace-scoped settings (presets, BYOK keys, broadcast destinations, routing rules) do not. Sending the key's current workspace is a no-op.
"0df9e665-d932-5740-b2c7-b52af166bc11"
Response
API key updated successfully
The updated API key information
Show child attributes
Show child attributes
{
"byok_usage": 17.38,
"byok_usage_daily": 17.38,
"byok_usage_monthly": 17.38,
"byok_usage_weekly": 17.38,
"created_at": "2025-08-24T10:30:00Z",
"creator_user_id": "user_2dHFtVWx2n56w6HkM0000000000",
"disabled": false,
"expires_at": "2027-12-31T23:59:59Z",
"external_user": null,
"hash": "f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943",
"include_byok_in_limit": false,
"label": "sk-or-v1-0e6...1c96",
"last_used_at": "2026-09-15T15:45:00Z",
"limit": 100,
"limit_remaining": 74.5,
"limit_reset": "monthly",
"name": "My Production Key",
"updated_at": "2025-08-24T15:45:00Z",
"usage": 25.5,
"usage_daily": 25.5,
"usage_monthly": 25.5,
"usage_weekly": 25.5,
"workspace_id": "0df9e665-d932-5740-b2c7-b52af166bc11"
}