curl --request POST \
--url https://app.textql.com/v2/api-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expirySeconds": 3600,
"assumedRoles": [
"80de0196-496f-44fe-9d4c-8013b3b44082"
],
"inheritAllRoles": true,
"name": "acme-session-key",
"targetMemberId": "<string>",
"clientId": "{\"tenant_id\": \"acme\", \"user_email\": \"jane@acme.example\"}",
"fullMemberAccess": true
}
'import requests
url = "https://app.textql.com/v2/api-keys"
payload = {
"expirySeconds": 3600,
"assumedRoles": ["80de0196-496f-44fe-9d4c-8013b3b44082"],
"inheritAllRoles": True,
"name": "acme-session-key",
"targetMemberId": "<string>",
"clientId": "{\"tenant_id\": \"acme\", \"user_email\": \"jane@acme.example\"}",
"fullMemberAccess": True
}
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({
expirySeconds: 3600,
assumedRoles: ['80de0196-496f-44fe-9d4c-8013b3b44082'],
inheritAllRoles: true,
name: 'acme-session-key',
targetMemberId: '<string>',
clientId: '{"tenant_id": "acme", "user_email": "jane@acme.example"}',
fullMemberAccess: true
})
};
fetch('https://app.textql.com/v2/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://app.textql.com/v2/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([
'expirySeconds' => 3600,
'assumedRoles' => [
'80de0196-496f-44fe-9d4c-8013b3b44082'
],
'inheritAllRoles' => true,
'name' => 'acme-session-key',
'targetMemberId' => '<string>',
'clientId' => '{"tenant_id": "acme", "user_email": "jane@acme.example"}',
'fullMemberAccess' => true
]),
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://app.textql.com/v2/api-keys"
payload := strings.NewReader("{\n \"expirySeconds\": 3600,\n \"assumedRoles\": [\n \"80de0196-496f-44fe-9d4c-8013b3b44082\"\n ],\n \"inheritAllRoles\": true,\n \"name\": \"acme-session-key\",\n \"targetMemberId\": \"<string>\",\n \"clientId\": \"{\\\"tenant_id\\\": \\\"acme\\\", \\\"user_email\\\": \\\"jane@acme.example\\\"}\",\n \"fullMemberAccess\": true\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://app.textql.com/v2/api-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expirySeconds\": 3600,\n \"assumedRoles\": [\n \"80de0196-496f-44fe-9d4c-8013b3b44082\"\n ],\n \"inheritAllRoles\": true,\n \"name\": \"acme-session-key\",\n \"targetMemberId\": \"<string>\",\n \"clientId\": \"{\\\"tenant_id\\\": \\\"acme\\\", \\\"user_email\\\": \\\"jane@acme.example\\\"}\",\n \"fullMemberAccess\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.textql.com/v2/api-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 \"expirySeconds\": 3600,\n \"assumedRoles\": [\n \"80de0196-496f-44fe-9d4c-8013b3b44082\"\n ],\n \"inheritAllRoles\": true,\n \"name\": \"acme-session-key\",\n \"targetMemberId\": \"<string>\",\n \"clientId\": \"{\\\"tenant_id\\\": \\\"acme\\\", \\\"user_email\\\": \\\"jane@acme.example\\\"}\",\n \"fullMemberAccess\": true\n}"
response = http.request(request)
puts response.read_body{
"key": "BEARER_SECRET_SHOWN_ONCE",
"api_key": {
"id": "4f0c39a1-7c9e-4a34-9d20-6a1f6f6f2b71",
"member_id": "9b2f7a64-11d0-4c1b-8f3e-2f9c5b7f6e10",
"name": "acme-session-key",
"client_id": "{\"tenant_id\": \"acme\", \"user_email\": \"jane@acme.example\"}",
"assumed_roles": [
"80de0196-496f-44fe-9d4c-8013b3b44082"
],
"status": "active",
"created_at": "2026-07-06T19:30:00Z",
"expires_at": "2026-07-06T20:30:00Z"
}
}{
"error": {
"code": "invalid_request",
"message": "Invalid request body"
}
}{
"error": {
"code": "unauthenticated",
"message": "Authentication required"
}
}{
"error": {
"code": "permission_denied",
"message": "Insufficient permissions"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded"
}
}{
"error": {
"code": "internal",
"message": "Internal server error"
}
}Create API Key
Mint a role-scoped platform API key, optionally carrying client metadata for row-level security
curl --request POST \
--url https://app.textql.com/v2/api-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"expirySeconds": 3600,
"assumedRoles": [
"80de0196-496f-44fe-9d4c-8013b3b44082"
],
"inheritAllRoles": true,
"name": "acme-session-key",
"targetMemberId": "<string>",
"clientId": "{\"tenant_id\": \"acme\", \"user_email\": \"jane@acme.example\"}",
"fullMemberAccess": true
}
'import requests
url = "https://app.textql.com/v2/api-keys"
payload = {
"expirySeconds": 3600,
"assumedRoles": ["80de0196-496f-44fe-9d4c-8013b3b44082"],
"inheritAllRoles": True,
"name": "acme-session-key",
"targetMemberId": "<string>",
"clientId": "{\"tenant_id\": \"acme\", \"user_email\": \"jane@acme.example\"}",
"fullMemberAccess": True
}
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({
expirySeconds: 3600,
assumedRoles: ['80de0196-496f-44fe-9d4c-8013b3b44082'],
inheritAllRoles: true,
name: 'acme-session-key',
targetMemberId: '<string>',
clientId: '{"tenant_id": "acme", "user_email": "jane@acme.example"}',
fullMemberAccess: true
})
};
fetch('https://app.textql.com/v2/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://app.textql.com/v2/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([
'expirySeconds' => 3600,
'assumedRoles' => [
'80de0196-496f-44fe-9d4c-8013b3b44082'
],
'inheritAllRoles' => true,
'name' => 'acme-session-key',
'targetMemberId' => '<string>',
'clientId' => '{"tenant_id": "acme", "user_email": "jane@acme.example"}',
'fullMemberAccess' => true
]),
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://app.textql.com/v2/api-keys"
payload := strings.NewReader("{\n \"expirySeconds\": 3600,\n \"assumedRoles\": [\n \"80de0196-496f-44fe-9d4c-8013b3b44082\"\n ],\n \"inheritAllRoles\": true,\n \"name\": \"acme-session-key\",\n \"targetMemberId\": \"<string>\",\n \"clientId\": \"{\\\"tenant_id\\\": \\\"acme\\\", \\\"user_email\\\": \\\"jane@acme.example\\\"}\",\n \"fullMemberAccess\": true\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://app.textql.com/v2/api-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"expirySeconds\": 3600,\n \"assumedRoles\": [\n \"80de0196-496f-44fe-9d4c-8013b3b44082\"\n ],\n \"inheritAllRoles\": true,\n \"name\": \"acme-session-key\",\n \"targetMemberId\": \"<string>\",\n \"clientId\": \"{\\\"tenant_id\\\": \\\"acme\\\", \\\"user_email\\\": \\\"jane@acme.example\\\"}\",\n \"fullMemberAccess\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.textql.com/v2/api-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 \"expirySeconds\": 3600,\n \"assumedRoles\": [\n \"80de0196-496f-44fe-9d4c-8013b3b44082\"\n ],\n \"inheritAllRoles\": true,\n \"name\": \"acme-session-key\",\n \"targetMemberId\": \"<string>\",\n \"clientId\": \"{\\\"tenant_id\\\": \\\"acme\\\", \\\"user_email\\\": \\\"jane@acme.example\\\"}\",\n \"fullMemberAccess\": true\n}"
response = http.request(request)
puts response.read_body{
"key": "BEARER_SECRET_SHOWN_ONCE",
"api_key": {
"id": "4f0c39a1-7c9e-4a34-9d20-6a1f6f6f2b71",
"member_id": "9b2f7a64-11d0-4c1b-8f3e-2f9c5b7f6e10",
"name": "acme-session-key",
"client_id": "{\"tenant_id\": \"acme\", \"user_email\": \"jane@acme.example\"}",
"assumed_roles": [
"80de0196-496f-44fe-9d4c-8013b3b44082"
],
"status": "active",
"created_at": "2026-07-06T19:30:00Z",
"expires_at": "2026-07-06T20:30:00Z"
}
}{
"error": {
"code": "invalid_request",
"message": "Invalid request body"
}
}{
"error": {
"code": "unauthenticated",
"message": "Authentication required"
}
}{
"error": {
"code": "permission_denied",
"message": "Insufficient permissions"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded"
}
}{
"error": {
"code": "internal",
"message": "Internal server error"
}
}Body
Mint the key for this member instead of the caller. A human target requires the caller's role to hold api_access_key:delegate; organization:write alone is denied. A service-account target requires organization:write. The key authenticates as the target member, always carries full member access so the target's direct object grants stay reachable, is scoped to that member's roles, and suppresses superadmin elevation. Granting api_access_key:delegate is a full impersonation capability.
When true, the key keeps the target member's direct object grants alongside its assumed-role grants. A key minted on behalf of a human member always carries full member access regardless of this flag. For a key acting as the caller or as a service account, false is the default and an API-key caller may set it true only when its own key already has full member access.