Developer documentation

Build with sasuAI

One REST endpoint, one API key, pay-as-you-go by the token. Send a conversation, get an answer back — streaming or all at once.

Introduction

The sasuAI API gives your own application direct access to the same model that powers sasuschat's chatbots. It speaks plain JSON over HTTPS, so any language that can make an HTTP request can use it — no SDK required.

BASE https://chat.sasusync.com/v1
  • Billing is prepaid credit, metered per token — no subscription, no minimum.
  • Every new account starts with 0.50 GHS of free credit, enough to try it properly.
  • Keys are shown once and stored only as a hash. Revoke any key instantly from your dashboard.

Using an AI coding agent? Point Claude, Cursor, or Copilot at https://chat.sasusync.com/docs/agent.md — a plain-text integration brief it can read directly and implement from, no copy-pasting required.

Authentication

Every request carries your secret key in an Authorization header. Keys start with sk-sasu-.

Header
Authorization: Bearer sk-sasu-your-key-here

Keep keys server-side. A key in browser or mobile code can be read by anyone who opens developer tools, and every call they make is billed to you. Put sasuAI calls behind your own backend endpoint.

Getting a key

  1. Create an account — or log in if you already have one.
  2. Open sasuAI API in the dashboard sidebar.
  3. Name a key and click Create key, then copy it — it is never shown again.

Quickstart

Your first call, in seven languages. Each one sends a single user message and prints the reply.

curl https://chat.sasusync.com/v1/chat/completions \
  -H "Authorization: Bearer $SASUAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "sasuai-core",
    "messages": [
      {"role": "user", "content": "Write a one-line welcome message."}
    ]
  }'

The response

200 OK
{
  "id": "chatcmpl-1757000000-a1b2c3d4",
  "object": "chat.completion",
  "created": 1757000000,
  "model": "sasuai-core",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Welcome aboard — glad you're here!" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 14, "completion_tokens": 9, "total_tokens": 23 }
}

Chat completions

POST /v1/chat/completions

Generates a reply for a conversation. Send the whole conversation each time — the API is stateless and keeps no history between calls.

Request body

FieldTypeDescription
messages required array The conversation so far, oldest first. Up to 40 messages and 24,000 characters in total.
model string Which model to use. Defaults to sasuai-core.
stream boolean Set true to receive the answer token by token. Defaults to false.

Message object

FieldTypeDescription
role required string One of system, user, or assistant. A leading system message sets the behaviour and tone for the whole conversation.
content required string The text of the message.

A multi-turn conversation

JSON
{
  "model": "sasuai-core",
  "messages": [
    { "role": "system",    "content": "You are a support agent for Acme Ltd. Be brief." },
    { "role": "user",      "content": "Do you ship to Kumasi?" },
    { "role": "assistant", "content": "Yes, next-day delivery to Kumasi." },
    { "role": "user",      "content": "How much does that cost?" }
  ]
}

Response fields

FieldDescription
idUnique id for this completion.
modelThe model that answered.
choices[0].message.contentThe generated reply.
choices[0].finish_reasonstop when the model finished on its own.
usageToken counts for the call — what you were billed on.

Streaming

Set "stream": true and the reply arrives as server-sent events, so you can render text as it is written instead of waiting for the whole answer. Each event is a line beginning data:; the stream ends with data: [DONE].

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"sasuai-core",
       "choices":[{"index":0,"delta":{"content":"Welcome"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"sasuai-core",
       "choices":[{"index":0,"delta":{"content":" aboard"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"sasuai-core",
       "choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]

Streamed calls are billed for what was produced. If you disconnect halfway through, you pay for the tokens generated up to that point, not the whole reply.

Models

GET /v1/models

Lists the models available to your key, with live pricing.

ModelBest forContext
sasuai-core Support chat, summarising, drafting, classification and extraction. 24,000 chars per request
cURL
curl https://chat.sasusync.com/v1/models \
  -H "Authorization: Bearer $SASUAI_API_KEY"

Errors

Failures return a JSON body with an error object and a matching HTTP status.

Error body
{
  "error": {
    "message": "Invalid or revoked API key.",
    "type": "authentication_error",
    "code": null
  }
}
StatusTypeWhat it means
400invalid_request_errorSomething in the request body is missing or malformed — check messages.
401authentication_errorThe key is missing, mistyped, or revoked.
402insufficient_quotaYour credit balance is empty. Top up to resume.
429rate_limit_errorToo many requests too quickly. Back off and retry.
502server_errorThe model could not complete the request. Safe to retry.

Pricing & credits

You are billed per token — roughly four characters of text — with input priced lower than output. Credits never expire, and calls stop cleanly at a zero balance rather than running up a bill.

Model
sasuai-core
sasuAI Core
Input
20
GHS per 1M tokens
Output
60
GHS per 1M tokens

Checking what a call cost

Every response carries a usage block with the exact token counts used for billing. Your dashboard's sasuAI API page shows the same figures per call, alongside your balance and full credit history.

Topping up

Add credit from the dashboard in a few taps — payment is by mobile money, and the balance is available the moment payment confirms.

Rate limits

Limits are per key and generous enough for normal production traffic.

EndpointLimit
POST /v1/chat/completions120 requests per minute · 5,000 per day
GET /v1/models60 requests per minute

Exceeding a limit returns 429. Retry with exponential backoff — wait a second, then two, then four — rather than retrying immediately in a loop.

Best practices

  • Keep the key on your server. Never ship it in browser, mobile, or desktop code.
  • Use one key per environment. Separate keys for staging and production mean you can revoke one without downtime for the other.
  • Trim old turns. You pay for every message you resend, so drop the parts of a long conversation the model no longer needs.
  • Put instructions in a system message. Tone, format and rules belong there, not repeated in every user message.
  • Set a timeout and retry on 429 and 502. Both are transient; 400 and 401 are not — fix those instead of retrying.
  • Stream anything long. Users see the first words in under a second, which reads as far faster than the same answer delivered whole.

Questions?

Email [email protected] — we answer developer questions directly.

Calling your chatbot directly

This is a different, second API from everything above — every chatbot you create already has its own conversational endpoint, the same one the embed widget calls. No sasuAI key, no per-token billing: it's scoped by the chatbot's own public_id (shown on its card in the dashboard) and metered against that chatbot's plan limits instead. Reach for this when you're building your own chat UI — a native app, a Slack bot, a support console — rather than dropping in the widget script tag.

POST /api/chat/<public_id>
cURL
curl https://chat.sasusync.com/api/chat/YOUR_CHATBOT_PUBLIC_ID \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Do you ship internationally?",
    "history": []
  }'

The response is plain streamed text, not JSON — read the body as it arrives and render it as-is; there's no envelope to parse.

Request body

FieldTypeDescription
message string The visitor's message. Optional if image is present.
history array Prior turns, oldest first: [{"role": "user"|"assistant", "content": "..."}]. Stateless — resend it every call.
image string Optional. A base64 data URI (data:image/png;base64,...) — never a link. Routes this turn to the vision model automatically. Max ~4MB.

Leads

If the chatbot has lead capture on, POST the same shape to /api/chat/<public_id>/lead with {"name", "email", "phone", "note"} (at least one of the first three) — it returns JSON, not a stream.

CORS is open on this endpoint for the widget's sake, so it's safe to call from your own frontend too — no key to leak. Calling it from your own backend works the same way, just without an Origin header to worry about. If you've restricted the chatbot's allowed origins in its settings, calls from a browser on a different origin are rejected; server-to-server calls are unaffected.

Errors & limits

404 unknown or disabled chatbot · 400 bad request body · 403 origin not allowed · 429 this chatbot or your account has hit its message limit for now — chatbots have their own daily ceiling independent of the account's monthly one, so a burst against one bot can't spend a whole month's quota at once.