Run models
Runs Leni / Realsage models from your prompt, optional attachments, and session context. Supports JSON and multipart as described in File uploads.
/users/run-modelsSandbox run-models: rate limit + sandbox quota apply; no credit balance check Development / production run-models: rate limit + credit gate apply; sandbox quota is not used.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
| question | string | Required | The prompt you want the model to answer. Must be non-empty after leading and trailing whitespace is removed. |
| files | array | Optional | Optional file attachments. In JSON, send an array of objects using the base64 shape described in File uploads. In multipart requests, add one or more parts named files. |
| filesBase64 | array | Optional | Optional JSON-only alias for files. Uses the same base64 object shape. When filesBase64 is present on the body, it is used instead of files so you can reserve files for multipart-only uploads. |
| sessionId | string | Optional Required for session history | You must send sessionId on every follow-up request if you want the question to be part of that session's history. Reuse the same id from a previous response so each turn is recorded in one thread and appears when you list or fetch messages for that session. When you omit sessionId with a valid API key, the service may create a new session and return its id—save that id and include it on your next request to continue the conversation. |
| tone | string | Optional | How the assistant should sound. One of: professional, friendly, authoritative, consultative, funny. Defaults to professional. |
| fastMode | boolean | Optional | When true, requests a faster response path where the upstream model supports it. Defaults to false. |
| uploadedAttachments | array | Optional | Metadata for attachments already stored (for example S3 references). This is not where you send raw file bytes—use files or filesBase64 for that. |
| userMemoryAttachmentsIds | string[] | Optional | Ids of user-memory attachments to include. If you omit this array, the service may derive ids from taggedMemoryIds. |
| orgMemoryAttachmentsIds | string[] | Optional | Ids of organisation-memory attachments to include. If you omit this array, the service may derive ids from taggedMemoryIds. |
| taggedMemoryIds | array | Optional | Memory items referenced in the prompt (for example [{ memoryType, id }]). When the explicit attachment id arrays are omitted, the service can derive them from this list. |
| customAnalyst | object | Optional | Use a custom analyst you created instead of a built-in model. Supply the analyst id and display fields; the service maps this to a custom-model request. After creating an analyst, set modelType to custom-model in user or send this object—see Custom analysts. |
| wait | boolean | string | Optional | Controls how long the gateway waits before responding. Set true or the string "true" (case-insensitive) to disable the default ~5 second HTTP deadline and wait for the full Leni response. Omit or use false to allow an early response with messageId, sessionId, and polling hints while the model may continue in the background. |
Fields inside user
After merging with your API key, the request typically carries:
- Required:
id,organisationId,modelType. - Optional:
modelId,buildingIds,leni_report_builder. - Custom analysts: use
customAnalystor configurecustom-modelper Custom analysts.
Optional files
- Multipart: append one or more parts named
files. - JSON: include a
filesorfilesBase64array using the shared base64 shape (see File uploads). Decoded files are sent asfilesparts with the rest of the payload. - Tagged memory: if you send
taggedMemoryIds, the backend can deriveuserMemoryAttachmentsIdsandorgMemoryAttachmentsIdswhen those arrays are not supplied explicitly.
Example: JSON with base64 file
{
"question": "Summarize the attached file in two sentences.",
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"organisationId": "00000000-0000-0000-0000-000000000000",
"modelType": "leniq-pro"
},
"tone": "professional",
"files": [
{
"filename": "note.txt",
"contentType": "text/plain",
"contentBase64": "SGVsbG8gd29ybGQ="
}
]
}Example: multipart (form-data)
| Key | Type | Value |
|---|---|---|
| question | Text | What is in this PDF? |
| user | Text | {"modelType":"leniq-pro"} (add ids as needed) |
| files | File | Select local file(s) |
Response deadline and polling
By default, the gateway may apply a short HTTP response deadline (about five seconds) while Leni /run-models is still running. If the upstream call has not finished in time, you can receive an early JSON payload that still identifies the persisted row in chat.message, for example messageId, sessionId, responseDeadlineReached: true, and a hint on how to poll. The model request may continue in the background.
Send wait as true (boolean or string "true") on the inbound JSON or multipart text field to disable that deadline and wait for the full Leni response. Poll with GET /users/me/chat-messages/:messageId or GET /users/me/chat-sessions/:sessionId/messages when you received a deadline response.
Response
Response JSON depends on the model and options selected. Inspect the status code and body for messages, session identifiers, and tool output.
Code examples
const res = await fetch(`${process.env.API_BASE}/users/run-models`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": process.env.LENI_API_KEY!,
},
body: JSON.stringify({
question: "What is in this PDF?",
user: { modelType: "leniq-pro" },
tone: "professional",
}),
});
const data = await res.json();Try it
Using key: leni_sk_sandbox_a3f8••••