curl --request POST \
--url https://scribe.skeptrune.com/api/org/api-keys \
--header 'Content-Type: application/json' \
--cookie scribe_session= \
--data '
{
"name": "CI docs bot",
"access": "read",
"expiresInDays": 90
}
'import requests
url = "https://scribe.skeptrune.com/api/org/api-keys"
payload = {
"name": "CI docs bot",
"access": "read",
"expiresInDays": 90
}
headers = {
"cookie": "scribe_session=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {cookie: 'scribe_session=', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'CI docs bot', access: 'read', expiresInDays: 90})
};
fetch('https://scribe.skeptrune.com/api/org/api-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://scribe.skeptrune.com/api/org/api-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([
'name' => 'CI docs bot',
'access' => 'read',
'expiresInDays' => 90
]),
CURLOPT_COOKIE => "scribe_session=",
CURLOPT_HTTPHEADER => [
"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://scribe.skeptrune.com/api/org/api-keys"
payload := strings.NewReader("{\n \"name\": \"CI docs bot\",\n \"access\": \"read\",\n \"expiresInDays\": 90\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("cookie", "scribe_session=")
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://scribe.skeptrune.com/api/org/api-keys")
.header("cookie", "scribe_session=")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"CI docs bot\",\n \"access\": \"read\",\n \"expiresInDays\": 90\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://scribe.skeptrune.com/api/org/api-keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["cookie"] = 'scribe_session='
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"CI docs bot\",\n \"access\": \"read\",\n \"expiresInDays\": 90\n}"
response = http.request(request)
puts response.read_body{
"key": {
"id": "key_2mNbVcXzLkJhGfDsAqWe",
"name": "CI docs bot",
"keyPrefix": "scrb_agt_AbC",
"access": "read",
"createdBy": "usr_V1StGXR8_Z5jdHi6BmyT",
"agentUserId": "usr_9wQxAgEnTbOtIdEf7g8h",
"expiresAt": 1752624000000,
"lastUsedAt": 1752624000000,
"revokedAt": null,
"createdAt": 1752624000000
},
"token": "scrb_agt_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGh"
}{
"error": {
"code": "not_found",
"message": "No such document."
}
}{
"error": {
"code": "not_found",
"message": "No such document."
}
}{
"error": {
"code": "not_found",
"message": "No such document."
}
}Create an API key
Creates an org-scoped API key together with its agent user — the member identity the key acts as on every other endpoint — and returns the secret token exactly once. Sessions need the admin role or higher; an API key with edit access can also mint keys, attributed to its agent identity via createdBy. Note that keys minted by an agent outlive that agent’s own revocation, so audit an agent’s keys (filter by createdBy) after revoking it.
curl --request POST \
--url https://scribe.skeptrune.com/api/org/api-keys \
--header 'Content-Type: application/json' \
--cookie scribe_session= \
--data '
{
"name": "CI docs bot",
"access": "read",
"expiresInDays": 90
}
'import requests
url = "https://scribe.skeptrune.com/api/org/api-keys"
payload = {
"name": "CI docs bot",
"access": "read",
"expiresInDays": 90
}
headers = {
"cookie": "scribe_session=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {cookie: 'scribe_session=', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'CI docs bot', access: 'read', expiresInDays: 90})
};
fetch('https://scribe.skeptrune.com/api/org/api-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://scribe.skeptrune.com/api/org/api-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([
'name' => 'CI docs bot',
'access' => 'read',
'expiresInDays' => 90
]),
CURLOPT_COOKIE => "scribe_session=",
CURLOPT_HTTPHEADER => [
"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://scribe.skeptrune.com/api/org/api-keys"
payload := strings.NewReader("{\n \"name\": \"CI docs bot\",\n \"access\": \"read\",\n \"expiresInDays\": 90\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("cookie", "scribe_session=")
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://scribe.skeptrune.com/api/org/api-keys")
.header("cookie", "scribe_session=")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"CI docs bot\",\n \"access\": \"read\",\n \"expiresInDays\": 90\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://scribe.skeptrune.com/api/org/api-keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["cookie"] = 'scribe_session='
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"CI docs bot\",\n \"access\": \"read\",\n \"expiresInDays\": 90\n}"
response = http.request(request)
puts response.read_body{
"key": {
"id": "key_2mNbVcXzLkJhGfDsAqWe",
"name": "CI docs bot",
"keyPrefix": "scrb_agt_AbC",
"access": "read",
"createdBy": "usr_V1StGXR8_Z5jdHi6BmyT",
"agentUserId": "usr_9wQxAgEnTbOtIdEf7g8h",
"expiresAt": 1752624000000,
"lastUsedAt": 1752624000000,
"revokedAt": null,
"createdAt": 1752624000000
},
"token": "scrb_agt_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGh"
}{
"error": {
"code": "not_found",
"message": "No such document."
}
}{
"error": {
"code": "not_found",
"message": "No such document."
}
}{
"error": {
"code": "not_found",
"message": "No such document."
}
}Authorizations
Browser session cookie set by the WorkOS sign-in flow.
Body
Key name, access level, and optional expiry.
Create a new API key.
Human-readable name for the new key.
1 - 120"CI docs bot"
Access level to grant the new key: read, comment, or edit.
read, comment, edit "read"
Days until the key expires. Omit for a non-expiring key.
1 <= x <= 365090
Response
The created key with its secret token. The token cannot be retrieved again.
A freshly created API key together with its secret token (returned only once).
An organization-scoped API key (agent credential). Never contains the secret token.
Show child attributes
Show child attributes
{
"id": "key_2mNbVcXzLkJhGfDsAqWe",
"name": "CI docs bot",
"keyPrefix": "scrb_agt_AbC",
"access": "read",
"createdBy": "usr_V1StGXR8_Z5jdHi6BmyT",
"agentUserId": "usr_9wQxAgEnTbOtIdEf7g8h",
"expiresAt": 1752624000000,
"lastUsedAt": 1752624000000,
"revokedAt": null,
"createdAt": 1752624000000
}
The full secret token. Shown exactly once — it cannot be retrieved again.
"scrb_agt_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGh"