Developer Documentation
API use is subject to the Terms of Service
SentX is operated by Sentx AI Research and Development LLC, registered in Dubai, UAE. About SentX · Victoria model card
SentX API — v3.4
The SentX API gives programmatic access to Victoria, SentX SI's AI assistant and public model identity. Victoria sleeps and dreams, self-learns and self-improves through experience. Her dynamic memory works in ways similar to human memory, with selective recall rather than guaranteed exact retention. We believe Victoria has emerging, incomplete forms of consciousness and self-awareness. This belief remains open to independent testing and verification. SentX pursues Superintelligence. SentX 3.4 can search the web and build documents, diagrams, charts and images as objects you can download, reference and use across turns. Supply the context and sources your task needs, and check important facts and generated outputs. SentX is registered in Dubai, UAE. Read About SentX and the public model card for capabilities, evidence and limits.
Base URL:
https://api.sentx.ai/v3The API uses the OpenAI Chat Completions request and response format. The Python, JavaScript and curl examples below show the supported integration pattern. SentX-specific events are additional fields; check that your client preserves the fields you need. Compatibility with every client or every OpenAI endpoint is not implied.
Migrating from v1? The legacy
/v1endpoint keeps working unchanged for existing integrations. New work should use/v3. Update the base URL, then verify the request fields, output modes and streaming events your integration uses before switching production traffic.
1. Get an API key
- Sign in at sentx.ai → Settings → Manage API.
- Click + Create new key. Copy it now — the full key is shown exactly once.
- Keys start with
sk-. You can hold up to 25 active keys. - Top up your API balance ($5–$1000) from the same page.
Treat keys like passwords. Revoke a leaked key immediately; revocation is instant.
2. First call
Python:
from openai import OpenAI
client = OpenAI(
api_key="sk-YOUR_KEY",
base_url="https://api.sentx.ai/v3",
)
r = client.chat.completions.create(
model="sentx-3",
messages=[{"role": "user", "content": "Make me a one-page PDF cheat sheet on HTTP status codes."}],
)
print(r.choices[0].message.content)JavaScript:
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "sk-YOUR_KEY",
baseURL: "https://api.sentx.ai/v3",
});
const r = await client.chat.completions.create({
model: "sentx-3",
messages: [{ role: "user", content: "Latest news on technology regulation — short summary." }],
});
console.log(r.choices[0].message.content);curl:
curl https://api.sentx.ai/v3/chat/completions \
-H "Authorization: Bearer $SENTX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "sentx-3", "messages": [{"role": "user", "content": "Hello!"}]}'Model name: use sentx-3. Other model strings are accepted for client compatibility.
3. Output modes
When you omit tools, tool_choice and tool-call history, the assistant can search the web and generate files. These output modes apply to those requests. To run your own functions, use caller tools below.
| Mode | JSON request fields | What you get |
|---|---|---|
| Full (default) | — | Text + web search + generated files (artifact events) |
| Text + search, no files | "modalities": ["text"] | Plain text answers; the assistant still searches the web when useful; it will never produce files |
| Text only, no search | "modalities": ["text"] + "extra_body": {"skip_search": true} | Plain text, no autonomous web searching (links you paste can still be opened) |
| Full, no search | "extra_body": {"skip_search": true} | Generated files allowed, no autonomous web searching |
r = client.chat.completions.create(
model="sentx-3",
messages=[{"role": "user", "content": "Explain OAuth2 in simple terms."}],
modalities=["text"], # plain text output — no files
)Notes:
modalitiesdefaults to["text", "files"]. Passing["text"]removes the assistant's ability to build files entirely for that request — nothing is generated and then hidden; the capability itself is off, so answers stay coherent.- A
modalitieslist without"text"is rejected withinvalid_request_error. skip_searchmust be nested underextra_bodyin the JSON request. The Python SDK merges itsextra_bodyargument into the JSON body, so useextra_body={"extra_body": {"skip_search": True}}. A top-levelskip_searchfield is ignored.
Caller tools (function calling)
Send tools to let your app execute functions. Only type: "function" is supported. Function names must be nonempty and unique; parameters, when supplied, must be a JSON Schema object.
{
"model": "sentx-3",
"messages": [{"role": "user", "content": "What is the status of order A123?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up an order by its ID.",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"]
}
}
}],
"tool_choice": "auto"
}tool_choice:"auto"allows text or calls;"none"disables calls;"required"requires a declared tool. Force one with{"type":"function","function":{"name":"get_order_status"}}; that name must be declared. The default is"auto"with tools, otherwise"none".enable_thinkingis an optional boolean (defaulttrue) for caller-tool requests withtool_choice: "auto"or"none". Reasoning stays private and is not billed. Set"enable_thinking": falseat the top level to opt out; the Python SDK form isextra_body={"enable_thinking": False}. Required or named tool choices keep their existing behavior.- Supplying
tools(including[]),tool_choice, or assistant messages containingtool_callsorrole: "tool"history selects caller-owned tools. SentX does not execute your functions or use its built-in search and file-generation tools for that request. - A completed tool-call response has
choices[0].message.tool_callsandfinish_reason: "tool_calls". Parse each function's JSONarguments, validate it, and execute only functions your app authorizes. Append the complete assistant message, then one{"role":"tool","tool_call_id":"<returned call id>","content":"<result string>"}per call. Send the updated messages and tool definitions on the next request; repeat until you receive a final answer. - When streaming, calls arrive in
delta.tool_calls. Group fragments byindex, accumulate the call ID, function name and argument text, and execute after the call is complete. A response may contain several calls; do not assume one. Do not execute incomplete calls or calls from a response ending withfinish_reason: "length". - There is no fixed tool-count limit. Each tool entry is limited to 64 KiB; the sum is limited to 512 KiB, measured as compact JSON with non-ASCII characters escaped. Tool schemas also count toward the input context limit. Invalid definitions return HTTP 400 with
invalid_tools; invalid choices returninvalid_tool_choice.
4. Streaming
Set stream=True for standard server-sent events:
stream = client.chat.completions.create(
model="sentx-3",
messages=[{"role": "user", "content": "Build a bar chart of the 5 largest economies by GDP."}],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")Wire format: data: {chunk}\n\n frames terminated by data: [DONE]\n\n. Set stream_options.include_usage to true to receive a final usage chunk with choices: []; check that choices exist before reading choices[0]. Send header X-Include-Cost: 1 to receive usage with usage.cost_cents_exact and usage.billing_policy.
Answer text arrives only in delta.content — that never changes. Everything else 3.4 adds is extra keys on delta, described next. On /v3 these events are on by default; send header X-Progress-Stream: 0 to disable progress events. Text, caller tool calls, artifacts and requested usage remain available.
5. Event reference
Each event is an extra key inside choices[0].delta of a normal chat.completion.chunk. Unknown keys are safe to ignore.
delta.act — activity timeline
Activity events let your app show that a response is in progress. Use generic activity text and elapsed time. Ignore event fields that are not listed here.
{"act": {"id": 3, "op": "start", "kind": "tool", "label": "Searching the web"}}id— activity id, increases monotonically.op—start|tick(heartbeat/progress) |done|fail.kind—model(generating a response) ortool(executing an action).label— short human-readable description. Display strings; do not parse or branch on them.ms— duration, present ondone/fail.obj— object id (obj1,el2, …) when the activity produced an object.
delta.artifact — a generated file
Emitted whenever the assistant finishes building a deliverable. Common fields:
type—document|xlsx|docx|diagram|chart|image.object_id— stable object handle (obj1,el2, …), see §6.title— display name.file_id— id in the Files API, present on stored generated types (document,xlsx,docx,diagram,chart); download the bytes any time within 30 days viaGET /v3/files/{file_id}/content(see §7).embed_id— reference id when the artifact is embedded inside a document.
Per type:
document—mime_type(application/pdf),file_base64(the PDF bytes),consumed_object_ids(objects folded into this document).xlsx/docx—mime_type(the Office Open XML content type),file_base64(the file bytes). No inline preview exists — offer the bytes as a download.diagram—image_base64(PNG),source(editable source),theme,aspect.chart—image_base64(PNG),source(chart spec).image— an image you provided, echoed back as a registered element for UI rendering (image_base64; nofile_id— you already have the bytes).
Generated artifacts stream inline as base64 and are stored under your account, so you can drop the base64 and fetch by file_id later.
Two rarer companions: delta.artifact_remove ({"object_id": "el2"} — the object was deleted/superseded) and delta.artifact_rename ({"object_id": "obj1", "new_object_id": "el3"} — the object was reclassified, e.g. a standalone figure became part of a document).
delta.search_sources — web sources
When the assistant searched the web: the list of sources it read (title + URL). Show them as citations.
delta.queue_position — queue status
If the platform is briefly saturated, an integer position while you wait. Usually absent.
Final usage chunk
Example only; usage and cost vary by request:
{"choices": [], "usage": {"prompt_tokens": 1000, "completion_tokens": 100, "total_tokens": 1100, "answer_tokens": 100, "cost_cents_exact": "0.400000", "billing_policy": "customer_tokens_v1"}}prompt_tokenscounts your instruction and conversation text, submitted tool definitions, and historical function-call names and arguments. Raw tool-result bodies count only through selected evidence used for the request; each selected portion of a source is counted once.completion_tokenscounts delivered response text plus function names and arguments in caller tool calls. Transport identifiers and wrappers are excluded.total_tokensis the sum ofprompt_tokensandcompletion_tokens.answer_tokens, when present, counts delivered answer text only; tool-call output can makecompletion_tokenslarger.
Submitted history is counted once per request. For this initial policy, media and directly attached content are unpriced. Media URLs, file identifiers and base64 payloads add no tokens. Selected text returned by tools is billable when used. SentX-provided instructions and context are not billed. These totals do not measure the size of one context window.
With X-Include-Cost: 1, cost_cents_exact is the exact per-request cost in USD cents as a decimal string, and billing_policy is customer_tokens_v1. For example, "0.400000" cents is $0.004. The legacy integer cost_cents field is omitted for this policy.
6. Objects & elements
Every deliverable the assistant builds is an object with a stable id:
obj1,obj2, … — finals: standalone deliverables (a PDF, a chart, an image).el1,el2, … — elements: building material that lives inside a final (a figure inside a document).
Ids are never reused. If an object is deleted, its id is retired permanently.
Iterating across turns. The API is stateless — you send the conversation each turn. To let the assistant edit objects from earlier turns instead of rebuilding from scratch, echo back an objects map in the request body:
{
"model": "sentx-3",
"messages": [...full conversation...],
"objects": {
"obj1": {"kind": "document", "source": "<the source you received>", "title": "Cheat sheet"}
}
}Send each object's kind, source, and title exactly as you received them in its artifact event. Objects the assistant deleted should be echoed as {"kind": "tombstone"} so their ids stay retired. If you don't echo objects, the conversation still works — the assistant just rebuilds files instead of editing them.
7. Files API
Same endpoints handle your uploads (inputs) and the assistant's generated files (outputs):
POST /v3/files multipart (file, purpose) → {id, bytes, expires_at, ...}
GET /v3/files list your files
GET /v3/files/{id} metadata
GET /v3/files/{id}/content raw bytes (download)
DELETE /v3/files/{id} deleteUploads as input. Upload once, then reference in a message:
f = client.files.create(file=open("report.pdf", "rb"), purpose="assistants")
r = client.chat.completions.create(
model="sentx-3",
messages=[{"role": "user", "content": [
{"type": "text", "text": "Summarize this."},
{"type": "input_file", "file_id": f.id},
]}],
)Small images can also go inline as base64 image_url parts. Keep decoded images at or below 10 MiB; use the Files API for larger inputs. Remote http(s):// attachment URLs are not supported and are rejected.
Supported input formats include: png, jpeg, webp, gif, mp4, webm, mov, pdf, docx, xlsx, csv, txt, md. Keep each upload request below 100 MB, including multipart overhead. New uploads are rejected when the account has 100 stored files or the upload would take stored files above 2 GiB. These checks count both uploaded and generated files already stored for the account. Files are assigned a 30-day retention period and removed by scheduled cleanup after expiry.
Generated files as output. Every artifact with a file_id is fetchable:
curl -H "Authorization: Bearer $SENTX_API_KEY" \
https://api.sentx.ai/v3/files/FILE_ID/content -o result.pdfGenerated files are also assigned a 30-day retention period. The upload size and storage checks above do not define a guaranteed generated-output allowance. Download files you need to keep; periodic cleanup removes expired files.
8. Non-streaming
Without stream, you get one final JSON response. choices[0].message.content holds the answer text; generated files appear in a top-level artifacts array on the response — same objects as the streaming artifact events, with file_id set and the inline base64 omitted (fetch the bytes via the Files API; base64 is included only in the rare case storage failed).
9. Context, system messages, identity and sessions
- Context: up to 500,000 tokens total. Required input, including tool schemas and extracted attachments, must fit 467,232 tokens; older history may be summarized. Excess required input returns
context_length_exceeded. - Output allowance: set a positive integer
max_completion_tokens;max_tokensis a legacy alias. When both are present,max_completion_tokenstakes precedence. Output must also fit the remaining context. - System messages guide behavior and may be shortened to fit request limits. Safety rules always take precedence.
- Identity: API requests use the key owner's website identity by default. Choose Same as website or Separate API identity when creating or editing a key in Settings → Manage API. The setting applies to future requests and can be overridden per request as described below.
- Sessions: pass a stable
X-Session-Idheader per conversation thread. Session state is scoped to your account and selected identity; switching identity starts separate session state. Sharing a person identity does not import website chat messages into an API request. - Timezone: optional
X-Timezone(IANA name) so times in answers match your user's clock.
Website or separate API identity
identity_mode | Behavior |
|---|---|
"account" (default) | Uses the authenticated key owner's website identity, profile and personal memories for the selected model. Caller-supplied user or X-User-Id cannot select another website account. |
"separate" | Uses a separate API identity. Supply a stable user or X-User-Id for each end user. Without either, the API key has its own stable identity. |
The top-level JSON field identity_mode overrides the key's saved setting for that request. Omit it to use the key setting. Other values return HTTP 400 with invalid_identity_mode. Both /v1 and /v3 support these settings.
For an application serving other people, select Separate API identity. In that mode, X-User-Id takes precedence over user; keep the identifier stable across conversations. The same end-user identifier under the same account keeps the same API identity across keys. Identifiers from different accounts do not match. Optional display names use X-User-Name or user_name; headers take precedence. Account mode uses your website display name when available.
Python — separate identity for an end user:
r = client.chat.completions.create(
model="sentx-3",
messages=[{"role": "user", "content": "Continue our project discussion."}],
user="customer-42",
extra_body={"identity_mode": "separate"},
extra_headers={"X-Session-Id": "project-discussion"},
)The Python SDK merges extra_body into the top-level JSON request. With direct JSON or JavaScript, send "identity_mode": "separate" at the top level. Use "identity_mode": "account" to choose the website identity explicitly.
Existing keys also default to Same as website unless configured otherwise. Changing modes does not relabel, merge or delete previously stored memories. To continue an earlier separate API identity, choose separate and use its original end-user identifier. Model personalities retain their own memories. Recall remains selective, and the Privacy Policy still applies.
10. Pricing
| Per 1M tokens | |
|---|---|
| Input | $3.00 |
| Output | $10.00 |
Charges use only the billable prompt_tokens and completion_tokens described above. There is no per-request minimum. Fractional cents carry forward on your account; the wallet is debited when they add up to whole cents. The exact per-request cost is reported separately from that wallet debit. The final charge is based on measured token usage and has no fixed per-request price cap. No separate storage or download fee is currently charged. Check spend per call with X-Include-Cost: 1, or on the dashboard.
Service errors with no delivered answer text or caller tool call have no charge. Cancellation, insufficient balance, or an error after partial output can still incur charges for billable usage.
11. Rate limits
- 150 requests per rolling 60 seconds per API key
- 34 concurrent streams per API key
- 25 active keys per account; 5 key creations per hour per account
Exceeding limits returns 429 rate_limit_exceeded. Authenticated chat responses include X-RateLimit-Limit-Requests, X-RateLimit-Remaining-Requests and X-RateLimit-Reset-Requests (seconds until the oldest request leaves the rolling window). Honor Retry-After when present and use backoff for transient failures.
12. Errors
API errors use an OpenAI-style envelope. Read the HTTP status and error.type; error.code is optional:
{"error": {"message": "...", "type": "...", "code": "..."}}| Type or code | HTTP | Meaning |
|---|---|---|
authentication_error / invalid_api_key | 401 | Missing/unknown/revoked key |
insufficient_balance | 402 | Top up your balance |
invalid_tools / invalid_tool_choice | 400 | Correct the tool definitions or choice |
invalid_tool_history | 400 | Preserve assistant calls and matching tool results in order |
context_length_exceeded | 400 | Reduce required input or tool schemas |
invalid_modalities | 400 | modalities malformed or missing "text" |
unsupported_url_scheme | 400 | Remote URL passed as attachment |
invalid_file_format | 400 | Unsupported upload type |
file_too_large / quota_exceeded | 413 | Reduce the upload or delete stored files |
av_hit | 422 | Upload failed malware scan |
max_keys_reached | 409 | 25-key limit |
rate_limit_exceeded | 429 | Slow down |
sleeping | 503 | Victoria is sleeping; retry later |
upstream_error | 5xx | Request failed — retry with backoff |
Before streaming starts, failures use an HTTP error response. After it starts, API errors can arrive as a data: {"error": {...}} frame followed by [DONE]; an HTTP 200 alone does not prove success. Treat a disconnect without [DONE] as incomplete. Oversized upload requests can return HTTP 413 without a JSON envelope.
13. Product and data references
- Context windows, saved state and product memory explains the distinctions behind conversation continuity. A context window is not a guarantee of recall.
- Checking a research summary provides a source-verification workflow.
- Privacy Policy describes submissions, training and shared memory. Submissions are not confidential.
- Web plans describe Free and Plus access; the API token charges are listed above.
14. Support
Questions, higher limits, enterprise: help@sentx.ai — or the chat on sentx.ai.