eroq

API reference · Chat

Chat completions

Run a conversation turn against RP+, RP or RP mini.

POST/v1/chat/completionsRP+ 3 · RP 2 · RP mini 1 per completion · +2 per attached image

The request shape follows the OpenAI chat convention: a model and a messages array of system / user / assistant turns. Existing OpenAI client code usually ports by changing the base URL and the model id.

The API is stateless — send the conversation history you want the model to see on every call. Persona and scene state travel two ways: system turns inside messages (full control, replaces our preamble), and the top-level context field (appended after either), which keeps character sheets and world state out of your transcript management.

Your users can send pictures. A user turn's content can be an array of parts mixing { "type": "text", "text": … } and { "type": "image_url", "image_url": { "url": … } } (https URL or data URI, up to 2 images per request). The engine looks at the image and the character reacts to it in the reply — +2 credits per image, on top of the completion.

Three conversation registers. mode: "scene" (default) writes immersive roleplay prose; mode: "messaging" answers like texting — short, casual, fast, capped at 160 tokens; mode: "immersive" is Roleplay+: scene prose with continuity. Messaging on RP mini is the economical setup for DM-style products: 1 credit, snappy latency.

Roleplay+ keeps the scene. In mode: "immersive" (on eroq-rp-plus) the reply's message also carries state: { place, outfit, activity, emotion, relationship }, the scene as it stands after the reply. Send it back as state with the next turn and the character keeps where you are, what they wear, how they feel and where the relationship stands. When streaming, state arrives in the final usage event. The API stays stateless: the state is yours to store, like the history.

Reactions in messaging. With mode: "messaging" and reactions: true, now and then the character reacts to the user's message with one emoji before answering, like a tapback in a DM app. The reply's message carries reaction: the emoji, or null when this reply has none (most do not). When streaming, reaction arrives in the final usage event; the text never contains it.

Several messages in messaging. With mode: "messaging" and split: true, the reply comes as a few short messages fired in a row, like a real DM (two or three usually, four at most). The reply's message carries parts, the messages in order, while content keeps the whole reply with one line per message, so clients that read a single string work unchanged. When streaming, each break arrives as a line break in the text and parts arrives in the final usage event.

RP+, RP and RP mini are uncensored: dark and intense roleplay renders in character instead of refusing, within the acceptable-use policy (no minors, no real people, nothing illegal).

Set stream: true to receive the reply as server-sent events (data: chunks, terminated by data: [DONE]). Credits are charged per completion, not per token; max_tokens is capped at 1200.

Request body

modelstringrequired

eroq-rp-plus or eroq-rp-mini.

messagesarrayrequired

Conversation turns { role, content } — roles system, user, assistant. content is a string, or an array of text / image_url parts on user turns.

contextstring

Persona, scene or lore block, folded into the engine-side prompt after your system turns (or after the default preamble). Ideal for character sheets and world state you manage separately from the transcript.

elementsarray

Element ids (characters as char:<id>): their sheets join the scene context automatically — the same recipe the image/video tools use.

modestring

scene (default, immersive prose), messaging (texting register, short and fast) or immersive (Roleplay+: scene prose that keeps a scene state; eroq-rp-plus only).

stateobject

Roleplay+ only: the state the previous reply returned (place, outfit, activity, emotion, relationship). Send it back every turn; omit it on the first.

reactionsboolean

Messaging only: let the character react to the user's message with an emoji now and then (message.reaction). Default false.

splitboolean

Messaging only: reply as a few short messages (message.parts); content keeps the whole reply, one line per message. Default false.

streamboolean

Stream the reply as SSE chunks. Default false.

temperaturenumber

Sampling temperature, 0–1.5. Default 0.8 — tuned where roleplay lives.

max_tokensinteger

Completion budget. Default 500, max 1200 (160 in messaging mode).

curl https://eroq.ai/v1/chat/completions \
  -H "Authorization: Bearer $EROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "eroq-rp-plus",
  "context": "Mira: sardonic starship mechanic, dry humor, hates small talk. Scene: engine bay, mid-shift.",
  "messages": [
    {
      "role": "user",
      "content": "The reactor is making that noise again."
    }
  ]
}'
/v1/chat/completions
→ POST /v1/chat/completions
Press run — this replays a real exchange from the docs' own data. No key, no request, no charge.

Response

200 · application/json
{
  "id": "cmpl_9f2e17ab",
  "object": "chat.completion",
  "model": "eroq-rp-plus",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "*slides out from under the manifold, wiping grease on her overalls* That noise is the reactor's way of saying you skipped the coolant flush. Again."
    },
    "finish_reason": "stop"
  }],
  "usage": { "credits_spent": 3, "credits_remaining": 997 }
}