LanaChat

API: fans, conversations and messages

7 min de lecturaActualizado Markdown

Un fan es una usuaria de Telegram que escribió a una de tus creadoras. Una conversation es el chat entre ese fan y una cuenta de Telegram. Los mensajes los envía la IA, una compañera o un script. Estos endpoints corresponden a Live Convs y Fans en la Console.

Endpoints #

MethodPathDescriptionPermissionStatus
GET/fansLista fans (creator_id=, status=, list_id=, q=, spent_min=)can_fan_readPlanned
GET/fans/{id}Un fan: idiomas, gasto, estado, listas, notascan_fan_readPlanned
PATCH/fans/{id}Cambia el alias, idioma de respuesta o notas del fancan_chatPlanned
GET/fans/{id}/salesCompras del fancan_sales_readPlanned
POST/fans/importImporta fans y mensajes antiguos (nunca envía nada)can_fan_importPlanned
GET/fan-listsListas (VIPs, win back…)can_fan_readPlanned
POST/fan-listsCrea una listacan_chatPlanned
POST/fan-lists/{id}/membersAñade fans a una listacan_chatPlanned
DELETE/fan-lists/{id}/membersQuita fans de una listacan_chatPlanned
GET/conversationsLista conversaciones (creator_id=, account_id=, state=, unread=true)can_fan_readPlanned
GET/conversations/{id}Una conversación y quién respondecan_fan_readPlanned
GET/conversations/{id}/messagesMensajes, el más nuevo primero (translate=en añade traducción)can_fan_readPlanned
POST/conversations/{id}/messagesEnvía un mensaje como la creadora (texto, media, oferta)can_chatPlanned
POST/conversations/{id}/reactionsAñade o quita una reacción en un mensaje de fancan_chatPlanned
POST/conversations/{id}/takeoverUna persona toma el control: la IA deja de responder a este fancan_chatPlanned
POST/conversations/{id}/releaseDevuelve la conversación a la IAcan_chatPlanned
POST/conversations/{id}/scriptEjecuta un script en esta conversacióncan_chatPlanned
POST/conversations/{id}/readMarca la conversación como leídacan_chatPlanned

The fan object #

{
  "id": "fan_921",
  "display_name": "Marco",
  "username": "marco_dl",
  "creator_id": "cr_lea",
  "purchases": 9,
  "spent": { "stars": 1450, "net_cents": 1885 },
  "lists": ["vip"]
}
FieldTypeDescription
idstringEmpieza por fan_
display_namestringNombre del fan en Telegram
usernamestring o nullEl @username de Telegram del fan, sin la @
creator_idstringLa creadora a la que escribió este fan
purchasesnumberCompras verificadas hasta ahora
spentobjectTotal gastado: stars y net_cents en centavos de dólar USA tras la comisión y reembolsos de Telegram
listsarray of stringsIds de las listas de fans en las que está este fan

Un fan también lleva los idiomas en los que escribe, su etiqueta de estado, notas del equipo, un alias y un idioma de respuesta, igual que en la página Fans.

The conversation object #

{
  "id": "conv_1001_88231",
  "fan_id": "fan_921",
  "creator_id": "cr_lea",
  "account_id": "acc_1001",
  "state": "ai",
  "status": { "tag": "active", "reason": null },
  "unread": 2,
  "last_message_at": "2026-10-06T14:02:51Z",
  "spent": { "stars": 1450, "net_cents": 1885 },
  "source_link_id": "lnk_3"
}
FieldTypeDescription
idstringEmpieza por conv_
fan_id, creator_id, account_idstringQuién habla con quién, en qué cuenta de Telegram
statestringQuién responde: ai, human (tomada por persona), script (ejecutando script) u off
statusobjecttag (las etiquetas de estado de la página Fans) y el reason si hay
unreadnumberMensajes de fan sin leer
last_message_atstringISO 8601, UTC
spentobjectLo que gastó el fan en esta conversación: stars y net_cents
source_link_idstring o nullEl enlace de seguimiento por el que llegó el fan

status.tag coincide con las etiquetas de estado de la página Fans (review, safety_hold, converted, lost, underage…). Una conversación en off por motivo de seguridad no puede devolverse a la IA (409).

The message object #

{
  "id": "msg_77120",
  "from": "creator",
  "sent_by": "ai",
  "text": "Made this one this morning…",
  "media": [ { "id": "med_5521", "locked": true, "stars": 300 } ],
  "at": "2026-10-06T14:02:51Z"
}
FieldTypeDescription
idstringEmpieza por msg_
fromstringcreator o fan
sent_bystringPara mensajes de creadora: ai, human o script
member_idstringLa compañera que lo envió, si sent_by es human desde la Console
token_idstringEl token de acceso que lo envió, si vino desde la API
textstringEl texto del mensaje
mediaarrayMedia enviada: id, locked (de pago y aún no comprado) y su precio en stars
reactionsarrayReacciones en un mensaje de fan
statusstringPara mensajes que envías: queued, sent, read o failed
atstringISO 8601, UTC

sent_by decide la comisión de una venta, así que lo fija el servidor y nunca tu petición.

The sale object #

{
  "sale_id": "sale_8812",
  "fan_id": "fan_921",
  "creator_id": "cr_lea",
  "account_id": "acc_1001",
  "conversation_id": "conv_1001_88231",
  "stars": 300,
  "net_cents": 390,
  "sent_by": "ai",
  "kind": "offer"
}
FieldTypeDescription
sale_idstringEmpieza por sale_
fan_id, creator_id, account_id, conversation_idstringQuién compró, a quién, dónde
starsnumberPrecio pagado en Telegram Stars
net_centsnumberValor neto en centavos de dólar USA (un Star vale $0.013)
sent_bystringai, human o script: quién envió la oferta, define la comisión
kindstringQué se compró, por ejemplo offer

El mismo objeto llega por webhook, evento sale.completed.

Fans #

List fans #

GET /fans · can_fan_read

ParameterTypeRequiredDescription
creator_idstringNoSolo los fans de esta creadora
statusstringNoUna etiqueta de estado de la página Fans, por ejemplo converted
list_idstringNoSolo los fans de esta lista
qstringNoParte del nombre o username del fan
spent_minnumberNoSolo fans que gastaron al menos estos Stars
limit, cursornumber, stringNoPaginación
curl "https://api.lanachat.ai/v1/fans?creator_id=cr_lea&spent_min=1000&limit=50" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
{
  "data": [
    { "id": "fan_921", "display_name": "Marco", "username": "marco_dl", "creator_id": "cr_lea", "purchases": 9, "spent": { "stars": 1450, "net_cents": 1885 }, "lists": ["vip"] }
  ],
  "next_cursor": null
}

Get a fan #

GET /fans/{id} · can_fan_read

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

La respuesta es el fan object. Un id desconocido responde 404.

Update a fan #

PATCH /fans/{id} · can_chat

Envía solo lo que cambie: alias, idioma de respuesta o notas del fan. La respuesta es el fan actualizado.

curl -X PATCH https://api.lanachat.ai/v1/fans/fan_921 \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"notes": "Likes beach sets, buys at night"}'

List a fan's purchases #

GET /fans/{id}/sales · can_sales_read

curl https://api.lanachat.ai/v1/fans/fan_921/sales \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
{
  "data": [
    { "sale_id": "sale_8812", "fan_id": "fan_921", "creator_id": "cr_lea", "account_id": "acc_1001", "conversation_id": "conv_1001_88231", "stars": 300, "net_cents": 390, "sent_by": "ai", "kind": "offer" }
  ],
  "next_cursor": null
}

Lista paginada de sale objects. Para totales por día, enlace o fuente, usa stats.

Import fan history #

POST /fans/import · can_fan_import

Añade fans antiguos y sus mensajes a tus registros, por ejemplo desde otra herramienta. Nunca envía mensajes a fans ni confirma compras.

curl -X POST https://api.lanachat.ai/v1/fans/import \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d @fans-history.json

Fan lists #

List fan lists #

GET /fan-lists · can_fan_read

curl https://api.lanachat.ai/v1/fan-lists \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
{
  "data": [ { "id": "vip", "name": "VIP" } ],
  "next_cursor": null
}

Create a list #

POST /fan-lists · can_chat

ParameterTypeRequiredDescription
namestringYesEl nombre que se muestra en la página Fans
curl -X POST https://api.lanachat.ai/v1/fan-lists \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name": "Win back"}'

La respuesta es la nueva lista (201).

Add or remove fans #

POST /fan-lists/{id}/members y DELETE /fan-lists/{id}/members · can_chat

ParameterTypeRequiredDescription
fan_idsarray of stringsYesLos fans a añadir o quitar
curl -X POST https://api.lanachat.ai/v1/fan-lists/vip/members \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"fan_ids": ["fan_921"]}'

DELETE usa el mismo body. Una lista o fan desconocido responde 404.

Conversations #

List conversations #

GET /conversations · can_fan_read

ParameterTypeRequiredDescription
creator_idstringNoSolo esta creadora
account_idstringNoSolo esta cuenta de Telegram
statestringNoai, human, script u off
unreadbooleanNotrue: solo conversaciones con mensajes de fan sin leer
limit, cursornumber, stringNoPaginación
curl "https://api.lanachat.ai/v1/conversations?creator_id=cr_lea&unread=true" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
{
  "data": [
    { "id": "conv_1001_88231", "fan_id": "fan_921", "creator_id": "cr_lea", "account_id": "acc_1001", "state": "ai", "status": { "tag": "active", "reason": null }, "unread": 2, "last_message_at": "2026-10-06T14:02:51Z", "spent": { "stars": 1450, "net_cents": 1885 }, "source_link_id": "lnk_3" }
  ],
  "next_cursor": null
}

Get a conversation #

GET /conversations/{id} · can_fan_read

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

La respuesta es el conversation object; state indica quién responde.

Read messages #

GET /conversations/{id}/messages · can_fan_read

ParameterTypeRequiredDescription
translatestringNoUn código de idioma, por ejemplo en: cada mensaje también lleva traducción
limit, cursornumber, stringNoPaginación, el más nuevo primero
curl "https://api.lanachat.ai/v1/conversations/conv_1001_88231/messages?limit=2" \
  -H "Authorization: Bearer $LANACHAT_TOKEN"
{
  "data": [
    { "id": "msg_77120", "from": "creator", "sent_by": "ai", "text": "Made this one this morning…", "media": [ { "id": "med_5521", "locked": true, "stars": 300 } ], "at": "2026-10-06T14:02:51Z" },
    { "id": "msg_77119", "from": "fan", "text": "show me more 😍", "reactions": [], "at": "2026-10-06T14:02:10Z" }
  ],
  "next_cursor": "eyJpZCI6Im1zZ183NzExOCJ9"
}

sent_by puede ser ai, human (con member_id) o script.

Send a message #

POST /conversations/{id}/messages · can_chat

ParameterTypeRequiredDescription
textstringSí, o mediaEl texto, como la creadora
mediaarrayNoMedia de Vault: id y stars para venderla bloqueada a ese precio
send_atstring o nullNoHora ISO 8601 para programar (hasta 7 días); null envía ahora
curl -X POST https://api.lanachat.ai/v1/conversations/conv_1001_88231/messages \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"text": "Only for you, tonight 🔥", "media": [{"id": "med_5522", "stars": 250}], "send_at": null}'
{ "id": "msg_77121", "from": "creator", "sent_by": "human", "token_id": "tok_31", "status": "queued", "at": "2026-10-06T14:03:30Z" }
  • Un mensaje enviado por la API cuenta como enviado por persona (sent_by: "human", con el token que lo envió) y toma el control de la conversación (state: "human") hasta que la liberes.
  • status pasa por queued, sent y luego read; failed lleva el motivo de Telegram (por ejemplo flood wait).
  • send_at programa el mensaje (hasta 7 días).

React to a message #

POST /conversations/{id}/reactions · can_chat

ParameterTypeRequiredDescription
message_idstringSíEl mensaje del fan
emojistringSíLa reacción
onbooleanSítrue la añade, false la quita
curl -X POST https://api.lanachat.ai/v1/conversations/conv_1001_88231/reactions \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"message_id": "msg_77119", "emoji": "❤️", "on": true}'

Take over #

POST /conversations/{id}/takeover · can_chat

curl -X POST https://api.lanachat.ai/v1/conversations/conv_1001_88231/takeover \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
{ "id": "conv_1001_88231", "state": "human", "taken_by": "tok_31", "taken_at": "2026-10-06T14:04:00Z" }

La IA deja de responder a este fan hasta que devuelvas la conversación.

Give back to the AI #

POST /conversations/{id}/release · can_chat

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

La respuesta es la conversación con state: "ai". Una conversación en off por seguridad no puede devolverse (409).

Run a script #

POST /conversations/{id}/script · can_chat

ParameterTypeRequiredDescription
script_idstringSíUn script de la misma creadora, ver Scripts
curl -X POST https://api.lanachat.ai/v1/conversations/conv_1001_88231/script \
  -H "Authorization: Bearer $LANACHAT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"script_id": "scr_204"}'

Mientras se ejecuta, el state de la conversación es script.

Mark as read #

POST /conversations/{id}/read · can_chat

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

El unread de la conversación vuelve a 0.

Las últimas novedades de Lana en Telegram

Novedades e invitaciones a la beta, primero en el canal.