curl --request GET \
--url https://allocait.app/api/v1/preferences \
--header 'x-api-key: <api-key>'import requests
url = "https://allocait.app/api/v1/preferences"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://allocait.app/api/v1/preferences', 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://allocait.app/api/v1/preferences",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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://allocait.app/api/v1/preferences"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://allocait.app/api/v1/preferences")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://allocait.app/api/v1/preferences")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_portfolio_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_scenario_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_watchlist_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_chart_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_playbook_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_monitor_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"theme": "light",
"onboarding_pinned": true,
"onboarding_completed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": "Portfolio not found or access denied",
"error_code": "NOT_FOUND"
}{
"error": "Portfolio not found or access denied",
"error_code": "NOT_FOUND"
}{
"error": "Portfolio not found or access denied",
"error_code": "NOT_FOUND"
}{
"error": "Internal error",
"error_code": "INTERNAL_ERROR",
"request_id": "5b1e7c52-3f4a-4d0e-9a55-2d5cbe6f0a11"
}Get what the app opens to, and the theme
Every page in the app (Dashboard, Compliance, Allocation, Watchlists, Playbooks, Monitors) falls back to this row to decide what to show by default.
curl --request GET \
--url https://allocait.app/api/v1/preferences \
--header 'x-api-key: <api-key>'import requests
url = "https://allocait.app/api/v1/preferences"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://allocait.app/api/v1/preferences', 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://allocait.app/api/v1/preferences",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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://allocait.app/api/v1/preferences"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://allocait.app/api/v1/preferences")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://allocait.app/api/v1/preferences")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_portfolio_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_scenario_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_watchlist_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_chart_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_playbook_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"active_monitor_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"theme": "light",
"onboarding_pinned": true,
"onboarding_completed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": "Portfolio not found or access denied",
"error_code": "NOT_FOUND"
}{
"error": "Portfolio not found or access denied",
"error_code": "NOT_FOUND"
}{
"error": "Portfolio not found or access denied",
"error_code": "NOT_FOUND"
}{
"error": "Internal error",
"error_code": "INTERNAL_ERROR",
"request_id": "5b1e7c52-3f4a-4d0e-9a55-2d5cbe6f0a11"
}Authorizations
Raw API key shown once when created in the Allocait app (Settings > API keys). Send it verbatim in this header; the server stores and compares only its SHA-256 hash. Allocait generates every key: alc_ followed by 64 lowercase hex characters. Keys issued before 2026-10-10 are 64 hex characters with no prefix and keep working. A key may carry an expiry (90 days or 1 year, or never). A malformed, unknown, revoked or expired key gets 401 with no further detail, and a malformed one is refused before any lookup. Keys cannot be created through this API.
Response
The caller's preferences, or null if the row somehow doesn't exist yet (every account is seeded one at signup, but nothing enforces it can never be absent).
The caller's active portfolio/scenario/watchlist/chart/playbook/monitor and theme. Every page in the app falls back to this row to decide what to show by default.
light, dark, system