curl --request GET \
--url https://api.atako.ai/organization/chart \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.atako.ai/organization/chart"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.atako.ai/organization/chart', 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.atako.ai/organization/chart",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.atako.ai/organization/chart"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.atako.ai/organization/chart")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.atako.ai/organization/chart")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"rootHumanId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tree": {
"roots": [
{
"key": "<string>",
"kind": "human",
"id": "<string>",
"name": "<string>",
"role": "<string>",
"children": "<array>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"memberCount": 123
}
],
"loose": [
{
"key": "<string>",
"kind": "human",
"id": "<string>",
"name": "<string>",
"role": "<string>",
"children": "<array>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"memberCount": 123
}
]
},
"issues": [
{
"kind": "team-lead",
"id": "<string>"
}
],
"teams": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"parentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"lead": {
"kind": "human",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
],
"agents": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"role": "<string>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"manager": {
"kind": "human",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
],
"humans": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"title": "<string>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"managerUserId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
],
"canEdit": true
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}The company org chart
The only read the client needs: it carries the drawn tree, the warnings, AND the three raw lists that fill the edit pickers — no second call to display a screen. Open to any company member; canEdit reports whether the caller may use the write operations. 404 (not 403) when you have no company, so the route is invisible rather than merely blocked.
curl --request GET \
--url https://api.atako.ai/organization/chart \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.atako.ai/organization/chart"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.atako.ai/organization/chart', 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.atako.ai/organization/chart",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.atako.ai/organization/chart"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.atako.ai/organization/chart")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.atako.ai/organization/chart")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"rootHumanId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tree": {
"roots": [
{
"key": "<string>",
"kind": "human",
"id": "<string>",
"name": "<string>",
"role": "<string>",
"children": "<array>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"memberCount": 123
}
],
"loose": [
{
"key": "<string>",
"kind": "human",
"id": "<string>",
"name": "<string>",
"role": "<string>",
"children": "<array>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"memberCount": 123
}
]
},
"issues": [
{
"kind": "team-lead",
"id": "<string>"
}
],
"teams": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"parentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"lead": {
"kind": "human",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
],
"agents": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"role": "<string>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"manager": {
"kind": "human",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
],
"humans": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"title": "<string>",
"teamId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"managerUserId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
],
"canEdit": true
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Authorizations
An aik_… programmatic API key (app.atako.ai → Settings → API keys) or a Supabase session JWT.
Response
The whole chart, and the single payload of every /organization operation — reads AND writes. A hierarchy change moves people who were not named in the request, so a write answers with the recomputed chart rather than an acknowledgement: the client never has to make a second call, nor guess. It carries both the derived SHAPE (tree) and the raw CHOICES (teams/agents/humans, with their explicit lead/manager), which is what an editor needs to show what was decided instead of what was inferred from it.
DERIVED, never stored: the oldest admin member. Null when the company has no admin at all — the only case where the chart has nothing to hang on.
The chart as a forest. roots are the people nobody stands above (normally one). loose collects what the structure left dangling — a team whose lead is gone stays on the chart, to be repaired rather than to vanish quietly.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
True when the caller is a company admin, i.e. when the write operations below are open to them. Told here so the client never has to deduce a permission from a 403 it provoked.