Amba

AI

Invoke a registered AI prompt from the client. JSON-mode output, streaming, and per-call usage metering — your provider key stays server-side.

The client AI surface proxies a registered prompt to its configured provider and returns the upstream response. Your provider key never reaches the device — the prompt's system text, model, token ceiling, rate limit, and key all live in Amba's backend.

Only prompts marked client_invokable can be reached from the device. Register and configure prompts via the Admin AI API or the amba_ai_prompts_* MCP tools.

Endpoints

MethodPathDescription
POST/client/ai/anthropic/messagesInvoke a prompt registered against an Anthropic model.
POST/client/ai/openai/chat/completionsInvoke a prompt registered against an OpenAI model.
POST/client/ai/mistral/chat/completionsInvoke a prompt registered against a Mistral model.
POST/client/ai/prompts/:name/invokeInvoke by slug in the URL (returns the raw upstream body, no envelope).

The three vendor-shaped paths are a stable wire surface for the SDK — the actual provider is resolved from the registered prompt, so pick the path that matches how you registered the prompt. All three carry the same body shape. A prompt registered against Gemini works through any of these (or the slug path) too — the backend builds Gemini's distinct contents[] / system-instruction body for you.

Request

FieldTypeRequiredNotes
prompt_slugstringyesRegistered prompt name. (prompt_key is accepted as a legacy alias; prompt_slug wins.)
variablesobjectnoTemplate variables substituted into the prompt's {{placeholders}}.
messagesarraynoConversation history ({ role, content }). When present, supersedes variables. A message's content may be a string or an array of content blocks ({ type: 'text', text } / { type: 'image', url | data, mime? }) for vision input — see Vision.
imagesarraynoSDK convenience for vision input — each { url } or { data, mime } attaches to the last user message as an image content block. See Vision.
max_tokensintegernoOutput cap. Clamped to the prompt's configured ceiling — you can ask for less, never more.
temperaturenumbernoSampling temperature; falls back to the prompt's default.
enable_prompt_cachebooleannoOpt into Anthropic prompt caching for this call.
streambooleannoWhen true, the response is a Server-Sent Events stream (see Streaming).

Response 200

Returns the upstream provider body verbatim, wrapped in the standard { data: … } envelope:

{
  "data": {
    "id": "msg_…",
    "model": "claude-sonnet-4-5",
    "role": "assistant",
    "content": [{ "type": "text", "text": "…" }],
    "stop_reason": "end_turn",
    "usage": {
      "input_tokens": 123,
      "output_tokens": 456,
      "cache_creation_input_tokens": 0,
      "cache_read_input_tokens": 0
    }
  }
}

The OpenAI / Mistral paths return their own native chat.completion shape under data.

Every successful call records a usage event server-side, so cost is attributed per user without you instrumenting a counter.

Structured JSON output

Provider-native structured-output controls (response_format, tool_choice, …) are passed through on the registered-prompt body. To force a model to return parseable JSON, configure response_format on the prompt, or pass it through the admin invoke extra_body (allowlisted to provider-native tuning keys):

  • {"type": "json_object"} — the model returns a syntactically valid JSON object.
  • {"type": "json_schema", "json_schema": { "name": "…", "schema": { … } }} — the model returns JSON conforming to your schema (OpenAI / Mistral).

The response is still the provider's native shape; the JSON your model produced is the text inside the first content block, which you then JSON.parse.

Vision (image input)

A prompt registered against a vision-capable model can receive images. Send them as a message's content array of blocks — { type: 'text', text } and { type: 'image', url } (or { type: 'image', data, mime } for base64) — and the backend maps each block to the provider's native image format:

{
  "prompt_slug": "describe_photo",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "What is in this picture?" },
        { "type": "image", "url": "https://example.com/cat.png" }
      ]
    }
  ]
}

The web/node SDKs also accept an images convenience array ([{ url }] or [{ data, mime }]) that attaches to the last user message for you.

If the prompt's model is not vision-capable, the request returns 422 ai_model_not_multimodal rather than silently dropping the image — switch the prompt to a vision model (e.g. claude-sonnet-4-5, gpt-4o, gemini-2.5-pro) and retry. Image tokens are metered into the usual usage event.

Streaming

Pass stream: true to receive a Server-Sent Events stream instead of a buffered JSON body. The backend forwards the provider's SSE frames as they arrive (content-type: text/event-stream) and still records the final usage server-side, so cost accounting is preserved on the streamed path.

curl -N -X POST '${BASE_URL}/client/ai/anthropic/messages' \
  -H 'X-Api-Key: ${CLIENT_API_KEY}' \
  -H 'Authorization: Bearer ${SESSION_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{ "prompt_slug": "support_assistant", "variables": { "q": "How do I cancel?" }, "stream": true }'

The buffered SDK methods (Amba.ai.anthropic.messages.create(...)) decode a single JSON envelope and therefore reject stream: true — consume the SSE stream over the REST endpoint directly (or from a server function) until a streaming SDK method lands.

Errors

  • 400 INVALID_BODYprompt_slug missing.
  • 400 INVALID_NAME — prompt name empty or too long.
  • 403 NOT_CLIENT_INVOKABLE — the prompt exists but isn't marked client_invokable.
  • 404 PROMPT_NOT_FOUND — no prompt registered under that slug.
  • 422 ai_model_not_multimodal — the request included an image but the prompt's model can't accept images; switch the prompt to a vision-capable model.
  • 502 AI_GATEWAY_ERROR / 502 AI_GATEWAY_UNREACHABLE — upstream provider failure.
  • 503 GATEWAY_UNCONFIGURED — the project has no provider key registered yet.

Try it:

POST/client/ai/anthropic/messages
client auth
curl -X POST 'https://api.amba.dev/v1/client/ai/anthropic/messages' \
  -H 'Content-Type: application/json' \
  -d '{
  "prompt_slug": "support_assistant",
  "variables": {
    "user_query": "How do I cancel?"
  },
  "max_tokens": 512
}'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

Curl:

curl -X POST '${BASE_URL}/client/ai/anthropic/messages' \
  -H 'X-Api-Key: ${CLIENT_API_KEY}' \
  -H 'Authorization: Bearer ${SESSION_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{ "prompt_slug": "support_assistant", "variables": { "user_query": "How do I cancel?" }, "max_tokens": 512 }'

Reference

On this page