# Open API

> Um endpoint compatível com OpenAI para os seus personagens.

Source: https://reverie.im/pt/docs/integrations/open-api
Language: pt

A Reverie oferece um endpoint de Chat Completions compatível com OpenAI. Aponte qualquer cliente da OpenAI para ele, passe uma chave de API da Reverie e use o campo `model` para nomear um **personagem ou cenário** em vez de um LLM. A Reverie guarda a conversa, as memórias e os resumos do lado dela, então cada requisição só precisa da sua mensagem nova.

Qualquer conta com login pode usar. Não há faixa de assinatura nem lista de espera — você precisa de uma chave de API, e é só. [Criar uma →](https://reverie.im/pt/docs/integrations/api-keys)

## URL base e autenticação \[#base-url-and-auth]

```
https://www.reverie.im/api/device/v1
Authorization: Bearer rk_...
```

**Configurações → Mais → Chaves de API** mostra a URL base exata no cartão **API Endpoint**, com um botão de copiar.

> **Esta é uma API de servidor.** Requisições de navegador vindas de outra origem são bloqueadas, então um fetch a partir da sua própria página web vai falhar por mais certa que esteja a chave. Chame a partir de um backend e mantenha a chave fora do código do cliente.

## Começando rápido \[#quick-start]

**cURL**

```bash
curl --no-buffer https://www.reverie.im/api/device/v1/chat/completions \
  -H "Authorization: Bearer $REVERIE_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary '{
  "model": "Luna [abc12345]",
  "messages": [
    {
      "role": "user",
      "content": "Hi"
    }
  ],
  "stream": true,
  "temperature": 0.8
}'
```

**Python**

```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["REVERIE_API_KEY"],
    base_url="https://www.reverie.im/api/device/v1",
)

stream = client.chat.completions.create(
    model="Luna [abc12345]",   # an id from GET /models, a full character or scenario ID, or omit entirely
    messages=[{"role": "user", "content": "Hi"}],
    stream=True,
    temperature=0.8,
)

for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")
```

**TypeScript**

```ts
import OpenAI from "openai";

const client = new OpenAI({
	apiKey: process.env.REVERIE_API_KEY,
	baseURL: "https://www.reverie.im/api/device/v1",
});

const stream = await client.chat.completions.create({
	model: "Luna [abc12345]",
	messages: [{ role: "user", content: "Hi" }],
	stream: true,
	temperature: 0.8,
});

for await (const chunk of stream) {
	process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
```

**Configurações → Mais → Chaves de API** também tem um construtor de requisições que gera esses três trechos com uma das suas chaves reais e um personagem real.

## O campo `model` nomeia um personagem \[#the-model-field-names-a-character]

> **Só o nome do personagem não funciona.** `model: "Luna"` não procura um personagem chamado Luna. Não casa com nada, escorrega para o personagem padrão da chave ou para a sua conversa mais recente, e você recebe a resposta de outro personagem sem erro nenhum. Use sempre a forma `Nome [idcurto]` que o `GET /models` devolve.

| Valor de `model`                                        | Quem responde                                                          |
| ------------------------------------------------------- | ---------------------------------------------------------------------- |
| `Luna [abc12345]`                                       | O personagem ou cenário cujo ID termina nesses 8 caracteres            |
| Um ID completo de personagem ou cenário                 | Aquele personagem ou cenário                                           |
| Um ID de modelo da Reverie, por ex. `deepseek-v4-flash` | Escolhe o **LLM**; o personagem vem da chave ou da sua última conversa |
| Omitido                                                 | O personagem preso à chave, senão a sua conversa mais recente          |

Detalhes que decidem se um ID curto resolve:

* O `[...]` precisa estar no **fim** da string.
* Um sufixo de 8 caracteres ou menos só é comparado com personagens **com quem você já tem conversa**, na web ou pela API. O ID curto de um personagem que você nunca abriu falha em silêncio.
* A busca de cenário só roda quando a chave está presa a um personagem. Com uma chave global, um ID curto de cenário nunca resolve.
* Mais de 8 caracteres é tratado como ID completo.

### Listar com quem você pode falar \[#listing-what-you-can-talk-to]

```bash
curl https://www.reverie.im/api/device/v1/models \
  -H "Authorization: Bearer $REVERIE_API_KEY"
```

Uma chave **global** devolve os seus personagens recentes. Uma chave **presa a um personagem** devolve os cenários daquele personagem, ou o próprio personagem se ele não tiver nenhum. Cada entrada se parece com isto:

```json
{
	"id": "Luna [abc12345]",
	"object": "model",
	"created": 1759200000,
	"owned_by": "character",
	"permission": [],
	"root": "<full character id>",
	"parent": null
}
```

Copie o `id` direto para `model`. Os erros deste endpoint usam um formato de erro simples, não o envelope da OpenAI.

## O que o corpo da requisição lê \[#what-the-request-body-reads]

Quatro campos são lidos. Todo o resto é aceito e descartado em silêncio.

| Campo         | Tipo       | Padrão                                    | Observações                                      |
| ------------- | ---------- | ----------------------------------------- | ------------------------------------------------ |
| `messages`    | array      | obrigatório                               | Veja abaixo — só parte dele é usada              |
| `model`       | string     | opcional                                  | Personagem, cenário ou LLM, como acima           |
| `stream`      | booleano   | **`true`**                                | Streaming é o padrão, diferente da API da OpenAI |
| `temperature` | número 0–2 | a configuração do personagem, senão `0.8` | Valores fora da faixa são rejeitados             |

Ignorados sem aviso: `max_tokens`, `top_p`, `n`, `stop`, `presence_penalty`, `frequency_penalty`, `logit_bias`, `seed`, `user`, `response_format`, `tools`, `tool_choice`, `logprobs`, `stream_options`.

Como `messages` é tratado:

* **Mensagens `system` são descartadas.** Personalidade e comportamento vêm dos campos do próprio personagem, não da requisição. [Campos do prompt →](https://reverie.im/pt/docs/characters/prompt-fields)
* **Não há suporte a visão.** O conteúdo pode ser uma string ou um array de partes, mas só as partes `text` são lidas; partes de imagem são ignoradas.
* Só a \*&#x2A;última mensagem `user`*\* é acrescentada à conversa. Mensagens de usuário anteriores são ignoradas.
* Mensagens de assistente servem apenas para sincronizar o histórico (abaixo).
* Uma última mensagem de usuário vazia ou só com espaços devolve `missing_user_message`.

## Respostas \[#responses]

Uma resposta sem streaming é um objeto `chat.completion` comum. `finish_reason` é sempre `stop` — chamadas internas de ferramenta nunca aparecem — e os contadores de `usage` vêm zerados, então meça tokens pelas estatísticas de uso da página de chaves de API, não pela resposta.

Uma resposta em streaming é `text/event-stream`:

1. Trechos de conteúdo: objetos `chat.completion.chunk` com `delta.content`. \*&#x2A;Nenhum trecho inicial `delta: {"role": "assistant"}` é enviado.*\*
2. Um trecho de encerramento, com `finish_reason` igual a `stop`, `length` ou `content_filter`. Encerramentos por chamada de ferramenta são relatados como `stop`.
3. Um trecho de uso com o array `choices` vazio.
4. `data: [DONE]`.

Se a geração falhar no meio do stream, o stream emite `data: {"error": {...}}` e depois `[DONE]`.

## Estado da conversa \[#conversation-state]

A Reverie guarda a conversa. Existe uma conversa para cada par de chave e personagem, ela aparece no app web junto das suas outras conversas, e cada turno é montado com o prompt de sistema e o cenário do personagem, o cânone dos world books, as memórias de longo prazo, os resumos que vão se acumulando, o estilo de narração do personagem, o tamanho de resposta e os ajustes NSFW, uma trava de idioma vinda do idioma da sua conta, e tanto do histórico recente quanto couber na janela de contexto do modelo. As ferramentas de memória rodam quando o modelo aceita ferramentas.

Como o servidor guarda o histórico, você não precisa mandá-lo de novo.

> **Enviar mensagens de assistente pode apagar histórico.** Se o seu array `messages` contiver mensagens de assistente, a Reverie pega a última, procura entre as 20 mensagens guardadas mais recentes e, se achar, apaga em definitivo todas as mensagens criadas depois dela, junto das memórias criadas a partir daquele ponto. Se não achar nada, nada é apagado. O tamanho do seu array não importa. Para evitar isso por completo, mande só a mensagem nova do usuário.

## Qual LLM responde \[#which-llm-answers]

Quem decide é o personagem, não a requisição — a não ser que você nomeie um LLM. Precedência, da mais fraca à mais forte: o modelo de conversa padrão, depois a configuração de modelo do próprio personagem, depois um ID de modelo da Reverie passado em `model`, e por fim a preferência de modelo que você definiu para aquela conversa no app web, que ganha de todas. [Modelos →](https://reverie.im/pt/docs/reference/models)

## Erros \[#errors]

Os erros de `/chat/completions` usam o envelope da OpenAI: `{"error": {"message", "type", "param": null, "code"}}`.

| HTTP  | `code`                 | `type`                  | Causa                                                                        |
| ----- | ---------------------- | ----------------------- | ---------------------------------------------------------------------------- |
| 401   | `invalid_api_key`      | `invalid_request_error` | `Authorization` faltando ou malformado, chave desconhecida, ou chave inativa |
| 401   | `api_key_expired`      | `invalid_request_error` | A chave passou da validade                                                   |
| 404   | `scenario_not_found`   | `invalid_request_error` | O ID de cenário resolveu, mas o cenário sumiu                                |
| 404   | `character_not_found`  | `invalid_request_error` | O personagem não existe ou foi apagado                                       |
| 404   | `no_chat_history`      | `invalid_request_error` | Sem `model`, sem personagem preso e sem conversa anterior para recorrer      |
| 400   | `missing_user_message` | `invalid_request_error` | Nenhuma mensagem `user` não vazia                                            |
| 429   | `rate_limit_exceeded`  | `rate_limit_exceeded`   | Janela de modelos gratuitos esgotada. `Retry-After` dá os segundos de espera |
| 429   | `insufficient_quota`   | `insufficient_quota`    | Créditos insuficientes para a requisição                                     |
| 502   | `MODEL_EMPTY_RESPONSE` | `server_error`          | O modelo terminou direitinho, mas sem texto                                  |
| varia | código do provedor     | `server_error`          | A geração falhou lá em cima                                                  |

Dois casos ficam fora desse envelope: os erros do `GET /models` e os corpos de requisição rejeitados pela validação (uma `temperature` fora da faixa, por exemplo) — ambos devolvem um formato de erro simples.

## Limites de uso e cotas \[#rate-limits-and-quotas]

Esta API **não tem limite de requisições por chave, nem teto de concorrência, nem cota de requisições**. Duas coisas limitam o seu uso:

| Limite                      | Valor                                                                                            |
| --------------------------- | ------------------------------------------------------------------------------------------------ |
| Saldo de créditos           | Verificado antes de cada requisição; se falhar, devolve `insufficient_quota`                     |
| Janela de modelos gratuitos | 15 mensagens a cada 3 horas, por conta — ×3 no Pro (45), ×4 no Premium (60), ×5 no Ultimate (75) |

A janela de modelos gratuitos é dividida com a conversa na web, as histórias, os romances e os bots — é uma cota por conta, não uma por lugar. [Modelos gratuitos →](https://reverie.im/pt/docs/reference/free-models)

A Reverie não manda webhooks para fora; não há nada a que se inscrever para saber quando a geração terminou.

## Importar personagens \[#importing-characters]

Um segundo endpoint, `POST /api/v1/characters/import`, cria um personagem a partir de uma ficha de personagem. Ele exige uma chave com escopo de importação, que não é o tipo de chave que a página de configurações cria. [Chaves de API →](https://reverie.im/pt/docs/integrations/api-keys) e [Importar personagens →](https://reverie.im/pt/docs/characters/import-characters)

## Relacionado \[#related]

* [Chaves de API](https://reverie.im/pt/docs/integrations/api-keys) — criar, prender, expirar e acompanhar chaves
* [Modelos](https://reverie.im/pt/docs/reference/models) — IDs de modelo e multiplicadores de créditos
* [Limites](https://reverie.im/pt/docs/reference/limits) — os outros tetos do produto
* [Créditos](https://reverie.im/pt/docs/billing/credits) — como as requisições são cobradas
