curl --request PATCH \
--url https://openrouter.ai/api/v1/byok/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"disabled": false,
"name": "Updated OpenAI Key"
}
'import requests
url = "https://openrouter.ai/api/v1/byok/{id}"
payload = {
"disabled": False,
"name": "Updated OpenAI Key"
}
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, name: 'Updated OpenAI Key'})
};
fetch('https://openrouter.ai/api/v1/byok/{id}', 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/byok/{id}",
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,
'name' => 'Updated OpenAI Key'
]),
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/byok/{id}"
payload := strings.NewReader("{\n \"disabled\": false,\n \"name\": \"Updated OpenAI Key\"\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/byok/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"disabled\": false,\n \"name\": \"Updated OpenAI Key\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://openrouter.ai/api/v1/byok/{id}")
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 \"name\": \"Updated OpenAI Key\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"allowed_api_key_hashes": null,
"allowed_models": null,
"allowed_user_ids": null,
"created_at": "2025-08-24T10:30:00Z",
"disabled": false,
"id": "11111111-2222-3333-4444-555555555555",
"is_byok_only": false,
"is_fallback": false,
"is_required": false,
"label": "sk-...AbCd",
"name": "Updated OpenAI Key",
"provider": "openai",
"sort_order": 0,
"workspace_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": 400,
"message": "Invalid request parameters"
}
}{
"error": {
"code": 401,
"message": "Missing Authentication header"
}
}{
"error": {
"code": 404,
"message": "Resource not found"
}
}{
"error": {
"code": 500,
"message": "Internal Server Error"
}
}Update a BYOK provider credential
Update an existing bring-your-own-key (BYOK) provider credential by its id. Include the key field to rotate the raw provider API key in-place (the previous key material is overwritten). Use allowed_api_key_hashes to restrict the credential to specific OpenRouter API keys (null clears the restriction). Management key required.
curl --request PATCH \
--url https://openrouter.ai/api/v1/byok/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"disabled": false,
"name": "Updated OpenAI Key"
}
'import requests
url = "https://openrouter.ai/api/v1/byok/{id}"
payload = {
"disabled": False,
"name": "Updated OpenAI Key"
}
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, name: 'Updated OpenAI Key'})
};
fetch('https://openrouter.ai/api/v1/byok/{id}', 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/byok/{id}",
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,
'name' => 'Updated OpenAI Key'
]),
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/byok/{id}"
payload := strings.NewReader("{\n \"disabled\": false,\n \"name\": \"Updated OpenAI Key\"\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/byok/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"disabled\": false,\n \"name\": \"Updated OpenAI Key\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://openrouter.ai/api/v1/byok/{id}")
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 \"name\": \"Updated OpenAI Key\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"allowed_api_key_hashes": null,
"allowed_models": null,
"allowed_user_ids": null,
"created_at": "2025-08-24T10:30:00Z",
"disabled": false,
"id": "11111111-2222-3333-4444-555555555555",
"is_byok_only": false,
"is_fallback": false,
"is_required": false,
"label": "sk-...AbCd",
"name": "Updated OpenAI Key",
"provider": "openai",
"sort_order": 0,
"workspace_id": "550e8400-e29b-41d4-a716-446655440000"
}
}{
"error": {
"code": 400,
"message": "Invalid request parameters"
}
}{
"error": {
"code": 401,
"message": "Missing Authentication header"
}
}{
"error": {
"code": 404,
"message": "Resource not found"
}
}{
"error": {
"code": 500,
"message": "Internal Server Error"
}
}Authorizations
API key as bearer token in Authorization header
Path Parameters
The BYOK credential ID (UUID).
"11111111-2222-3333-4444-555555555555"
Body
Optional allowlist of OpenRouter API key hashes (api_keys.hash) that may use this credential. null clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400.
1 - 100 elements^[a-f0-9]{64}$[
"f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943"
]
Optional allowlist of model slugs this credential may be used for. null means no restriction.
100null
Optional allowlist of user IDs that may use this credential. null means no restriction.
100null
Whether this credential is disabled.
false
Whether OpenRouter's shared endpoints on this provider are removed for every model, including models outside allowed_models and after all of your keys for the provider fail. The provider is skipped instead of spending OpenRouter credits. Only valid on non-fallback credentials. Omit to leave the stored value unchanged.
false
Whether this credential is treated as a fallback — used only after non-fallback keys for the same provider have been tried. Cannot be combined with is_byok_only. Omit to leave the stored value unchanged.
false
Whether OpenRouter's shared endpoints on this provider are removed for the models this credential applies to (its allowed_models, or every model when null). Requests for those models run only on your keys; models outside the allowlist may still fall back to shared capacity on this provider. Omit to leave the stored value unchanged.
false
A new raw provider API key to rotate the credential in-place. The previous key material is overwritten and the masked label is regenerated. Encrypted at rest and never returned in API responses.
1"sk-proj-newkey456..."
Optional human-readable name for the credential.
255"Updated OpenAI Key"
Response
BYOK credential updated successfully
The updated BYOK credential.
Show child attributes
Show child attributes
{
"allowed_api_key_hashes": null,
"allowed_models": null,
"allowed_user_ids": null,
"created_at": "2025-08-24T10:30:00Z",
"disabled": false,
"id": "11111111-2222-3333-4444-555555555555",
"is_byok_only": false,
"is_fallback": false,
"is_required": false,
"label": "sk-...AbCd",
"name": "Production OpenAI Key",
"provider": "openai",
"sort_order": 0,
"workspace_id": "550e8400-e29b-41d4-a716-446655440000"
}