curl --request POST \
--url https://app.famulor.io/api/v1/api-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "CRM integration",
"scopes": [
"calls:read",
"leads:write"
]
}
'import requests
url = "https://app.famulor.io/api/v1/api-keys"
payload = {
"name": "CRM integration",
"scopes": ["calls:read", "leads:write"]
}
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: 'CRM integration', scopes: ['calls:read', 'leads:write']})
};
fetch('https://app.famulor.io/api/v1/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.famulor.io/api/v1/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' => 'CRM integration',
'scopes' => [
'calls:read',
'leads:write'
]
]),
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.famulor.io/api/v1/api-keys"
payload := strings.NewReader("{\n \"name\": \"CRM integration\",\n \"scopes\": [\n \"calls:read\",\n \"leads:write\"\n ]\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.famulor.io/api/v1/api-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"CRM integration\",\n \"scopes\": [\n \"calls:read\",\n \"leads:write\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.famulor.io/api/v1/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 \"name\": \"CRM integration\",\n \"scopes\": [\n \"calls:read\",\n \"leads:write\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"prefix": "<string>",
"scopes": [
"<string>"
],
"principal_type": "user",
"expires_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"key": "fam_live_a1b2c3d4e5f6..."
}
}{
"error": {
"code": "invalid_request",
"message": "Requested scopes exceed the scopes granted to this API key. A key can never mint another key with broader access than itself."
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid API key."
}
}{
"error": {
"code": "forbidden",
"message": "Only workspace owners or admins can manage API keys."
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests. Retry after the indicated delay."
}
}{
"error": {
"code": "internal_error",
"message": "Request protection is temporarily unavailable."
}
}Create an API key
Mints a new self-service API key for the calling workspace. scopes must be a subset of the calling credential’s own scopes — a key can never mint another key with broader access than itself (a caller with unrestricted access, i.e. no scopes or *, may grant any scope, and an omitted scopes defaults to its own scopes). A new key cannot outlive a finite calling credential. Requires the calling credential to be a workspace owner/admin (service-account keys always qualify). The plaintext key is returned exactly once and cannot be retrieved again. Required scope: settings:write.
curl --request POST \
--url https://app.famulor.io/api/v1/api-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "CRM integration",
"scopes": [
"calls:read",
"leads:write"
]
}
'import requests
url = "https://app.famulor.io/api/v1/api-keys"
payload = {
"name": "CRM integration",
"scopes": ["calls:read", "leads:write"]
}
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: 'CRM integration', scopes: ['calls:read', 'leads:write']})
};
fetch('https://app.famulor.io/api/v1/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.famulor.io/api/v1/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' => 'CRM integration',
'scopes' => [
'calls:read',
'leads:write'
]
]),
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.famulor.io/api/v1/api-keys"
payload := strings.NewReader("{\n \"name\": \"CRM integration\",\n \"scopes\": [\n \"calls:read\",\n \"leads:write\"\n ]\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.famulor.io/api/v1/api-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"CRM integration\",\n \"scopes\": [\n \"calls:read\",\n \"leads:write\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.famulor.io/api/v1/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 \"name\": \"CRM integration\",\n \"scopes\": [\n \"calls:read\",\n \"leads:write\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"prefix": "<string>",
"scopes": [
"<string>"
],
"principal_type": "user",
"expires_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"key": "fam_live_a1b2c3d4e5f6..."
}
}{
"error": {
"code": "invalid_request",
"message": "Requested scopes exceed the scopes granted to this API key. A key can never mint another key with broader access than itself."
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid API key."
}
}{
"error": {
"code": "forbidden",
"message": "Only workspace owners or admins can manage API keys."
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests. Retry after the indicated delay."
}
}{
"error": {
"code": "internal_error",
"message": "Request protection is temporarily unavailable."
}
}Authorizations
API key (fam_..., created under Settings → API Keys) or an OAuth 2.0 access token (fam_at_...). REST operations also require API Access for the credential's workspace. Keys can be restricted to scopes such as assistants:read, calls:write, campaigns:write, automations:read, dashboards:read, dashboards:write, leads:write, segments:write, loop:read, loop:write, phone_numbers:write, sip_trunks:write, knowledge:write, voices:read, billing:read, billing:write, settings:write, platform:read, platform:write; a *:write scope implies the matching *:read. Automation and dashboard endpoints also accept the legacy calls:* scope. Keys without scope restrictions have full access within the workspace's available capabilities.
Body
100Must be a subset of the calling credential's own scopes — a key can never mint another key with broader access than itself. Omitted defaults to the calling credential's own scopes (or, if the credential itself has unrestricted access, every scope).
50Requested lifetime. Omitted inherits a finite calling credential's expiry, or means no expiry when the caller itself does not expire.
1 <= x <= 365Response
The minted key (shown once).
A newly-minted API key, including the plaintext secret.
Show child attributes
Show child attributes