LanaChat

API: team members, roles and access tokens

6 min readUpdated Markdown

Your team is the people who work in the workspace. Each member has a role (built-in or custom) that sets what they can do, the creators they work on, and a personal access key to sign in. Access tokens are the keys of the API and of the MCP connection. All these endpoints need an owner token: in the examples, $LANACHAT_TOKEN holds one.

Endpoints #

MethodPathDescriptionPermissionStatus
GET/membersList members (status=active,disabled, role_id=, q=)ownerPlanned
POST/membersAdd a member with a role and creatorsownerPlanned
GET/members/{id}One member, last activity and overridesownerPlanned
PATCH/members/{id}Change role, creators, overrides; disable or enableownerPlanned
DELETE/members/{id}Delete a member (their past messages keep their name)ownerPlanned
POST/members/{id}/access-keyCreate a personal access key (shown once)ownerPlanned
POST/members/{id}/invitationE-mail an access key to the memberownerPlanned
DELETE/members/{id}/access-keyRevoke the member's key: they are signed outownerPlanned
GET/rolesBuilt-in and custom roles with their permission tableownerPlanned
POST/rolesCreate a custom roleownerPlanned
PATCH/roles/{id}Rename a role or change its permissionsownerPlanned
DELETE/roles/{id}Delete a custom role no member hasownerPlanned
GET/tokensAPI and MCP access tokens (include_revoked=true)ownerPlanned
POST/tokensCreate a token with its permissions (shown once)ownerPlanned
PATCH/tokens/{id}Rename a token or change its permissionsownerPlanned
POST/tokens/{id}/rotateReplace the secret; the old one stops at onceownerPlanned
DELETE/tokens/{id}Revoke a tokenownerPlanned

The member object #

{
  "id": "mem_4",
  "name": "Ana",
  "email": "[email protected]",
  "status": "active",
  "role_id": "role_chatter",
  "creator_ids": ["cr_lea", "cr_mia"],
  "overrides": { "billing.read": false, "fans.export": true },
  "access_key": { "active": true, "created_at": "2026-09-20T09:00:00Z" },
  "last_active_at": "2026-10-06T13:40:00Z"
}
FieldTypeDescription
idstringStarts with mem_
namestringTheir name in the Console
emailstring or nullWhere the invitation goes
statusstringactive or disabled
role_idstringTheir role
creator_idsarray of stringsThe creators they work on
overridesobjectPermissions set for this member only, on top of the role
access_keyobjectWhether they have an active personal access key, and since when; never the key itself
last_active_atstring or nullTheir last activity

A disabled member cannot sign in and keeps their history, role and creators.

The role object #

{
  "id": "role_chatter",
  "name": "Chatter",
  "builtin": true,
  "permissions": { "live.read": true, "live.reply": true, "fans.read": true, "fans.export": false, "billing.read": false },
  "members": 6
}
FieldTypeDescription
idstringThe role
namestringIts name
builtinbooleantrue for Owner, Manager and Chatter
permissionsobjectOne key per row of the permission table, true or false
membersintegerHow many members have it

Permission keys follow the rows of the permission table in Team Management › Roles, grouped by area: Dashboard, Creators, AI Brain, Conversations, Vault, Scripts, Playground, Telegram and Employees. Owner always has every permission and cannot be edited. Manager and Chatter are built in: you can change their permissions but not rename or delete them.

The access token object #

{
  "id": "tok_31",
  "name": "Reporting script",
  "permissions": ["can_fan_read", "can_sales_read"],
  "status": "active",
  "created_at": "2026-10-06T15:10:00Z",
  "expires_at": "2027-01-04T15:10:00Z"
}
FieldTypeDescription
idstringStarts with tok_
namestringUp to 100 characters, required
permissionsarray of stringsThe permissions it has
statusstringActive, expired or revoked
created_at, expires_atstringISO 8601, UTC
tokenstringThe secret, only in the answer that creates or rotates it

Members #

List members #

GET /members · owner

ParameterTypeRequiredDescription
statusstringNoactive or disabled; both separated by a comma
role_idstringNoOnly members with this role
qstringNoPart of a name
limit, cursornumber, stringNoPagination
curl "https://api.lanachat.ai/v1/members?status=active&role_id=role_chatter" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
{
  "data": [
    { "id": "mem_4", "name": "Ana", "email": "[email protected]", "status": "active", "role_id": "role_chatter", "creator_ids": ["cr_lea", "cr_mia"], "overrides": {}, "access_key": { "active": true, "created_at": "2026-09-20T09:00:00Z" }, "last_active_at": "2026-10-06T13:40:00Z" }
  ],
  "next_cursor": null
}

Add a member #

POST /members · owner

ParameterTypeRequiredDescription
namestringYesTheir name
emailstringNoNeeded to send an invitation
role_idstringYesA built-in or custom role
creator_idsarray of stringsNoThe creators they work on
curl -X POST https://api.lanachat.ai/v1/members \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name": "Ana", "email": "[email protected]", "role_id": "role_chatter", "creator_ids": ["cr_lea"]}'

The answer is the new member (201), active, without an access key yet.

Get a member #

GET /members/{id} · owner

curl https://api.lanachat.ai/v1/members/mem_4 \
  -H "Authorization: Bearer $LANACHAT_TOKEN"

The answer is the member object. An unknown id answers 404.

Update a member #

PATCH /members/{id} · owner

ParameterTypeRequiredDescription
role_idstringNoNew role
creator_idsarray of stringsNoReplaces their list of creators
overridesobjectNoPermissions for this member only
statusstringNoactive or disabled
curl -X PATCH https://api.lanachat.ai/v1/members/mem_4 \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"creator_ids": ["cr_lea", "cr_mia"], "overrides": {"fans.export": true}}'

The answer is the updated member. status: "disabled" cuts access at once; the role and creators are kept.

Delete a member #

DELETE /members/{id} · owner

curl -X DELETE https://api.lanachat.ai/v1/members/mem_4 \
  -H "Authorization: Bearer $LANACHAT_TOKEN"

The member is removed and their creators are unassigned. Their past messages keep their name. To keep them for later, disable them instead.

Personal access keys #

Team members don't use a password: they sign in with a personal access key. Keys start with emp_.

Create an access key #

POST /members/{id}/access-key · owner

curl -X POST https://api.lanachat.ai/v1/members/mem_4/access-key \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
{ "member_id": "mem_4", "sign_in_url": "https://app.lanachat.ai/login/?mode=employee", "access_key": "emp_6Yq2…", "shown_once": true }

Send both the sign-in address and the key to the person through a channel you trust. A disabled member answers 409: enable them first.

E-mail an access key #

POST /members/{id}/invitation · owner

curl -X POST https://api.lanachat.ai/v1/members/mem_4/invitation \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

The key is e-mailed to the address on their card. A member without an e-mail address, or a disabled one, answers 409.

Revoke an access key #

DELETE /members/{id}/access-key · owner

curl -X DELETE https://api.lanachat.ai/v1/members/mem_4/access-key \
  -H "Authorization: Bearer $LANACHAT_TOKEN"

The key stops at once and the member is signed out. Create a new key to let them back in.

Roles #

List roles #

GET /roles · owner

curl https://api.lanachat.ai/v1/roles \
  -H "Authorization: Bearer $LANACHAT_TOKEN"

A list of role objects: Owner, Manager, Chatter and your custom roles.

Create a custom role #

POST /roles · owner

ParameterTypeRequiredDescription
namestringYesThe role's name
permissionsobjectNoThe rows to turn on; the others are off
curl -X POST https://api.lanachat.ai/v1/roles \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name": "Night chatter", "permissions": {"live.read": true, "live.reply": true, "fans.read": true}}'

The answer is the new role (201) with builtin: false.

Update a role #

PATCH /roles/{id} · owner

ParameterTypeRequiredDescription
namestringNoNew name (custom roles only)
permissionsobjectNoThe rows to change; the others are kept
curl -X PATCH https://api.lanachat.ai/v1/roles/role_chatter \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"permissions": {"fans.export": false}}'

The change applies at once to every member with that role, except their own overrides. Editing Owner, or renaming Manager or Chatter, answers 409.

Delete a custom role #

DELETE /roles/{id} · owner

curl -X DELETE https://api.lanachat.ai/v1/roles/role_night \
  -H "Authorization: Bearer $LANACHAT_TOKEN"

Deleting a role that members still have answers 409: give them another role first. Built-in roles cannot be deleted.

Access tokens #

List tokens #

GET /tokens · owner

ParameterTypeRequiredDescription
include_revokedbooleanNotrue also lists revoked tokens
curl "https://api.lanachat.ai/v1/tokens?include_revoked=true" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"

A list of access token objects, without their secret.

Create a token #

POST /tokens · owner

ParameterTypeRequiredDescription
namestringYesWhat it is for, up to 100 characters
permissionsarray of stringsYesThe permissions it gets
expires_in_daysintegerNoWhen it stops
curl -X POST https://api.lanachat.ai/v1/tokens \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name": "Reporting script", "permissions": ["can_fan_read", "can_sales_read"], "expires_in_days": 90}'
{ "id": "tok_31", "name": "Reporting script", "token": "lc_live_8f2c1d0e9b7a4c6f", "permissions": ["can_fan_read", "can_sales_read"], "expires_at": "2027-01-04T15:10:00Z" }

token is in this answer only. A token can never give more than the owner token that created it. A missing name answers 400.

Update a token #

PATCH /tokens/{id} · owner

ParameterTypeRequiredDescription
namestringNoNew name
permissionsarray of stringsNoReplaces its permissions
curl -X PATCH https://api.lanachat.ai/v1/tokens/tok_31 \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"permissions": ["can_sales_read"]}'

The answer is the token, without its secret. Turning can_engine off also removes publishing, Advanced AI and experiment-report permissions. A revoked token answers 409.

Rotate a token #

POST /tokens/{id}/rotate · owner

curl -X POST https://api.lanachat.ai/v1/tokens/tok_31/rotate \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

The answer is the token with a new token secret, shown once. The old secret stops at once, so update your script right after. A revoked token answers 409.

Revoke a token #

DELETE /tokens/{id} · owner

curl -X DELETE https://api.lanachat.ai/v1/tokens/tok_31 \
  -H "Authorization: Bearer $LANACHAT_TOKEN"

The token stops at once. A token already revoked answers 409.

Warning A token works like a password. Revoke it as soon as you stop using it or think it leaked.

Latest news about Lana on Telegram

New releases and beta invites, first in the channel.