Leni HTTP API
Run Leni analysis
Start a real-estate or finance analysis with optional session context, memory, and attachments.
POST/users/run-models
| Field | Type | Requirement | Behavior |
|---|---|---|---|
| question | string | Required | Non-empty prompt to answer. |
| sessionId | UUID | Optional | Reuse the returned session id on follow-up requests to preserve history. |
| tone | string | Optional | professional, friendly, authoritative, consultative, or funny. Defaults to professional. |
| fastMode | boolean | Optional | Requests the faster upstream path when supported. Defaults to false. |
| wait | boolean or "true" | Optional | Wait for a complete response when the run stays synchronous. A durably admitted async run still returns HTTP 202. |
| user.modelType | string | Optional | Model selection such as leniq-pro. User and organization identity still come from the API key. |
| user.modelId | string | Optional | Authorized custom model identifier when applicable. |
| customAnalyst | object | Optional | An owned custom analyst selection. |
| files / filesBase64 | array | Optional | Base64 file objects. Multipart parts named files are also supported. |
| uploadedAttachments | array | Optional | Metadata for previously stored attachments. |
| userMemoryAttachmentsIds | string[] | Optional | Owned user-memory attachment ids to include. |
| orgMemoryAttachmentsIds | string[] | Optional | Authorized organization-memory attachment ids to include. |
| taggedMemoryIds | array | Optional | Referenced memory items; attachment ids may be derived from these entries. |
Owner context
Accepted async response (HTTP 202)
Async-capable analysis is durably admitted before this response is returned. Save the exact run, message, and session identifiers. Once accepted is true, do not repeat the POST; poll the existing run instead. A message or analysis identifier is not a session identifier.
{
"accepted": true,
"status": "processing",
"runId": "<uuid>",
"messageId": "<uuid>",
"sessionId": "<uuid>",
"responseDeadlineReached": true,
"pollAfterSeconds": 2,
"hint": "The analysis was accepted and is still running. ..."
}Poll the exact accepted message
pollAfterSeconds, then call GET /users/me/chat-messages/:messageId with the returned messageId. Continue while its status is processing. On completed or failed, fetch the persisted result with POST /users/me/chat-sessions/message-responses using the same sessionId and messageId.| Message status | Meaning | Client action |
|---|---|---|
| processing | The admitted run is queued or executing. | Keep polling with backoff. |
| completed | The terminal response was persisted successfully. | Fetch the message response. |
| failed | The run reached a terminal failure. | Fetch the response for failure detail; do not clone or use an older result. |
Completed response (HTTP 200)
A synchronous completion returns HTTP 200. Set wait: true only when the caller can hold the HTTP connection, but do not assume it forces synchronous execution: a durably admitted run still returns the HTTP 202 shape above. A completed normalized response can include messageId, sessionId, quickReply, reasoning, result, success, summary, and generated-file attachments.
curl -sS -X POST "https://api.prod.ca-central-1.leni.co/users/run-models" \
-H "X-Api-Key: $LENI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"question": "Summarize portfolio occupancy drivers.",
"user": { "modelType": "leniq-pro" },
"tone": "professional",
"wait": false
}'Follow-up prompts must reuse sessionId. runId identifies durable execution only;messageId identifies the turn to poll and retrieve; sessionId identifies conversation context. Never substitute one for another.
Synchronous deadline compatibility
If an analysis uses the synchronous fallback and exceeds the gateway’s roughly five-second response deadline, the API can return HTTP 200 with responseDeadlineReached: true, messageId, and sessionId. Poll it with the same lifecycle above.