# AvA API Reference > REST API for building and running AI assistants: assistants (personas), plugins > (executable tools they call) and knowledge bases (documents they answer from). > Authenticated with a scoped API key. This file is the machine-readable copy of > https://console.ava.pathor.ai/api-docs — every heading below has a permalink into that page. - Base URL: `https://avaai.pathor.in/api/v1` - Auth header: `Authorization: Bearer ava_ai_…` - Request/response format: JSON, except the knowledge-base file upload (multipart). - Machine-readable OpenAPI 3.1: https://console.ava.pathor.ai/api-docs/openapi.json - Human page: https://console.ava.pathor.ai/api-docs - Keys are minted at https://console.ava.pathor.ai/dashboard/api_key (sign-in required). ## Contents - [Getting started](https://console.ava.pathor.ai/api-docs#start) - [Authentication](https://console.ava.pathor.ai/api-docs#auth) - [Scopes and errors](https://console.ava.pathor.ai/api-docs#scopes) - [Quickstart](https://console.ava.pathor.ai/api-docs#quickstart) - [Assistants](https://console.ava.pathor.ai/api-docs#assistants) - [POST List assistants](https://console.ava.pathor.ai/api-docs#assistants.list) — `/persona/enterprise/getAllPersonas/{sessionId}` - [POST Search assistants](https://console.ava.pathor.ai/api-docs#assistants.search) — `/persona/enterprise/searchPersonas` - [POST Get one assistant](https://console.ava.pathor.ai/api-docs#assistants.get) — `/persona/enterprise/getPersona/{sessionId}/{personaId}` - [POST Create an assistant](https://console.ava.pathor.ai/api-docs#assistants.create) — `/persona/enterprise/createPersona` - [PUT Update an assistant](https://console.ava.pathor.ai/api-docs#assistants.update) — `/persona/enterprise/updatePersona` - [DELETE Delete an assistant](https://console.ava.pathor.ai/api-docs#assistants.delete) — `/persona/enterprise/deletePersona/{sessionId}/{personaId}` - [POST Mint a share-link token](https://console.ava.pathor.ai/api-docs#assistants.share) — `/persona/enterprise/sharePersona/{customPersonaId}` - [POST Transfer ownership](https://console.ava.pathor.ai/api-docs#assistants.transfer) — `/persona/enterprise/transferOwnership/{personaId}` - [GET Voice catalog](https://console.ava.pathor.ai/api-docs#assistants.voices) — `/users/get_voice_clone` - [Plugins](https://console.ava.pathor.ai/api-docs#plugins) - [POST List plugins](https://console.ava.pathor.ai/api-docs#plugins.list) — `/users/enterprise/getallplugin/{userId}` - [POST Get one plugin](https://console.ava.pathor.ai/api-docs#plugins.get) — `/users/enterprise/getPlugin` - [POST Search plugins](https://console.ava.pathor.ai/api-docs#plugins.search) — `/users/enterprise/searchPlugin` - [POST Create a plugin](https://console.ava.pathor.ai/api-docs#plugins.create) — `/plugin/enterprise/createGlobalPlugin` - [PUT Update a plugin](https://console.ava.pathor.ai/api-docs#plugins.update) — `/plugin/enterprise/updateGlobalPlugin` - [DELETE Delete a plugin](https://console.ava.pathor.ai/api-docs#plugins.delete) — `/plugin/enterprise/deleteGlobalPlugin` - [Knowledge Base](https://console.ava.pathor.ai/api-docs#knowledge-base) - [GET List knowledge bases](https://console.ava.pathor.ai/api-docs#kb.list) — `/kb` - [POST Create a knowledge base](https://console.ava.pathor.ai/api-docs#kb.create) — `/kb` - [DELETE Delete a knowledge base](https://console.ava.pathor.ai/api-docs#kb.delete) — `/kb/{kbId}` - [POST Ingest text](https://console.ava.pathor.ai/api-docs#kb.ingestText) — `/kb/{kbId}/ingest-text` - [POST Ingest a URL](https://console.ava.pathor.ai/api-docs#kb.ingestUrl) — `/kb/{kbId}/ingest-url` - [POST Upload a file](https://console.ava.pathor.ai/api-docs#kb.ingestFile) — `/kb/{kbId}/ingest` - [GET List documents](https://console.ava.pathor.ai/api-docs#kb.documents) — `/kb/{kbId}/documents` - [DELETE Delete a document](https://console.ava.pathor.ai/api-docs#kb.deleteDocument) — `/kb/{kbId}/documents/{docId}` - [POST Query a knowledge base](https://console.ava.pathor.ai/api-docs#kb.query) — `/kb/{kbId}/query` - [GET Knowledge base stats](https://console.ava.pathor.ai/api-docs#kb.stats) — `/kb/{kbId}/stats` - [GET Bases attached to an assistant](https://console.ava.pathor.ai/api-docs#kb.personaKbs) — `/kb/persona/{personaId}` - [POST Attach a base to an assistant](https://console.ava.pathor.ai/api-docs#kb.attach) — `/kb/{kbId}/personas/{personaId}` - [PATCH Update an attachment](https://console.ava.pathor.ai/api-docs#kb.updateAttachment) — `/kb/{kbId}/personas/{personaId}` - [DELETE Detach a base](https://console.ava.pathor.ai/api-docs#kb.detach) — `/kb/{kbId}/personas/{personaId}` - [PATCH Schedule a re-crawl](https://console.ava.pathor.ai/api-docs#kb.autoRefresh) — `/kb/{kbId}/auto-refresh` - [POST Re-crawl now](https://console.ava.pathor.ai/api-docs#kb.refreshNow) — `/kb/{kbId}/refresh-now` ## Getting started Permalink: https://console.ava.pathor.ai/api-docs#start Every endpoint is JSON over HTTPS and takes a single `Authorization` header. There is no SDK to install and no handshake to complete. ```bash export AVA_API_KEY="ava_ai_live_xxxxxxxxxxxxxxxxxxxx" curl 'https://avaai.pathor.in/api/v1/kb' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Several list endpoints carry a path segment like `/:sessionId` or `/:userId`. They are vestigial — the caller is resolved from the bearer and the segment is ignored. Send any non-empty value; the console sends the literal `:dummyData`. ## Authentication Permalink: https://console.ava.pathor.ai/api-docs#auth An API key is a non-human member of an account. It carries a per-module capability map — the same shape a human teammate's access has — so a key can only do the one job it was issued for. Levels, lowest to highest: | Level | Means | |---|---| | `view` | Read: can list and fetch, cannot change anything. | | `edit` | Read & write: can create and update, but not delete. | | `manage` | Full control: can also delete, publish and transfer. | A higher level includes everything below it. **No key can ever**, at any scope: create/read/revoke API keys, manage the team, write the profile, switch accounts, take a payment, or reach a platform-admin route. Those are refused outright rather than being a grantable checkbox. ## Scopes and errors Permalink: https://console.ava.pathor.ai/api-docs#scopes When a key falls short, the 403 body names the module, the level required and the level held — you do not have to guess which scope to widen. ```json { "auth": false, "success": false, "code": "scope_denied", "module": "assistants", "required": "manage", "held": "edit", "message": "This API key has \"edit\" access to Assistants and this request needs \"manage\"." } ``` | Status | `code` | What happened | |---|---|---| | 401 | `invalid bearer token` | The key does not exist, or the header was not sent as `Bearer `. | | 403 | `key_revoked` | The key was revoked in the console. Revoking takes effect on the next request — reissue rather than trying to un-revoke. | | 403 | `key_expired` | The key passed its expiry. The message carries the date it lapsed. | | 403 | `route_forbidden` | No key may ever reach this route — key management, team, profile writes, payments, platform admin. Not a scope you can grant yourself out of. | | 403 | `scope_denied` | The key is valid but holds a lower level in this module than the request needs. The body names `module`, `required` and `held`. | | 403 | `route_not_in_scope_table` | A scoped key hit a route with no rule. Scoped keys fail closed by design: a route added tomorrow is not inherited by every key issued today. | ## Quickstart — empty account to grounded assistant Permalink: https://console.ava.pathor.ai/api-docs#quickstart Four calls, in this order. An assistant can be attached to a knowledge base only once both exist; the retrieval query at the end is how you verify the assistant is being shown what you think it is. ```bash # 1 — create a knowledge base curl -X POST 'https://avaai.pathor.in/api/v1/kb' -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" -d '{"name":"Orion product docs"}' # 2 — ingest something into it curl -X POST 'https://avaai.pathor.in/api/v1/kb//ingest-text' -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" -d '{"title":"Returns policy","text":"…"}' # 3 — create an assistant (voice _id from GET /users/get_voice_clone) curl -X POST 'https://avaai.pathor.in/api/v1/persona/enterprise/createPersona' -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Orion Support","customPersonaId":"orion-support","isPublic":false,"voice":"","tags":["Support"],"base_sys_prompt":"…"}' # 4 — attach the base to the assistant curl -X POST 'https://avaai.pathor.in/api/v1/kb//personas/orion-support' -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" -d '{"grounding_mode":"supplemental","enabled":true}' ``` ## Assistants Permalink: https://console.ava.pathor.ai/api-docs#assistants An assistant is a prompt, a voice, a set of plugins and a set of knowledge bases. Everything else in this reference hangs off one — plugins give it hands, knowledge bases give it facts. ### List assistants `POST https://avaai.pathor.in/api/v1/persona/enterprise/getAllPersonas/{sessionId}` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.list - Scope required: Assistants · Read (`assistants: view`) - Success status: 200 Every assistant the key's account can see, paginated. This is the call the console's Assistants grid makes. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `sessionId` | string | yes | Vestigial. The handler reads the caller from the bearer and ignores this segment — send any non-empty value. The console sends the literal string :dummyData. Example: `:dummyData`. | Query parameters: | Field | Type | Required | Notes | |---|---|---|---| | `isPublic` | private | public | all | no | private is what the console shows: assistants this account owns or was granted. public is the shared catalog. Default: `all`. Example: `private`. | | `isMainAgent` | all | true | false | no | false narrows to agentic tools — assistants that exist to be called by another assistant rather than talked to. Default: `all`. Example: `all`. | | `os` | string | no | Comma-separated targets: nt, android, web. Ignored when the request carries a browser Origin header — from a browser the server always widens this to web,nt,android, so a filtered list needs a server-side call. Default: `nt`. Example: `nt`. | | `page` | number | no | Default: `1`. Example: `1`. | | `limit` | number | no | Default: `50`. Example: `20`. | | `ret` | count | no | Send ret=count to get the total back without the documents. | Notes: - This response carries **no `status` field** — unlike most of the API. Branch on the HTTP status, and treat a body with no `allPersonas` array as a failure rather than as an empty account. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/persona/enterprise/getAllPersonas/:dummyData?isPublic=private&isMainAgent=all&os=nt&page=1&limit=20' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "allPersonas": [ { "_id": "66f2a1b4c5d6e70012345678", "customPersonaId": "orion-support", "name": "Orion Support", "title": "Customer support specialist", "isPublic": false, "voice": "66f1c0a4e2b1a90012ab34cd", "os": [ "nt" ], "Is_main_agent": true, "attached_kbs": [ { "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "enabled": true, "grounding_mode": "supplemental" } ], "createdAt": "2026-07-02T09:14:22.104Z" } ], "totalPersonas": 42, "currentPage": 1, "totalPages": 3 } ``` ### Search assistants `POST https://avaai.pathor.in/api/v1/persona/enterprise/searchPersonas` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.search - Scope required: Assistants · Read (`assistants: view`) - Success status: 200 The same shape as the list, filtered by a free-text term across name and title. Query parameters: | Field | Type | Required | Notes | |---|---|---|---| | `search` | string | yes | Example: `support`. | | `isMainAgent` | all | true | false | no | Default: `all`. Example: `all`. | | `os` | string | no | Default: `nt`. Example: `nt`. | | `page` | number | no | Default: `1`. Example: `1`. | | `limit` | number | no | Default: `30`. Example: `20`. | Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/persona/enterprise/searchPersonas?search=support&isMainAgent=all&os=nt&page=1&limit=20' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": true, "allPersonas": [ { "_id": "66f2a1b4c5d6e70012345678", "customPersonaId": "orion-support", "name": "Orion Support" } ], "totalPersonas": 3, "currentPage": 1, "totalPages": 1 } ``` ### Get one assistant `POST https://avaai.pathor.in/api/v1/persona/enterprise/getPersona/{sessionId}/{personaId}` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.get - Scope required: Assistants · Read (`assistants: view`) - Success status: 200 The full document, including the system prompt, attached knowledge bases and plugin ids. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `sessionId` | string | yes | Vestigial, as above. Any non-empty value. Example: `:dummyData`. | | `personaId` | string | yes | The customPersonaId — the readable id you chose at creation, not the Mongo _id. Example: `orion-support`. | Notes: - The document is under **`personaData`**, not `persona` — and the list endpoints return theirs under `allPersonas`. Three names, one object; this is the API's oldest wart. - An id the account cannot see answers **400**, not 404. The server does not distinguish “no such assistant” from “not yours”. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/persona/enterprise/getPersona/:dummyData/orion-support' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": true, "personaData": { "_id": "66f2a1b4c5d6e70012345678", "customPersonaId": "orion-support", "name": "Orion Support", "base_sys_prompt": "You handle billing and delivery questions for Orion…", "voice": "66f1c0a4e2b1a90012ab34cd", "accessible_plugin": [], "attached_kbs": [ { "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "enabled": true, "grounding_mode": "supplemental" } ] } } ``` ### Create an assistant `POST https://avaai.pathor.in/api/v1/persona/enterprise/createPersona` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.create - Scope required: Assistants · Read & write (`assistants: edit`) - Success status: 200 Mints a new assistant on the key's account. customPersonaId is unique platform-wide and is how every other call addresses it. Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `name` | string | yes | Display name. | | `customPersonaId` | string | yes | Your own stable id — slug-like, unique platform-wide. Every later call uses this, so pick something you will not want to rename. | | `isPublic` | boolean | yes | Listed in the shared catalog. false for anything account-specific. Must be present — an omitted isPublic is a 400, not a default. | | `voice` | string | yes | A voice _id from the voice catalog below. Required even for a text-only assistant. | | `tags` | string[] | yes | Send an array, even an empty one. General is appended server-side if you leave it out. | | `base_sys_prompt` | string | no | The system prompt. Capped at 5,000 characters for Android-only assistants and silently truncated past it. | | `title` | string | no | One-line role description shown under the name. | | `personality` | string | no | Free text, max 2,100 characters. Longer is a 400. | | `gender` | string | no | — | | `languages` | string[] | no | — | | `behavior` | string[] | no | — | | `os` | string[] | no | Target platforms: nt, android, web. An android-only assistant takes the 5,000-character prompt cap. | | `Is_main_agent` | boolean | no | True for an assistant people talk to. Capital I — that is the wire name. | | `is_agentic_tool` | boolean | no | True when this assistant exists to be called by another one. | | `accessible_plugin` | string[] | no | Plugin _ids this assistant may run. | | `authorised_users_email` | string[] | no | Emails granted access. Each address is sent an invitation when the assistant is created. | | `logo` | string | no | Absolute image URL. | | `voice_language` | string | no | Accent code, e.g. en-IN. | Notes: - A duplicate customPersonaId comes back as **404** with `persona already exists with …` — an unusual status for a conflict, but that is what the server sends. - The response does not echo the created document. Follow with **Get one assistant** if you need it. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/persona/enterprise/createPersona' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Orion Support", "customPersonaId": "orion-support", "title": "Customer support specialist", "isPublic": false, "voice": "66f1c0a4e2b1a90012ab34cd", "voice_language": "en-IN", "gender": "female", "languages": [ "english" ], "tags": [ "Support" ], "behavior": [ "calm", "precise" ], "base_sys_prompt": "You handle billing and delivery questions for Orion. Answer from the attached knowledge base. Confirm the order number before quoting any refund amount.", "personality": "Warm, brisk, never over-promises.", "os": [ "nt" ], "Is_main_agent": true, "is_agentic_tool": false, "accessible_plugin": [], "authorised_users_email": [], "logo": "https://cdn.example.com/orion.png" }' ``` Response `200`: ```json { "status": true, "message": "New persona has been created" } ``` ### Update an assistant `PUT https://avaai.pathor.in/api/v1/persona/enterprise/updatePersona` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.update - Scope required: Assistants · Read & write (`assistants: edit`) - Success status: 200 Partial update. Send only the fields you are changing — but read the array rule before you send one. Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `personaId` | string | yes | The customPersonaId. Named personaId in this body only; everywhere else that name means the Mongo _id. | | `base_sys_prompt` | string | no | Replaced wholesale. | | `os · languages · tags · behavior · hobbies · accessible_rag_folders` | string[] or string | no | An array REPLACES the field. A bare string APPENDS to it. Sending tags: "Support" adds one tag; sending tags: ["Support"] makes Support the only tag. | | `accessible_plugin` | string[] or string | no | Inverted from the fields above, and easy to get wrong: an array ADDS the plugin ids, a bare string REMOVES that one plugin. | | `name` | string | no | — | | `title` | string | no | — | | `isPublic` | boolean | no | — | | `voice` | string | no | — | | `logo` | string | no | — | Notes: - A personaId the key's account does not own returns **400** `unauthorized user`, not 404 — the server will not confirm whether the assistant exists. Request: ```bash curl -X PUT 'https://avaai.pathor.in/api/v1/persona/enterprise/updatePersona' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "personaId": "orion-support", "base_sys_prompt": "You handle billing and delivery questions for Orion. Confirm the order number before quoting any refund amount.", "tags": [ "Support", "Billing" ] }' ``` Response `200`: ```json { "status": true, "message": "Persona has been updated!" } ``` ### Delete an assistant `DELETE https://avaai.pathor.in/api/v1/persona/enterprise/deletePersona/{sessionId}/{personaId}` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.delete - Scope required: Assistants · Full control (`assistants: manage`) - Success status: 200 - **Destructive.** Irreversible, acts on live account data. Permanent. The assistant, its share links and its knowledge-base attachments go with it. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `sessionId` | string | yes | Vestigial. Any non-empty value. Example: `:dummyData`. | | `personaId` | string | yes | The customPersonaId. Example: `orion-support`. | Notes: - Written to your account's activity trail as `assistant.deleted`, with the name captured before the delete so the entry still reads sensibly afterwards. Request: ```bash curl -X DELETE 'https://avaai.pathor.in/api/v1/persona/enterprise/deletePersona/:dummyData/orion-support' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": true, "message": "Persona has been deleted!" } ``` ### Mint a share-link token `POST https://avaai.pathor.in/api/v1/persona/enterprise/sharePersona/{customPersonaId}` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.share - Scope required: Assistants · Full control (`assistants: manage`) - Success status: 200 Returns a con_sh_… token that lets someone talk to this one assistant without an account. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `customPersonaId` | string | yes | Example: `orion-support`. | Notes: - manage, not edit: minting a public link is a disclosure, not an edit. - A con_sh_ token is **not** an API key. It reaches one assistant, carries no scope map, and can never be widened. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/persona/enterprise/sharePersona/orion-support' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": true, "message": "Sharable persona token generated successfully", "data": "con_sh_9f2c7a1b4e08" } ``` ### Transfer ownership `POST https://avaai.pathor.in/api/v1/persona/enterprise/transferOwnership/{personaId}` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.transfer - Scope required: Assistants · Full control (`assistants: manage`) - Success status: 200 - **Destructive.** Irreversible, acts on live account data. Hands the assistant to another account by email. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `personaId` | string | yes | The Mongo _id here — the one route in this section that does not take customPersonaId. A non-ObjectId value is rejected with a 400. Example: `66f2a1b4c5d6e70012345678`. | Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `newOwnerEmail` | string | yes | Must already have an account. | | `keepAccess` | boolean | no | Leave yourself on the assistant as a full-access editor. Default: `false`. | Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/persona/enterprise/transferOwnership/66f2a1b4c5d6e70012345678' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "newOwnerEmail": "ops@example.com", "keepAccess": true }' ``` Response `200`: ```json { "status": true, "message": "Ownership of \"Orion Support\" transferred to ops@example.com", "note": "You retain full-access editor rights" } ``` ### Voice catalog `GET https://avaai.pathor.in/api/v1/users/get_voice_clone` - Permalink: https://console.ava.pathor.ai/api-docs#assistants.voices - Scope required: Voices · Read (`voices: view`) - Success status: 200 Every voice available to the account, cloned ones included. You need an _id from here before you can create an assistant at all. Query parameters: | Field | Type | Required | Notes | |---|---|---|---| | `title` | string | no | Narrow to one voice by exact title. Omit for the whole catalog. | Notes: - The array is under **`data`**, and the `_id` — not `voice_id` — is what `createPersona` wants for its `voice` field. `voice_id` is the upstream provider's own id and the assistant routes will not accept it. - Lives under the **Voices** module, not Assistants — a key scoped to assistants alone gets a 403 here. The **Assistants & knowledge** preset already includes Voices at Read. Request: ```bash curl -X GET 'https://avaai.pathor.in/api/v1/users/get_voice_clone' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": true, "message": "voice_clone fetched successfully", "data": [ { "_id": "66f1c0a4e2b1a90012ab34cd", "title": "Aria", "gender": "female", "voice_language": "en-IN", "voice_provider": "cartesia", "voice_type": "non-custom", "isPublic": true, "voice_sample_uri": "https://cdn.example.com/voices/aria.mp3" } ] } ``` ## Plugins Permalink: https://console.ava.pathor.ai/api-docs#plugins A plugin is a function definition the model is shown plus a Python body that runs when it decides to call it. Authoring one is a write; deleting one can break every assistant referencing it, so it takes Full control. ### List plugins `POST https://avaai.pathor.in/api/v1/users/enterprise/getallplugin/{userId}` - Permalink: https://console.ava.pathor.ai/api-docs#plugins.list - Scope required: Plugins · Read (`plugins: view`) - Success status: 200 The plugin catalog visible to the key's account — your own plugins plus anything published platform-wide. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `userId` | string | yes | Vestigial, like the assistant routes: the caller comes from the bearer. Any non-empty value. Example: `:dummyData`. | Query parameters: | Field | Type | Required | Notes | |---|---|---|---| | `isPublic` | public | private | all | no | private is the account's own catalog. Default: `all`. Example: `private`. | | `status` | all | approved | pending | no | Default: `all`. Example: `all`. | | `os` | string | no | nt, android, web, or all. Default: `all`. Example: `all`. | | `page` | number | no | Default: `1`. Example: `1`. | | `limit` | number | no | Default: `50`. Example: `20`. | Notes: - The collection key is **`plugin`**, singular — not `plugins`. Every list endpoint in this section uses it. - An empty result is shaped differently: `{ status: "true", message: "No plugin found", tags: […] }` with **no `plugin` key at all**. Read it as `data.plugin || []` rather than indexing straight into it. - `func_run` and `func_schema` come back **AES-encrypted**. The console decrypts them in the browser; from a server you would need to do the same. Everything else on the document is plain. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/users/enterprise/getallplugin/:dummyData?isPublic=private&status=all&os=all&page=1&limit=20' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "totalPlugins": 12, "totalPages": 1, "currentPage": 1, "plugin": [ { "_id": "66f3b2c5d6e7f80012345679", "title": "order_lookup", "name": "Order lookup", "tags": [ "commerce" ], "isPublic": false, "creator": "Orion Ltd", "os": [ "nt" ] } ], "tags": [ "new", "all", "connected" ] } ``` ### Get one plugin `POST https://avaai.pathor.in/api/v1/users/enterprise/getPlugin` - Permalink: https://console.ava.pathor.ai/api-docs#plugins.get - Scope required: Plugins · Read (`plugins: view`) - Success status: 200 One plugin, addressed by its unique title. Query parameters: | Field | Type | Required | Notes | |---|---|---|---| | `title` | string | yes | The plugin's unique title — its identity, not its display name. Example: `order_lookup`. | Notes: - `status` is the **string** `"true"` on this endpoint, not the boolean the assistant routes return. Do not branch on it — branch on the HTTP status. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/users/enterprise/getPlugin?title=order_lookup' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "true", "plugin": { "_id": "66f3b2c5d6e7f80012345679", "title": "order_lookup", "name": "Order lookup", "human_description": "Looks up an order by its reference number.", "isPublic": false, "isOwner": true } } ``` ### Search plugins `POST https://avaai.pathor.in/api/v1/users/enterprise/searchPlugin` - Permalink: https://console.ava.pathor.ai/api-docs#plugins.search - Scope required: Plugins · Read (`plugins: view`) - Success status: 200 Free-text search across plugin titles, names and descriptions. Query parameters: | Field | Type | Required | Notes | |---|---|---|---| | `search` | string | yes | Example: `order`. | | `os` | string | no | Default: `all`. Example: `all`. | | `page` | number | no | Default: `1`. Example: `1`. | | `limit` | number | no | Default: `20`. Example: `20`. | Notes: - Same empty-result shape as the list: no `plugin` key when nothing matched. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/users/enterprise/searchPlugin?search=order&os=all&page=1&limit=20' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "totalPlugins": 1, "totalPages": 1, "currentPage": 1, "plugin": [ { "_id": "66f3b2c5d6e7f80012345679", "title": "order_lookup" } ], "tags": [ "new", "all", "connected" ] } ``` ### Create a plugin `POST https://avaai.pathor.in/api/v1/plugin/enterprise/createGlobalPlugin` - Permalink: https://console.ava.pathor.ai/api-docs#plugins.create - Scope required: Plugins · Read & write (`plugins: edit`) - Success status: 200 Publishes a new plugin to the account's catalog. Every field in the required list must be present — the server checks for presence, not truthiness, so send false and [] explicitly rather than omitting them. Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `title` | string | yes | Unique identity, snake_case by convention. Also the function name the model calls. | | `name` | string | yes | Display name. | | `tags` | string[] | yes | — | | `authentication_required` | boolean | yes | When true, connection_url becomes required too. | | `os` | string[] | yes | Platforms the plugin can run on: nt, android, web. | | `human_description` | string | yes | What it does, for the person browsing the catalog. | | `ai_description` | string | yes | What it does, for the model deciding whether to call it. Say when to call it and what comes back — this is the text the assistant reasons over. | | `parameters` | object | yes | JSON-Schema object describing the arguments. | | `func_schema` | string | yes | The tool schema the model is shown, as a JSON string. | | `func_run` | string | yes | The Python body. Must define `def _run(self, …)` whose parameters match your schema. Encrypted at rest. | | `isPublic` | boolean | yes | Publish to the platform-wide catalog. | | `isAnonymous` | boolean | yes | Hide the author's name on the catalog card. | | `connection_url` | string | no | OAuth / connection endpoint. Required when authentication_required is true. | | `logo` | string | no | Absolute image URL. | | `is_agentic_tool` | object | no | { status, object } — defaults to { status: false, object: null }. | Notes: - A missing required field returns **404** with a single message naming all of them at once. A duplicate title returns **400**. - Titles are reserved platform-wide. `browser_search` and `code_interpreter` are AvA's built-ins and are rejected outright. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/plugin/enterprise/createGlobalPlugin' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "order_lookup", "name": "Order lookup", "tags": [ "commerce" ], "authentication_required": false, "os": [ "nt" ], "human_description": "Looks up an order by its reference number.", "ai_description": "Call this when the customer gives an order number and wants its status. Returns the status string and the courier's tracking URL.", "parameters": { "type": "object", "properties": { "order_id": { "type": "string", "description": "The customer's order reference." } }, "required": [ "order_id" ] }, "func_schema": "{\"name\":\"order_lookup\",\"description\":\"Look up an order by reference\",\"parameters\":{\"type\":\"object\",\"properties\":{\"order_id\":{\"type\":\"string\"}},\"required\":[\"order_id\"]}}", "func_run": "def _run(self, order_id):\n import requests\n r = requests.get(f\"https://api.example.com/orders/{order_id}\")\n r.raise_for_status()\n data = r.json()\n return {\"status\": data[\"status\"], \"tracking_url\": data[\"tracking_url\"]}\n", "isPublic": false, "isAnonymous": false, "logo": "https://cdn.example.com/plugins/order-lookup.png" }' ``` Response `200`: ```json { "status": true, "message": "plugin created successfully" } ``` ### Update a plugin `PUT https://avaai.pathor.in/api/v1/plugin/enterprise/updateGlobalPlugin` - Permalink: https://console.ava.pathor.ai/api-docs#plugins.update - Scope required: Plugins · Read & write (`plugins: edit`) - Success status: 200 Partial update, addressed by title. Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `title` | string | yes | Identifies the plugin. Cannot itself be changed here. | | `name` | string | no | — | | `human_description` | string | no | — | | `ai_description` | string | no | — | | `parameters` | object | no | — | | `func_schema` | string | no | — | | `func_run` | string | no | — | | `isPublic` | boolean | no | — | | `tags` | string[] | no | — | | `os` | string[] | no | — | | `logo` | string | no | — | Notes: - Sending any of `_id`, `userId`, `status`, `appVersion`, `createdAt` or `__v` is rejected with **404** `Invalid Body`. Strip a document you fetched before you send it back. Request: ```bash curl -X PUT 'https://avaai.pathor.in/api/v1/plugin/enterprise/updateGlobalPlugin' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "order_lookup", "ai_description": "Call this when the customer gives an order number. Returns the status, the courier and the tracking URL." }' ``` Response `200`: ```json { "status": true, "message": "plugin updated successfully" } ``` ### Delete a plugin `DELETE https://avaai.pathor.in/api/v1/plugin/enterprise/deleteGlobalPlugin` - Permalink: https://console.ava.pathor.ai/api-docs#plugins.delete - Scope required: Plugins · Full control (`plugins: manage`) - Success status: 200 - **Destructive.** Irreversible, acts on live account data. Removes the plugin from both catalogs. Assistants that referenced it lose the capability on their next turn. Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `title` | string | yes | — | Notes: - Check **List assistants** for `accessible_plugin` references first — nothing blocks the delete, and the assistants simply stop being able to call it. Request: ```bash curl -X DELETE 'https://avaai.pathor.in/api/v1/plugin/enterprise/deleteGlobalPlugin' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "order_lookup" }' ``` Response `200`: ```json { "status": true, "message": "plugin deleted successfully" } ``` ## Knowledge Base Permalink: https://console.ava.pathor.ai/api-docs#knowledge-base A knowledge base is a set of documents, chunked and embedded, that an attached assistant retrieves from at answer time. You can query one directly — the fastest way to find out whether an assistant is being shown what you think it is. **Important:** Knowledge Base needs a **scoped** key. Keys minted before scoping existed show as “Unrestricted” on the keys page and are judged by an older path allowlist that /kb was never on — every /kb call from one is a 403 route_forbidden. Reissue with a scope map and it works. ### List knowledge bases `GET https://avaai.pathor.in/api/v1/kb` - Permalink: https://console.ava.pathor.ai/api-docs#kb.list - Scope required: Knowledge Base · Read (`knowledgeBase: view`) - Success status: 200 Every knowledge base on the account, with its document count and size. Notes: - `liveSourcesCount` counts inline-tier documents — the ones that sit in the assistant's context every turn instead of being retrieved. They are the expensive ones, which is why they are counted apart from the rest. - `shared` is true for a base another account owns and granted to you. Request: ```bash curl -X GET 'https://avaai.pathor.in/api/v1/kb' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "kbs": [ { "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "name": "Orion product docs", "description": "Public manuals and the returns policy.", "docsCount": 14, "totalSize": 2841203, "liveSourcesCount": 1, "autoRefresh": { "enabled": false, "intervalDays": 3, "lastRefreshedAt": null, "nextRefreshAt": null }, "createdAt": "2026-06-19T11:02:41.882Z", "shared": false } ] } ``` ### Create a knowledge base `POST https://avaai.pathor.in/api/v1/kb` - Permalink: https://console.ava.pathor.ai/api-docs#kb.create - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 201 Returns the kbId every other call in this section takes. It is a UUID, not a Mongo _id. Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `name` | string | yes | — | | `description` | string | no | Default: `""`. | Notes: - Answers **201**, not 200 — the only endpoint in this reference that does. Branch on `res.ok`, not on `status === 200`. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/kb' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Orion product docs", "description": "Public manuals and the returns policy." }' ``` Response `201`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "name": "Orion product docs", "description": "Public manuals and the returns policy." } ``` ### Delete a knowledge base `DELETE https://avaai.pathor.in/api/v1/kb/{kbId}` - Permalink: https://console.ava.pathor.ai/api-docs#kb.delete - Scope required: Knowledge Base · Full control (`knowledgeBase: manage`) - Success status: 200 - **Destructive.** Irreversible, acts on live account data. The base, every document in it and every vector. Permanent. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Request: ```bash curl -X DELETE 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "deleted": true, "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13" } ``` ### Ingest text `POST https://avaai.pathor.in/api/v1/kb/{kbId}/ingest-text` - Permalink: https://console.ava.pathor.ai/api-docs#kb.ingestText - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 The workhorse. You extract the text, this chunks and embeds it. Use it for anything you can already read as a string. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `text` | string | yes | The document body. | | `title` | string | yes | How it is listed, and what a retrieval cites. | | `mimeType` | string | no | Default: `text/plain`. | | `source` | string | no | Free-text provenance label kept on the document. Default: `manual`. | | `mode` | auto | vector | inline | no | vector chunks and embeds it for retrieval. inline keeps it whole and hands it to the assistant every turn — right for a short policy, expensive for a manual. auto decides on length. Default: `auto`. | Notes: - An inline-tier document answers with `{ docId, mode, inlineChars, digestMethod, crawledChars }` instead of `chunksCreated`. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/ingest-text' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Returns policy 2026", "text": "Orion accepts returns within 30 days of delivery, provided the item is unused and in its original packaging. Refunds are issued to the original payment method within 5 working days of the item reaching our warehouse.", "mimeType": "text/plain", "source": "handbook", "mode": "auto" }' ``` Response `200`: ```json { "status": "ok", "docId": "b81e5c0a-7d33-4f2e-9c11-2a4f6d8e0b55", "chunksCreated": 3, "title": "Returns policy 2026", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13" } ``` ### Ingest a URL `POST https://avaai.pathor.in/api/v1/kb/{kbId}/ingest-url` - Permalink: https://console.ava.pathor.ai/api-docs#kb.ingestUrl - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 The server fetches the page, extracts its text and ingests that. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `url` | string | yes | — | | `title` | string | no | Defaults to the page title. | Notes: - A JavaScript-rendered page usually yields nothing useful. Extract the text yourself and use **Ingest text** when that happens. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/ingest-url' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/returns", "title": "Returns policy" }' ``` Response `200`: ```json { "status": "ok", "docId": "c92f6d1b-8e44-4a3f-8d22-3b5e7f9a1c66", "mode": "vector", "chunksCreated": 5, "title": "Returns policy", "url": "https://example.com/returns", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13" } ``` ### Upload a file `POST https://avaai.pathor.in/api/v1/kb/{kbId}/ingest` - Permalink: https://console.ava.pathor.ai/api-docs#kb.ingestFile - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 - Content type: `multipart/form-data` (not JSON). multipart/form-data with a `file` part and an optional `title`. PDF, DOCX, TXT and MD. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Form fields: | Field | Type | Required | Notes | |---|---|---|---| | `file` | file | yes | The multipart file part. | | `title` | string | no | Defaults to the filename. | Notes: - A **scanned** PDF has no extractable text layer and ingests as an empty document. The console OCRs those in the browser before sending; from a server, OCR first and use **Ingest text**. - Not runnable from the playground — it needs a real multipart body. The snippets below are complete. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/ingest' \ -H "Authorization: Bearer $AVA_API_KEY" \ -F "file=@./document.pdf" \ -F "title=Orion manual" ``` Response `200`: ```json { "status": "ok", "docId": "d03a7e2c-9f55-4b40-9e33-4c6f80ab2d77", "chunksCreated": 41, "title": "orion-manual.pdf", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13" } ``` ### List documents `GET https://avaai.pathor.in/api/v1/kb/{kbId}/documents` - Permalink: https://console.ava.pathor.ai/api-docs#kb.documents - Scope required: Knowledge Base · Read (`knowledgeBase: view`) - Success status: 200 Everything in the base, with per-document chunk counts and tier. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Request: ```bash curl -X GET 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/documents' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "documents": [ { "docId": "b81e5c0a-7d33-4f2e-9c11-2a4f6d8e0b55", "title": "Returns policy 2026", "source": "handbook", "mimeType": "text/plain", "chunksCount": 3, "fileSize": 1420, "mode": "vector", "createdAt": "2026-07-11T08:20:14.512Z" } ] } ``` ### Delete a document `DELETE https://avaai.pathor.in/api/v1/kb/{kbId}/documents/{docId}` - Permalink: https://console.ava.pathor.ai/api-docs#kb.deleteDocument - Scope required: Knowledge Base · Full control (`knowledgeBase: manage`) - Success status: 200 - **Destructive.** Irreversible, acts on live account data. Drops the document and its vectors. The rest of the base is untouched. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | | `docId` | string | yes | Example: `b81e5c0a-7d33-4f2e-9c11-2a4f6d8e0b55`. | Request: ```bash curl -X DELETE 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/documents/b81e5c0a-7d33-4f2e-9c11-2a4f6d8e0b55' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "deleted": true, "docId": "b81e5c0a-7d33-4f2e-9c11-2a4f6d8e0b55", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13" } ``` ### Query a knowledge base `POST https://avaai.pathor.in/api/v1/kb/{kbId}/query` - Permalink: https://console.ava.pathor.ai/api-docs#kb.query - Scope required: Knowledge Base · Read (`knowledgeBase: view`) - Success status: 200 Semantic search over the base — the same retrieval an assistant runs, exposed directly. Use it to check what your assistant would actually be shown. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `query` | string | yes | Natural language. | | `topK` | number | no | Chunks to return. Capped at 20. Default: `5`. | Notes: - A read behind a POST, so it needs only **Read** on Knowledge Base despite the verb. - Chunks whose document has since been deleted are filtered out of the result rather than returned as orphans. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/query' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "How long do I have to return something?", "topK": 3 }' ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "results": [ { "text": "Orion accepts returns within 30 days of delivery, provided the item is unused…", "score": 0.8821, "docTitle": "Returns policy 2026", "docId": "b81e5c0a-7d33-4f2e-9c11-2a4f6d8e0b55", "chunkIndex": 0 } ] } ``` ### Knowledge base stats `GET https://avaai.pathor.in/api/v1/kb/{kbId}/stats` - Permalink: https://console.ava.pathor.ai/api-docs#kb.stats - Scope required: Knowledge Base · Read (`knowledgeBase: view`) - Success status: 200 Counts and sizes for one base — cheap enough to poll after an ingest. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Request: ```bash curl -X GET 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/stats' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "documentsCount": 14, "vectorCount": 312 } ``` ### Bases attached to an assistant `GET https://avaai.pathor.in/api/v1/kb/persona/{personaId}` - Permalink: https://console.ava.pathor.ai/api-docs#kb.personaKbs - Scope required: Knowledge Base · Read (`knowledgeBase: view`) - Success status: 200 Which knowledge bases one assistant can retrieve from, and how. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `personaId` | string | yes | The customPersonaId. Example: `orion-support`. | Request: ```bash curl -X GET 'https://avaai.pathor.in/api/v1/kb/persona/orion-support' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "personaId": "orion-support", "kbs": [ { "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "enabled": true, "grounding_mode": "supplemental", "name": "Orion product docs", "description": "Public manuals and the returns policy.", "docsCount": 14, "totalSize": 2841203 } ] } ``` ### Attach a base to an assistant `POST https://avaai.pathor.in/api/v1/kb/{kbId}/personas/{personaId}` - Permalink: https://console.ava.pathor.ai/api-docs#kb.attach - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 Gives the assistant retrieval over this base from its next turn onward. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | | `personaId` | string | yes | Example: `orion-support`. | Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `grounding_mode` | strict | supplemental | no | strict confines the assistant to what it retrieves and makes it say so when it finds nothing. supplemental lets it answer from its own knowledge as well. Default: `supplemental`. | | `enabled` | boolean | no | Default: `true`. | Notes: - **An assistant may hold at most three knowledge bases.** A fourth is a 400. Merge related material into one base rather than splitting it finely. - Re-posting a base that is already attached updates it instead, and answers `updated: true` rather than `attached: true`. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/personas/orion-support' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "grounding_mode": "supplemental", "enabled": true }' ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "personaId": "orion-support", "grounding_mode": "supplemental", "enabled": true, "attached": true } ``` ### Update an attachment `PATCH https://avaai.pathor.in/api/v1/kb/{kbId}/personas/{personaId}` - Permalink: https://console.ava.pathor.ai/api-docs#kb.updateAttachment - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 Change grounding mode, or switch a base off for one assistant without detaching it. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | | `personaId` | string | yes | Example: `orion-support`. | Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `grounding_mode` | strict | supplemental | no | — | | `enabled` | boolean | no | — | Request: ```bash curl -X PATCH 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/personas/orion-support' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "grounding_mode": "strict" }' ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "personaId": "orion-support", "updated": true } ``` ### Detach a base `DELETE https://avaai.pathor.in/api/v1/kb/{kbId}/personas/{personaId}` - Permalink: https://console.ava.pathor.ai/api-docs#kb.detach - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 Removes the link. The base and its documents survive. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | | `personaId` | string | yes | Example: `orion-support`. | Notes: - Only **Read & write**, not Full control — detaching an assistant destroys nothing, so it is not held to the same bar as deleting a base. Request: ```bash curl -X DELETE 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/personas/orion-support' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "personaId": "orion-support", "detached": true } ``` ### Schedule a re-crawl `PATCH https://avaai.pathor.in/api/v1/kb/{kbId}/auto-refresh` - Permalink: https://console.ava.pathor.ai/api-docs#kb.autoRefresh - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 Re-fetch every URL-sourced document in the base on an interval. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Body fields: | Field | Type | Required | Notes | |---|---|---|---| | `enabled` | boolean | yes | — | | `intervalDays` | number | no | Use with intervalHours. | | `intervalHours` | number | no | — | Request: ```bash curl -X PATCH 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/auto-refresh' \ -H "Authorization: Bearer $AVA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "intervalDays": 7, "intervalHours": 0 }' ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "autoRefresh": { "enabled": true, "intervalDays": 7, "lastRefreshedAt": null, "nextRefreshAt": "2026-08-27T09:00:00.000Z" } } ``` ### Re-crawl now `POST https://avaai.pathor.in/api/v1/kb/{kbId}/refresh-now` - Permalink: https://console.ava.pathor.ai/api-docs#kb.refreshNow - Scope required: Knowledge Base · Read & write (`knowledgeBase: edit`) - Success status: 200 Kicks the refresh immediately rather than waiting for the schedule. Returns as soon as the job is queued. Path parameters: | Field | Type | Required | Notes | |---|---|---|---| | `kbId` | string | yes | Example: `3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13`. | Notes: - Only URL-sourced documents are re-crawled. An uploaded file or pasted text has no source to re-fetch, so it is left alone. Request: ```bash curl -X POST 'https://avaai.pathor.in/api/v1/kb/3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13/refresh-now' \ -H "Authorization: Bearer $AVA_API_KEY" ``` Response `200`: ```json { "status": "ok", "kbId": "3f6b1c22-8f0e-4a71-9a2e-5c1d0f9b7a13", "refreshedDocs": 4, "autoRefresh": { "enabled": true, "intervalDays": 7, "lastRefreshedAt": "2026-08-20T09:41:02.771Z", "nextRefreshAt": "2026-08-27T09:41:02.771Z" }, "message": "Successfully re-indexed 4 URL document(s)." } ``` ## Not documented here Campaigns, WhatsApp and journeys have API-key scopes of their own but are not on this reference: they place calls and message real people, which does not belong on an unauthenticated page with an executable playground. Contact support for those.