Create Pat
curl --request POST \
--url https://api.example.com/organization-pats \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"expires_at": 123
}
'import requests
url = "https://api.example.com/organization-pats"
payload = {
"name": "<string>",
"expires_at": 123
}
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({name: '<string>', expires_at: 123})
};
fetch('https://api.example.com/organization-pats', 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://api.example.com/organization-pats",
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' => '<string>',
'expires_at' => 123
]),
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://api.example.com/organization-pats"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"expires_at\": 123\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://api.example.com/organization-pats")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"expires_at\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/organization-pats")
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 \"name\": \"<string>\",\n \"expires_at\": 123\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"name": "<string>",
"key_id": "<string>",
"pat_key": "<string>",
"expires_at": "<string>",
"created_at": "<string>",
"owner_user_id": "<string>",
"owner_name": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}PATs
Create an Organization API Key
POST
/
organization-pats
Create Pat
curl --request POST \
--url https://api.example.com/organization-pats \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"expires_at": 123
}
'import requests
url = "https://api.example.com/organization-pats"
payload = {
"name": "<string>",
"expires_at": 123
}
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({name: '<string>', expires_at: 123})
};
fetch('https://api.example.com/organization-pats', 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://api.example.com/organization-pats",
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' => '<string>',
'expires_at' => 123
]),
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://api.example.com/organization-pats"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"expires_at\": 123\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://api.example.com/organization-pats")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"expires_at\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/organization-pats")
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 \"name\": \"<string>\",\n \"expires_at\": 123\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"name": "<string>",
"key_id": "<string>",
"pat_key": "<string>",
"expires_at": "<string>",
"created_at": "<string>",
"owner_user_id": "<string>",
"owner_name": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Requires an active organization — without one, the org lookup this performs fails and the request returns
404 rather than proceeding. The secret is generated here, hashed with Argon2id, and stored in the pats table (org-scoped by row-level security). Creates the paired Logto personal access token first, then the local pats row; if the local insert fails, the Logto token is deleted to avoid leaving an orphaned credential.
Auth
Requirespats:create and an active organization, since the key is created under the token’s organization. Every default role carries pats:create: the key is minted under the caller’s own Logto user and, at exchange, carries only that user’s scopes, so it can’t grant more access than the caller already has.
Response
200 OK — same shape as one element of the List Organization API Keys response, except:
| Field | Type | Description |
|---|---|---|
pat_key | string | The full secret, ak_<key_id>.<secret> — shown exactly once. Store it now; it cannot be retrieved again. |
Errors
| Status | Cause |
|---|---|
404 Not Found | The token’s organization claim doesn’t resolve to a known AnyCRM organization (Organization not found for logto_org_id=...) — typically means no active organization was selected. |
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json