Profiles
A profile represents one of your end customers. Your API key is bound to exactly one, so every endpoint here operates on that profile and no other. See Core concepts for the model.
Profiles are created in the dashboard, not through the API.
GET/api/v1/profilesList profiles
Returns the single profile your key is bound to. The array shape exists so the response does not change if key scoping is ever relaxed.
curl --fail-with-body "$ADELI_URL/api/v1/profiles" \
-H "Authorization: Bearer $ADELI_API_KEY"{
"profiles": [
{
"id": "00000000-0000-4000-8000-000000000001",
"name": "Client A",
"externalId": "customer-123",
"metadata": {},
"isDefault": true,
"createdAt": "2026-09-08T20:00:00.000Z",
"updatedAt": "2026-09-08T20:00:00.000Z"
}
]
}Errors — 401 unauthorized, 404 profile_not_found, 502 database_error.
POST/api/v1/profilesCreate a profile — not available
Always returns 403 profile_scope_violation. A profile-scoped key cannot create
another profile; if it could, one leaked key would let an attacker grow its own
blast radius. Create profiles in the dashboard and issue a key per profile.
{
"error": {
"code": "profile_scope_violation",
"message": "This API key is scoped to one profile and cannot create another profile"
}
}GET/api/v1/profiles/{profileId}Get a profile
Returns the profile as a bare object — not wrapped in profiles.
Path parameters
profileIduuidRequired- Must be the profile your key is bound to. Any other value returns 404 profile_not_found.
Errors — 401 unauthorized, 400 invalid_request, 404 profile_not_found,
502 database_error.
PUT/api/v1/profiles/{profileId}Update a profile
Replaces the mutable fields. This is a full replace, not a merge: omitting
externalId or metadata clears them.
Body
namestringRequired- 1–200 characters after trimming. Must be unique across your profiles.
externalIdstring | null- Up to 200 characters. Must be unique across your profiles when not null.
metadataobject | null- Any JSON object, up to 16 KiB encoded as UTF-8. Arrays and scalars are rejected.
curl --fail-with-body -X PUT \
"$ADELI_URL/api/v1/profiles/$PROFILE_ID" \
-H "Authorization: Bearer $ADELI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Client A","externalId":"customer-123","metadata":{"plan":"pro"}}'Errors — 401 unauthorized, 400 invalid_request, 400 invalid_profile,
404 profile_not_found, 409 profile_name_conflict,
409 profile_external_id_conflict, 502 database_error.
Both conflict responses carry the colliding profile in details:
{
"error": {
"code": "profile_name_conflict",
"message": "A profile with this name already exists",
"details": { "existingProfileId": "00000000-0000-4000-8000-000000000009" }
}
}DELETE/api/v1/profiles/{profileId}Delete a profile
This cascades and cannot be undone
Deleting a profile removes its connected accounts, their cached history, its connection sessions, and its API keys — including, most likely, the key making this request. It does not delete anything on Instagram, Facebook, TikTok, or YouTube.
{ "id": "00000000-0000-4000-8000-000000000001", "deleted": true }Errors — 401 unauthorized, 400 invalid_request, 404 profile_not_found,
502 database_error.