Amba

AI Prompts

Manage AI providers and prompt templates — register your provider key, define versioned prompts with a model and system prompt, test-invoke them server-side, and call the raw passthrough.

These admin routes manage the AI surface for a project: register the provider key the project uses, define reusable prompt templates, and test-invoke them. End-user invocation from app code (Amba.ai.run()) is covered in the AI SDK guide; this page is the developer-side management API.

You bring your own provider key (Anthropic, OpenAI, Mistral, or Google Gemini). Register it once, then define prompts that reference it. All routes mount under /v1/admin/projects/:projectId/ai/*.

Endpoints

MethodPathDescription
POST/admin/projects/:projectId/ai/providersRegister / rotate a provider key.
GET/admin/projects/:projectId/ai/providersList registered providers.
DELETE/admin/projects/:projectId/ai/providers/:nameRevoke a provider and delete its key.
POST/admin/projects/:projectId/ai/promptsRegister or version a prompt (upsert).
GET/admin/projects/:projectId/ai/promptsList prompts.
GET/admin/projects/:projectId/ai/prompts/:nameDescribe one prompt.
POST/admin/projects/:projectId/ai/prompts/:name/invokeInvoke a named prompt server-side.
DELETE/admin/projects/:projectId/ai/prompts/:nameDelete a prompt.
GET/admin/projects/:projectId/ai/prompts/:name/budgetRead a prompt's budget + spend.
PUT/admin/projects/:projectId/ai/prompts/:name/budgetSet or clear a prompt's budget.
GET/admin/projects/:projectId/ai/prompts/:name/spendCurrent-period AI spend.
POST/admin/projects/:projectId/ai/messagesRaw provider passthrough.
POST/admin/projects/:projectId/ai/embeddingsGenerate embeddings.

Providers

Register the key for anthropic, openai, mistral, or gemini. The key is stored encrypted; the response shows only a masked preview, never the full value.

curl -X POST "https://api.amba.dev/v1/admin/projects/$PROJECT_ID/ai/providers" \
  -H "Authorization: Bearer ${DEV_TOKEN}" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "anthropic", "api_key": "sk-ant-…" }'
{ "data": { "name": "anthropic", "configured": true, "api_key_preview": "sk-ant…1234" } }

A provider can't be deleted while prompts still reference it — you get 409 PROVIDER_HAS_PROMPTS. Delete the prompts first.

Try it:

POST/admin/projects/%7B%7BprojectId%7D%7D/ai/providers
developer auth
curl -X POST 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/providers'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

POST /admin/projects/:projectId/ai/prompts

Register a prompt template. This is an upsert keyed on name: re-registering an existing name bumps its version. The referenced provider must already be registered, or you get 409 PROVIDER_NOT_REGISTERED.

Request

FieldTypeRequiredNotes
namestringyes^[a-z][a-z0-9_-]{0,127}$.
providerenumyesanthropic, openai, mistral, or gemini.
modelstringyesProvider-native model id.
system_promptstringnoSent on every invocation. null to clear.
max_tokensnumberno1–200000. Default 4096.
rate_limitobjectno{ window, max, key }. Per-key invocation cap.
client_invokablebooleannoWhen true, end-user SDK code can invoke it. Default false.
curl -X POST "https://api.amba.dev/v1/admin/projects/$PROJECT_ID/ai/prompts" \
  -H "Authorization: Bearer ${DEV_TOKEN}" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "summarize",
    "provider": "anthropic",
    "model": "claude-sonnet-4-5-20250929",
    "system_prompt": "Summarize the user message in one sentence.",
    "max_tokens": 256,
    "client_invokable": true
  }'

Response 200

{
  "data": {
    "name": "summarize",
    "version": 1,
    "provider": "anthropic",
    "model": "claude-sonnet-4-5-20250929",
    "client_invokable": true
  }
}

Try it:

POST/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts
developer auth
curl -X POST 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

GET /admin/projects/:projectId/ai/prompts

List every registered prompt with its full configuration.

{
  "data": [
    {
      "name": "summarize",
      "version": 1,
      "provider": "anthropic",
      "model": "claude-sonnet-4-5-20250929",
      "system_prompt": "Summarize the user message in one sentence.",
      "max_tokens": 256,
      "rate_limit": null,
      "client_invokable": true,
      "created_at": "…",
      "updated_at": "…"
    }
  ]
}

Try it:

GET/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts
developer auth
curl -X GET 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

GET /admin/projects/:projectId/ai/prompts/:name

Describe one prompt (same row shape as the list). 404 NOT_FOUND if it isn't registered.

Try it:

GET/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts/%7B%7BpromptName%7D%7D
developer auth
curl -X GET 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts/%7B%7BpromptName%7D%7D'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

DELETE /admin/projects/:projectId/ai/prompts/:name

Hard-delete a prompt. Any client invocation referencing the name afterwards returns 404.

{ "data": { "name": "summarize" } }

Try it:

DELETE/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts/%7B%7BpromptName%7D%7D
developer auth
curl -X DELETE 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts/%7B%7BpromptName%7D%7D'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

POST /admin/projects/:projectId/ai/prompts/:name/invoke

Invoke a registered prompt from trusted server or admin tooling. Unlike the raw /ai/messages passthrough, this route resolves the prompt by name and enforces its configured output-token cap, rate limit, and spend budget. Usage and spend are attributed to that named prompt. Server/admin invocation works when client_invokable is false; that flag only gates end-user SDK calls.

curl -X POST \
  "https://api.amba.dev/v1/admin/projects/$PROJECT_ID/ai/prompts/summarize/invoke" \
  -H "Authorization: Bearer ${DEV_TOKEN}" \
  -H 'Content-Type: application/json' \
  -d '{
    "messages": [{ "role": "user", "content": "Explain named prompt budgets." }],
    "max_tokens": 128
  }'

The request accepts the same unified invocation fields as the SDK: context, messages, max_tokens, stream, and response_format. A budget denial returns HTTP 429 with ai_budget_exceeded before the provider is called.

Try it:

POST/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts/%7B%7BpromptName%7D%7D/invoke
developer auth
curl -X POST 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/prompts/%7B%7BpromptName%7D%7D/invoke'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

Prompt budgets

Each prompt can carry a spend budget — a per-period USD ceiling on its AI cost. Once the period's spend reaches the budget, further invocations are denied with a clear ai_budget_exceeded error (HTTP 429) until the period resets — so a prompt you've exposed to your app can't run away with spend. Budgets are off by default (unlimited). When the current spend can't be read, a budgeted prompt answers 503 ai_budget_unavailable and the model is not called; retry shortly.

A budget is a hard cap, including for calls that run at the same time. Before a budgeted call reaches the model, Amba holds the most it could cost: its input size plus its max_tokens output cap, at the model's price. A call is admitted only while the period's spend, plus what calls in progress hold, plus its own maximum fits in the budget. When it finishes, the hold becomes its actual cost; a call that fails before the model answers releases its hold. So a denial can come before spend reaches the budget: the error's details carry spend_usd, reserved_usd (held by calls in progress) and call_max_usd (this call's maximum). Lower max_tokens or shorten the input to fit a nearly spent budget; a denial caused only by calls in progress carries Retry-After: 5. A stream that breaks before the model reports its usage is charged what it showed: its input (or the input bound, if the input never arrived) plus output bounded by the bytes delivered, never more than its hold. A budgeted prompt refuses calls that carry audio, video or a document (422 ai_budget_unmeterable_input): their cost depends on duration or page count, so no hold can bound it. Images and text are fine.

This is the fine-grained sibling of the project-wide spend ceiling: that caps your whole project's monthly bill; a prompt budget caps one named prompt.

budget_period is the reset cadence: monthly (default — resets the first of each UTC month), daily (resets at UTC midnight), or total (never resets — a hard lifetime cap).

PUT /admin/projects/:projectId/ai/prompts/:name/budget

Set or clear a prompt's budget. Pass budget_usd as a dollar amount, or null to remove the budget.

curl -X PUT "https://api.amba.dev/v1/admin/projects/$PROJECT_ID/ai/prompts/summarize/budget" \
  -H "Authorization: Bearer ${DEV_TOKEN}" \
  -H 'Content-Type: application/json' \
  -d '{ "budget_usd": 25, "budget_period": "monthly" }'
{ "data": { "name": "summarize", "budget_usd": 25, "budget_period": "monthly" } }

GET /admin/projects/:projectId/ai/prompts/:name/budget

Read the budget alongside the current period's spend.

{
  "data": {
    "name": "summarize",
    "budget_usd": 25,
    "budget_period": "monthly",
    "period_spend_usd": 2.25,
    "remaining_usd": 22.75,
    "exceeded": false
  }
}

GET /admin/projects/:projectId/ai/prompts/:name/spend

Current-period AI spend for the prompt, summed from every invocation's cost. Pass ?period=daily|monthly|total to inspect a different window.

{
  "data": {
    "name": "summarize",
    "period": "monthly",
    "period_start": "2026-06-01T00:00:00.000Z",
    "spend_usd": 2.25,
    "budget_usd": 25,
    "exceeded": false
  }
}

POST /admin/projects/:projectId/ai/messages

Raw passthrough — forward a provider-shaped body to your registered provider using the project's key. Useful for admin tooling and eval suites.

Request

{
  "provider": "anthropic",
  "body": {
    "model": "claude-sonnet-4-5-20250929",
    "max_tokens": 256,
    "messages": [{ "role": "user", "content": "Hello" }]
  }
}

The provider's native response is returned verbatim.

Try it:

POST/admin/projects/%7B%7BprojectId%7D%7D/ai/messages
developer auth
curl -X POST 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/messages'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

POST /admin/projects/:projectId/ai/embeddings

Generate embeddings through the registered provider. Body { provider, model, input } where input is a string or array of strings. Returns { data: { embeddings, usage } }. (Embeddings are supported on openai.)

Try it:

POST/admin/projects/%7B%7BprojectId%7D%7D/ai/embeddings
developer auth
curl -X POST 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/ai/embeddings'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

MCP tools

amba_ai_prompts_create, amba_ai_prompts_list, amba_ai_prompts_get, amba_ai_prompts_update, amba_ai_prompts_delete, and amba_ai_prompts_invoke wrap the prompt routes for agentic use. amba_ai_prompts_invoke resolves a registered prompt by name and invokes the named route, so its budget, rate limit, output-token cap, and usage attribution all apply. Pass the prompt name and a provider-shaped messages array. To test a vision prompt, pass images (each { url } or { data, mime }); they attach to the last user message and are mapped to the model's native image format. The prompt's model must be vision-capable.

amba_ai_prompts_set_budget and amba_ai_prompts_get_spend manage and inspect a prompt's spend budget — set a per-period USD ceiling, then read the live spend and remaining headroom.