curl --request POST \
--url https://openrouter.ai/api/v1/keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expires_at": "2027-12-31T23:59:59Z",
"include_byok_in_limit": true,
"limit": 50,
"limit_reset": "monthly",
"name": "My New API Key"
}
'import requests
url = "https://openrouter.ai/api/v1/keys"
payload = {
"expires_at": "2027-12-31T23:59:59Z",
"include_byok_in_limit": True,
"limit": 50,
"limit_reset": "monthly",
"name": "My New API Key"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
expires_at: '2027-12-31T23:59:59Z',
include_byok_in_limit: true,
limit: 50,
limit_reset: 'monthly',
name: 'My New API Key'
})
};
fetch('https://openrouter.ai/api/v1/keys', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'expires_at' => '2027-12-31T23:59:59Z',
'include_byok_in_limit' => true,
'limit' => 50,
'limit_reset' => 'monthly',
'name' => 'My New API 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/keys"
payload := strings.NewReader("{\n \"expires_at\": \"2027-12-31T23:59:59Z\",\n \"include_byok_in_limit\": true,\n \"limit\": 50,\n \"limit_reset\": \"monthly\",\n \"name\": \"My New API Key\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://openrouter.ai/api/v1/keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expires_at\": \"2027-12-31T23:59:59Z\",\n \"include_byok_in_limit\": true,\n \"limit\": 50,\n \"limit_reset\": \"monthly\",\n \"name\": \"My New API Key\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://openrouter.ai/api/v1/keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expires_at\": \"2027-12-31T23:59:59Z\",\n \"include_byok_in_limit\": true,\n \"limit\": 50,\n \"limit_reset\": \"monthly\",\n \"name\": \"My New API Key\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"byok_usage": 0,
"byok_usage_daily": 0,
"byok_usage_monthly": 0,
"byok_usage_weekly": 0,
"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": true,
"label": "My New API Key",
"limit": 50,
"limit_remaining": 50,
"limit_reset": "monthly",
"name": "My New API Key",
"updated_at": null,
"usage": 0,
"usage_daily": 0,
"usage_monthly": 0,
"usage_weekly": 0,
"workspace_id": "0df9e665-d932-5740-b2c7-b52af166bc11"
},
"key": "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"
}{
"error": {
"code": 400,
"message": "Invalid request parameters"
}
}{
"error": {
"code": 401,
"message": "Missing Authentication header"
}
}{
"error": {
"code": 403,
"message": "Only management keys can perform this operation"
}
}{
"error": {
"code": 429,
"message": "Rate limit exceeded"
}
}{
"error": {
"code": 500,
"message": "Internal Server Error"
}
}Create a new API key
Create a new API key for the authenticated user. The plaintext key is returned only in this response. Treat it as a write-only, sensitive value; it cannot be retrieved later. Authenticate with a management key, or with a Connect client secret. external_user and external_api_key are accepted only with a client secret, and external_user is required there; supplying either field with a management key is rejected with 403.
curl --request POST \
--url https://openrouter.ai/api/v1/keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expires_at": "2027-12-31T23:59:59Z",
"include_byok_in_limit": true,
"limit": 50,
"limit_reset": "monthly",
"name": "My New API Key"
}
'import requests
url = "https://openrouter.ai/api/v1/keys"
payload = {
"expires_at": "2027-12-31T23:59:59Z",
"include_byok_in_limit": True,
"limit": 50,
"limit_reset": "monthly",
"name": "My New API Key"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
expires_at: '2027-12-31T23:59:59Z',
include_byok_in_limit: true,
limit: 50,
limit_reset: 'monthly',
name: 'My New API Key'
})
};
fetch('https://openrouter.ai/api/v1/keys', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'expires_at' => '2027-12-31T23:59:59Z',
'include_byok_in_limit' => true,
'limit' => 50,
'limit_reset' => 'monthly',
'name' => 'My New API 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/keys"
payload := strings.NewReader("{\n \"expires_at\": \"2027-12-31T23:59:59Z\",\n \"include_byok_in_limit\": true,\n \"limit\": 50,\n \"limit_reset\": \"monthly\",\n \"name\": \"My New API Key\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://openrouter.ai/api/v1/keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expires_at\": \"2027-12-31T23:59:59Z\",\n \"include_byok_in_limit\": true,\n \"limit\": 50,\n \"limit_reset\": \"monthly\",\n \"name\": \"My New API Key\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://openrouter.ai/api/v1/keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expires_at\": \"2027-12-31T23:59:59Z\",\n \"include_byok_in_limit\": true,\n \"limit\": 50,\n \"limit_reset\": \"monthly\",\n \"name\": \"My New API Key\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"byok_usage": 0,
"byok_usage_daily": 0,
"byok_usage_monthly": 0,
"byok_usage_weekly": 0,
"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": true,
"label": "My New API Key",
"limit": 50,
"limit_remaining": 50,
"limit_reset": "monthly",
"name": "My New API Key",
"updated_at": null,
"usage": 0,
"usage_daily": 0,
"usage_monthly": 0,
"usage_weekly": 0,
"workspace_id": "0df9e665-d932-5740-b2c7-b52af166bc11"
},
"key": "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"
}{
"error": {
"code": 400,
"message": "Invalid request parameters"
}
}{
"error": {
"code": 401,
"message": "Missing Authentication header"
}
}{
"error": {
"code": 403,
"message": "Only management keys can perform this operation"
}
}{
"error": {
"code": 429,
"message": "Rate limit exceeded"
}
}{
"error": {
"code": 500,
"message": "Internal Server Error"
}
}Authorizations
API key as bearer token in Authorization header
Body
Name for the new API key
1"My New API Key"
Optional user ID of the key creator. Only meaningful for organization-owned keys where a specific member is creating the key.
1"user_2dHFtVWx2n56w6HkM0000000000"
Optional ISO 8601 UTC expiration timestamp. Must include seconds (YYYY-MM-DDTHH:MM:SSZ; fractional seconds allowed); minute-precision timestamps are rejected.
"2027-12-31T23:59:59Z"
Optional partner-supplied API key. Stored as a SHA-256 hash and never returned. Accepted only when authenticating with a Connect client secret; supplying it with a management key is rejected with 403.
1 - 512Partner's end-user identifier for attribution, between 1 and 512 characters. Accepted only when authenticating with a Connect client secret, where it is required; supplying it with a management key is rejected with 403.
1 - 512Whether to include BYOK usage in the limit
true
Optional spending limit for the API key in USD
50
Type of limit reset 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 "monthly"
The workspace to create the API key in. Defaults to the default workspace if not provided.
"0df9e665-d932-5740-b2c7-b52af166bc11"
Response
API key created successfully
The created 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", "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" }
The actual API key string (only shown once)
"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"