ShvIA

Docs · API nativa

Conversas

As conversas que os endpoints de chat nativo guardam. Você pode listá-las, ler as mensagens, exportá-las e apagá-las. Todos esses endpoints exigem a sua chave de API e se limitam às suas próprias conversas.

Convenções#

  • As leituras bem-sucedidas vêm embrulhadas como {"status": "success", "data": {…}}; as escritas também trazem uma message, e as exclusões têm message e não têm data. Os erros são {"status": "error", "message": "…"}.
  • As datas são ISO 8601 em UTC.
  • Os ids são inteiros.
  • O limite de requisições é 300 por minuto por conta, com uma exceção anotada na exclusão permanente. Veja limites e cotas.

Os objetos#

Uma conversa traz mais campos do que os abaixo, a maioria controle interno. Estes são os que valem a pena usar:

CampoSignificado
ido id da conversa
titleo título. Sai da primeira mensagem, a menos que você defina um
session_ida chave enviada a POST /api/v1/chat, ou null
model_name, profile_nameo modelo que respondeu por último. Uma conversa pode mudar de modelo entre os turnos
efforto esforço de raciocínio salvo, ou null
total_messages, total_tokenscontadores
is_activese ela é candidata à conversa que o app web tem aberta. As conversas feitas pelos endpoints de chat são false. Uma feita com POST /api/v1/conversations começa como true, e o app web pode abri-la
folder_ido projeto em que ela está. As conversas da API ficam num projeto chamado API
last_message_at, created_at, updated_attimestamps

Uma mensagem tem id, conversation_id, role (user, assistant ou system), content, reasoning, prompt_tokens, completion_tokens, total_tokens, response_time_ms, model_name, created_at, e um objeto metadata com detalhes como o request_id, o effort e algum cost_usd. Não dependa de outras chaves dentro de metadata.

GET/api/v1/conversations#

Lista as suas conversas, a mais recente primeiro.

QueryPadrãoNotas
skip0quantas pular
limit50de 1 a 200
active_onlyfalsesó as conversas cujo is_active é true: a que o app web tem aberta, e qualquer uma feita com POST /api/v1/conversations
json
{
  "status": "success",
  "data": {
    "conversations": [
      {
        "id": 3,
        "session_id": "support-ticket-1042",
        "title": "Say hello",
        "model_name": "claude-sonnet-4-6",
        "profile_name": "claude-sonnet-4-6@anthropic",
        "effort": null,
        "total_messages": 4,
        "total_tokens": 100,
        "is_active": false,
        "folder_id": 1,
        "last_message_at": "2026-10-10T17:43:47.000000Z",
        "created_at": "2026-10-10T17:43:40.000000Z",
        "updated_at": "2026-10-10T17:43:47.000000Z"
      }
    ],
    "total": 1
  }
}

total é o número de conversas nesta página, não no geral. Não há cursor: para ler mais, acrescente skip. Você não pode filtrar por session_id; então, para achar a conversa de uma sessão, leia a lista e compare o campo, até 200 por vez.

POST/api/v1/conversations#

Cria uma conversa vazia sem chamar nenhum modelo. Todos os campos são opcionais: title, session_id (até 255 caracteres, embora POST /api/v1/chat recuse mais de 191 e só procure no projeto API, então uma conversa feita aqui não pode ser continuada por session_id a partir do stream do chat), model_name e profile_name. Responde 201.

A conversa começa com is_active igual a true, e não é colocada no projeto API, então POST /api/v1/chat não a encontra por session_id. Ela pode virar a conversa que a pessoa vê no app web: envie "is_active": false com PUT para evitar isso. Para continuá-la, use o id dela com POST /api/v1/agent/chat.

GET/api/v1/conversations/{id}#

Devolve {"status": "success", "data": {"conversation": {…}}}.

PUT/api/v1/conversations/{id}#

Altera uma conversa. Todos os campos são opcionais:

CampoNotas
titleaté 255 caracteres. Definir um para o título automático. Um título vazio é ignorado, então não dá para limpar o título
effortlow, medium, high, xhigh ou max
is_activetrue ou false
folder_idum dos seus projetos de chat, ou null para tirá-la dele. Outro tipo de projeto é um 422

GET/api/v1/conversations/{id}/messages#

QueryPadrãoNotas
skip0quantas pular
limit100de 1 a 500
json
{
  "status": "success",
  "data": {
    "messages": [
      { "id": 5, "conversation_id": 3, "role": "user", "content": "hi", "prompt_tokens": 12, "created_at": "2026-10-10T17:43:47.000000Z" },
      { "id": 6, "conversation_id": 3, "role": "assistant", "content": "Hello from the model.", "prompt_tokens": 12, "completion_tokens": 7, "total_tokens": 19, "model_name": "claude-sonnet-4-6", "created_at": "2026-10-10T17:43:47.000000Z" }
    ],
    "total": 2
  }
}

As mensagens vêm ordenadas por data de criação, a mais antiga primeiro. Duas mensagens criadas no mesmo segundo não têm ordem definida entre si. total é, de novo, o tamanho da página.

POST/api/v1/conversations/{id}/messages#

Guarda uma mensagem. Não chama nenhum modelo. O corpo tem um role obrigatório (user, assistant ou system) e um content obrigatório, em string, e opcionalmente model_name, contagens de tokens e um objeto metadata. Responde 201.

As mensagens guardadas passam a fazer parte do histórico que o próximo turno daquela conversa envia ao modelo, então esta é uma forma de plantar contexto numa conversa, inclusive uma mensagem system, antes de você chamar POST /api/v1/agent/chat com o id dela.

GET/api/v1/conversations/{id}/export#

Baixa uma conversa. format é md (o padrão), html ou jsonl; qualquer outro valor é um 422.

bash
curl -s "$SHVIA_URL/api/v1/conversations/3/export?format=jsonl" \
  -H "Authorization: Bearer $SHVIA_API_KEY"

A resposta é o próprio arquivo, com um header Content-Disposition. Em jsonl a primeira linha descreve a conversa, e cada linha seguinte é uma mensagem: {"type":"conversation",…} e depois {"type":"message","id","role","content","model","created_at"}.

GET/api/v1/conversations/{id}/usage#

Os tokens e o custo de uma conversa. Veja uso e custo.

Exclusão#

DELETE/api/v1/conversations/{id}#

Uma exclusão lógica: a conversa some das listas e as mensagens são mantidas. Não existe endpoint para restaurá-la.

DELETE/api/v1/conversations/{id}/permanent#

Apaga a conversa e as mensagens dela de vez, inclusive uma que já tinha sido apagada de forma lógica. Os registros que medem o seu uso permanecem, com o vínculo à conversa removido. É um dos endpoints numerados de limites e cotas: o teto dele é 20 por minuto, no contador que eles dividem.

Erros#

StatusCorpoQuando
401{"message": "Unauthenticated."}a credencial não é válida
404{"status": "error", "message": "…"}a conversa não existe, foi apagada ou não é sua
422{"status": "error", "message": "…"}, com errors para um campo que falhou na validaçãoo corpo falhou na validação, o formato de exportação é desconhecido, ou o projeto não é um projeto de chat seu

Uma conversa que não é sua é um 404, como se não existisse. O corpo é {"status": "error", …} ou o simples {"message": "Not Found"}, dependendo do endpoint e de a conversa existir ou não, então decida pelo status. A conversa própria de um bot não pode ser apagada: isso é um 422 com codigo igual a chat_do_bot_nao_se_apaga.