# Auto Appy AI API

Source-checked on 2026-09-22. This guide describes the checked-out implementation; deployment may be older. Backend revision before documentation: `bf02333`.

## Authentication and independent use

These APIs can be called from any server-side HTTP client; no workflow node, integration template, or Gemini call is required. Use the API host below, not the product website. The examples use fictional records and placeholders. No request shown here was sent to production during this implementation.

Create an application-specific API key through the signed-in app's **API keys** page. Supply `Authorization: Bearer <key>`, `Accept: application/json`, and `X-AutoAppy-Workspace: <central organisation UUID>`. Add `Content-Type: application/json` for JSON writes. The key is a personal credential: current application access, organisation membership and resource permissions still apply. Use a read/write key for writes; a read-only key does not become writable by selecting an organisation. Keys cannot create more keys or bypass interactive management restrictions. Set finite client timeouts, keep TLS verification enabled, and do not follow redirects with credentials.

Store the key in a server-side environment/secret store. The Postman collection has an empty `api_key` variable; set it locally as a secret. Do not export it after adding a key. The collection contains writes: send only the requests you intend to execute; do not run the whole collection against production.

## Errors and debugging

| Result | Meaning / next check |
| --- | --- |
| 200 / 201 | API read/create accepted; inspect business status in the response. |
| 202 | Work accepted asynchronously, not finished. Read its status/result. |
| 401 | Missing, invalid, expired or revoked credential; wrong auth mechanism may also cause this. |
| 403 | Wrong application key, read-only write, missing membership, role, record access, or interactive-only endpoint. |
| 404 | Wrong local ID or inaccessible record. Do not substitute an ID from another organisation. |
| 409 | Version conflict or incompatible repeated operation. Fetch current state before deciding how to proceed. |
| 413 / 422 | Payload bounds or validation failure. Inspect the direct API's `message` and `errors`. |
| 429 | Rate limit. Honor `Retry-After` when present. Do not automatically repeat a write. |
| 5xx / timeout | Dependency or server failure; a write may already have happened. Inspect state before retrying. |

Central API key checks allow up to 120 requests/minute/key by default; module validation and platform subrequests consume additional calls. Endpoint-specific limits and AI orchestration limits also apply. A successful request is not proof of WhatsApp delivery or of completed AI processing.

To isolate a bug:

1. Call the documented read endpoint directly with the same app key, central organisation and resource IDs. Record method, path, timestamp, status and a redacted response.
2. Compare with this guide and the endpoint's linked controller/request validator. If the documented contract disagrees with deployed code, record both revisions and correct the contract or implementation deliberately.
3. If direct API succeeds but the workflow fails, compare the mapped input, saved connection tag, selected action name, path/query/body mapping, and source API host. Never paste a key into an issue or application log.
4. If the API accepts work but the result is wrong, inspect the owning app's job/message/turn history and downstream provider status. The integration must preserve these distinctions.

The [route reference](ROUTES.md), [OpenAPI specification](openapi.json) and [Postman collection](postman_collection.json) describe native application operations independently of the workflow catalog. [Coverage](coverage.json) accounts for included operations and exclusions. [Lookup recipes](lookup-guide.md) provide field descriptions, pagination, complete requests, responses and error handling. Third-party adapter endpoints are internal-only and absent from all public downloads. Sensitive control-plane endpoints are excluded; the exact internal audit remains in the repository. Browser-only product routes are explicitly marked and do not imply API-key access; SSO and CSRF requirements remain enforced.

## Authentication boundaries

API root: `https://aiapi.autoappy.com`. Website: `https://ai.autoappy.com`. Key application: `auto-appy-ai`.

The machine-to-machine contract is `/api/orchestration/*`. It verifies the key centrally on every request and requires an organisation owner/admin with AI access. A read-only AI key reads supported resources; mutations require write permission. Bot/channel publication, private previews and other management operations can explicitly require interactive sign-in even with a write key.

The older `/api/ai-jobs`, `/api/faq-bots`, `/api/knowledge-bots`, `/api/product-bots`, `/api/intake-bots` and personal library endpoints use the session/JWT middleware, which **does not accept opaque `aa_key_` keys**. Use the signed-in app or supported OAuth session for those. `/api/bridge/*` uses the separately configured internal authentication and is not a public API-key substitute.

```sh
curl --fail-with-body 'https://aiapi.autoappy.com/api/orchestration/channels' \
  -H "Authorization: Bearer $AI_API_KEY" \
  -H "X-AutoAppy-Workspace: $AUTOAPPY_ORGANISATION_ID" -H 'Accept: application/json'
```

## OpenAI-compatible chat API

Use any OpenAI SDK or tool with base URL `https://aiapi.autoappy.com/v1`, an Auto Appy AI key, and your organisation ID as `organization` (sent as `OpenAI-Organization`) or `X-AutoAppy-Workspace`.

- `GET /v1/models` lists `autoappy` (the default Auto Appy model), `autoappy/<installed model>` and `assistant/<id>` for the organisation's assistants. Read or write keys.
- `POST /v1/chat/completions` takes `model`, `messages` (text, or text parts), `temperature`, `max_tokens` or `max_completion_tokens` (up to 4,096), `stream`, `stream_options.include_usage`, `reasoning_effort` and `store`. A write key is required because it runs the AI.
- Auto Appy models run on Auto Appy servers. Raw models receive exactly your messages; `assistant/<id>` first adds that assistant's instructions and reference notes.
- Responses and stream chunks follow OpenAI's shapes; errors are `{"error": {"message", "type", "code"}}` (404 `model_not_found`). An extra `autoappy` object reports timing and the request ID.
- Only metadata (model, tokens, time, key prefix) is logged; message text is stored only when `store: true`, as a chat the key owner can open in the app.
- Each completed answer is one action: 2 credits on Auto Appy models, 1 on connected provider models.

```python
from openai import OpenAI
client = OpenAI(base_url="https://aiapi.autoappy.com/v1", api_key=AI_API_KEY, organization=AUTOAPPY_ORGANISATION_ID)
print(client.chat.completions.create(model="autoappy", messages=[{"role": "user", "content": "Hello"}]).choices[0].message.content)
```

The signed-in app's `/api/ai/*` endpoints (Chat, assistants, memory, prompts, model settings) refuse API keys and are listed in the exclusions.

## OpenAI-compatible audio API

Same base URL, key and organisation as chat. Runs on Auto Appy servers; a write key is required.

- `POST /v1/audio/speech` takes `model`, `input` (up to 4,096 characters), `voice`, `response_format` (mp3, wav, opus, ogg) and `speed`. `autoappy-tts` (or `tts-1`) is the Fast model: about a fifth of real time, Hindi, Hinglish, English and more. `autoappy-tts-expressive` (or `tts-1-hd`, `gpt-4o-mini-tts`) is more natural and supports cloned voices, takes up to 600 characters and is slower than real time. `voice` accepts OpenAI names (alloy, nova, …), names such as `Priya` or `Arjun`, ids like `kokoro:hf_alpha`, or `custom:<id>` for a cloned voice. The response is the audio; `X-Audio-Seconds` and `X-Generation-Ms` report length and time.
- `POST /v1/audio/transcriptions` (and `/translations`, into English) take a multipart `file` up to 25 MB, `model` (`whisper-1` or `autoappy-stt` for Whisper large-v3 turbo, `autoappy-stt-accurate` for large-v3), `language`, `prompt` and `response_format` (json, text, verbose_json, srt, vtt).
- Requests finish within about a minute; send short recordings here and use the Voice studio for long ones. Text and audio are not stored; only metadata is logged.
- Credits per answer: 1 (Fast speech), 3 (Expressive speech), 3 (transcript), 5 (accurate transcript).

```python
client.audio.speech.create(model="autoappy-tts", voice="Priya", input="नमस्ते! आपका order ship हो गया है।").write_to_file("hello.mp3")
print(client.audio.transcriptions.create(model="whisper-1", file=open("call.mp3", "rb")).text)
```

The Voice studio's `/api/ai/voice/*` endpoints (history, cloned voices) refuse API keys and are listed in the exclusions.

## Discover bots and channels

- `GET /api/orchestration/bots`: cursor paginator, up to200 per page, optional `channel_id` filters to that channel's allowed bots. Inspect `active` and version; the directory may include inactive definitions.
- `GET /api/orchestration/bots/{bot}`: one tenant-owned definition in `data`.
- `GET /api/orchestration/channels`: non-preview channels, cursor paginator, up to100 per page.
- `GET /api/orchestration/channels/{channel}`: `data` plus `can_execute`.

Follow `next_cursor` with `?cursor=...` using the same host and path. A channel must already be created, active and configured in the signed-in AI app. Its policy selects allowed bots, default routing and handoffs. Submitting an event does not publish a bot or override channel policy.

## Submit and retrieve a turn

`POST /api/orchestration/channels/{channel}/events` accepts at most100KB:

```json
{"contract_version":"1.0","conversation_id":"website:example-session","event_id":"request-20260922-0001","subject_id":"customer:example-123","message":{"role":"user","text":"What services do you offer?","at":"2026-09-22T10:00:00Z"}}
```

Required fields are `contract_version` (exactly `1.0`), stable external `conversation_id` and `event_id` (max160), and `message` with `role` (`user` or `human`), `text` (present, max4000) and a valid date `at`. `subject_id` is optional but stable for a person (max160, letters/numbers/underscore/dot/colon/hyphen; initial character alphanumeric). Optional `initial_mode` is auto/human/assisted/external. Context accepts campaign_id, tags (up to50), journey, event and contact. History accepts up to40 `{role,text}` items. `choice_id` is supported for configured menu choices.

A duplicate event with the same payload is deduplicated within the conversation; changed payload under the same event ID conflicts. Preserve the original timestamp and text if checking an uncertain submission. A conversation cannot switch to a different subject. Human events are observations, not requests for an automatic answer.

HTTP202 means queued/processing. HTTP200 can mean an existing/completed/suppressed turn. Example response shape (illustrative):

```json
{"data":{"id":"turn-uuid","conversation_id":"internal-conversation-uuid","session_id":null,"event_id":"request-20260922-0001","status":"queued","revision":1,"mode":"auto","decision":{"bot_name":null},"error_code":null,"delivery_status":"none","result":null}}
```

Call `GET /api/orchestration/turns/{turn}` to read status and result; use a bounded delay/poll loop in your client. Do not feed a queued response into a downstream send step as though it were an answer. Suppression, stale revisions, human takeover and changed published versions can intentionally remove deliverable output. `result.messages` can include typed messages; retain the full result rather than assuming one text string. The API may queue configured handoffs; callers should understand their selected channel policy.

If your client actually delivers output, `POST /api/orchestration/turns/{turn}/receipt` accepts status sent/failed/uncertain/suppressed and optional provider_id (max160). It must reflect the real outcome; the workflow integration does not auto-acknowledge delivery.

## Person memory and other families

`GET /api/orchestration/channels/{channel}/people/{subject}/memory` returns `{revision,data,schema,events,scope:"person"}`. Memory is tenant/channel/person scoped, and the read may import existing legacy memory. Fields can be locked or cleared. Manual edits use PUT with the versioned memory contract; use the source validator and current schema before implementing writes.

Conversation reads/control, context/history, contact-field catalogs, usage and bot/channel management are listed in the route reference. Personal AI jobs are asynchronous too: their signed-in create endpoint returns a job resource, and callers read job state separately. Do not mix a personal source bot ID, an orchestration published-bot ID, an external conversation ID, and an internal turn/conversation UUID.
