Developer Documentation
API use is subject to the Terms of Service
SentX API — v3.3
The SentX API gives you programmatic access to Victoria, our foundation model trained and running in Dubai, UAE. Her unique cognitive architecture supports dynamic symbolic memory, learning from experience, and original problem-solving. SentX 3.3 also searches the web and builds documents, diagrams, charts, and images as objects you can download, reference, and iterate on across turns. Our research and development in Dubai pursues AGI and solutions to consciousness and self-awareness.
Base URL:
https://api.sentx.ai/v3Drop-in compatible: works with any OpenAI SDK (Python, JS, curl) and every OpenAI-compatible client. All 3.3 features arrive as additive fields inside standard chat-completion chunks — a plain OpenAI client simply ignores them and still gets clean text.
Migrating from v1? The legacy
/v1endpoint keeps working unchanged for existing integrations. New work should use/v3. Switching is one line: change the base URL and you're done — same keys, same billing, same request shape.
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 EU AI 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
By default the assistant has its full toolset: web search plus file generation (documents, diagrams, charts, images). You can narrow that per request.
| Mode | How | 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. - Both fields also work inside
extra_bodyfor SDKs that don't pass unknown top-level fields.
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,
)
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. The final chunk carries usage; send header X-Include-Cost: 1 to add usage.cost_cents.
Answer text arrives only in delta.content — that never changes. Everything else 3.3 adds is extra keys on delta, described next. On /v3 these events are on by default; send header X-Progress-Stream: 0 if you want a bare OpenAI stream with text and artifacts only.
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
The assistant's live activity feed: what it is doing right now (thinking, running a tool, building a file).
{"act": {"id": 3, "op": "start", "kind": "tool", "label": "Searching the web", "chars": {"think": 0, "text": 0, "args": 41}}}id— activity id, increases monotonically.op—start|tick(heartbeat/progress) |done|fail.kind—model(reasoning/writing) ortool(executing an action).label— short human-readable description. Display strings; do not parse or branch on them.chars— live character counters{think, text, args}for progress display.ms— duration, present ondone/fail.obj— object id (obj1,el2, …) when the activity produced an object.
delta.step — phase rows
Coarser phase updates for long tool runs: {"sid": 2, "label": "Rendering document", "status": "active" | "done" | "error", "detail": "..."}. A UI can show these as checklist rows.
delta.step_data — expandable step output
Optional payload attached to a step: {"sid": 2, "label": "...", "content": "<text ≤20k chars>", "images": ["<base64>", ...]}. Useful for "show work" panels.
delta.reasoning_chars — thinking meter
A running integer count of the assistant's internal reasoning length for the current activity. It is a count only — reasoning text is never exposed. Use it for a live "thinking…" indicator.
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 generated types (document,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 key, 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
{"usage": {"prompt_tokens": 812, "completion_tokens": 401, "total_tokens": 1213, "cost_cents": 2}}cost_cents appears when you send X-Include-Cost: 1.
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 (≤10 MB). Remote http(s):// URLs are not supported and are rejected.
Supported input formats: png, jpeg, webp, gif, mp4, webm, mov, pdf, docx, xlsx, csv, txt, md. Limits: 25 MB per file, 500 MB cumulative, 100 live files, 30-day retention.
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 follow the same 30-day retention.
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. System messages, identity, sessions
- System messages are allowed (max 2,000 characters). Safety rules always take precedence.
- End-user identity: pass
user(body) orX-User-Id(header) with your own stable id per end user — the assistant keeps per-user memory across conversations. Optional display name viauser_nameinextra_bodyorX-User-Name. Headers win over body fields;X-*headers are Latin-1 only. - Sessions: pass a stable
X-Session-Idheader per conversation thread for best continuity. - Timezone: optional
X-Timezone(IANA name) so times in answers match your user's clock.
10. Pricing
| Per 1M tokens | |
|---|---|
| Input | $3.00 |
| Output | $10.00 |
Minimum 1¢ per request, maximum $5.00 per request, rounded half up. Generated files bill only the tokens spent building them — storage and downloads are free. Check spend per call with X-Include-Cost: 1, or on the dashboard.
11. Rate limits
- 60 requests / minute per key
- 5 concurrent streams per key
- 25 active keys, 5 key creations / hour
Exceeding limits returns 429 rate_limit_exceeded.
12. Errors
Standard OpenAI error envelope:
{"error": {"message": "...", "type": "...", "code": "..."}}| Code | HTTP | Meaning |
|---|---|---|
invalid_api_key | 401 | Missing/unknown/revoked key |
insufficient_balance | 402 | Top up your balance |
invalid_modalities | 400 | modalities malformed or missing "text" |
unsupported_url_scheme | 400 | Remote URL passed as attachment |
invalid_file_format | 400 | Unsupported upload type |
av_hit | 422 | Upload failed malware scan |
max_keys_reached | 409 | 25-key limit |
rate_limit_exceeded | 429 | Slow down |
stream_interrupted | 5xx (in-stream) | Relay broke mid-stream — retry |
internal_error | 500 | Our fault — retry with backoff |
In streams, errors arrive as a data: {"error": {...}} frame followed by [DONE].
13. Support
Questions, higher limits, enterprise: [email protected] — or the chat on sentx.ai.