Developer Documentation
SentX API — v3.0
The SentX API gives you programmatic access to SentX 3.0: an assistant that thinks in steps, searches the web on its own, and builds real deliverables — documents, diagrams, charts, and images — as objects you can download, reference, and iterate on across turns.
Base URL:
https://api.sentx.ai/v3Drop-in compatible: works with any OpenAI SDK (Python, JS, curl) and every OpenAI-compatible client. All 3.0 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.0 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|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).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.