> ## Documentation Index
> Fetch the complete documentation index at: https://omni.fireflo.au/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /v1/agents/knowledge/sources

> Add an article or an FAQ to Knowledge, or a website for agents to read.

Adds a source to Knowledge. It is `processing` at first and `ready` a few seconds later, once read; agents answer from it from then on. Files are uploaded to [POST /v1/agents/knowledge/files](/api-reference/ai-agents/upload-file) instead.

<Note>Needs the `agents.knowledge:write` scope.</Note>

## Body

| Field | Type | Required | Notes |
| :- | :- | :- | :- |
| `kind` | string | Yes | `article`, `faq` or `website`. |
| `collection` | integer | No | The [collection](/api-reference/ai-agents/list-collections) it goes in; **General** when left out. |
| `active` | boolean | No | Whether agents use it. True by default. |

For an article or an FAQ:

| Field | Type | Required | Notes |
| :- | :- | :- | :- |
| `title` | string | Yes | An article's title, or an FAQ's question. Up to 200 characters; unique among articles, or among FAQs. |
| `body` | string | Yes | An article's text in Markdown (up to 20,000 characters; headings split it into passages), or an FAQ's answer (up to 2,000). |
| `alternates` | array | No | FAQs: up to 20 other ways customers ask the question. |
| `answer_exactly` | boolean | No | FAQs: send the answer exactly as written, with no AI rewording — for prices, terms and legal wording. |

For a website:

| Field | Type | Required | Notes |
| :- | :- | :- | :- |
| `url` | string | Yes | The web address. One already imported is refused. |
| `pages` | array | No | The pages to read, on the same site — up to 50. Just `url` when left out. Pages on other sites are left out. |
| `crawl` | string | No | `page` (the default) or `sitemap`: whether these pages came from one page or the site's sitemap. Through the API, the pages read are the ones you list. |
| `refresh` | string | No | How often to check for changes: `never` (the default), `daily` or `weekly`. Only changed pages are read again. |

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.fireflo.au/v1/agents/knowledge/sources" \
    -H "Authorization: Bearer $OMNI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "kind": "faq",
      "title": "How long does a refund take?",
      "body": "Refunds reach your account 5–7 working days after we receive the item. UPI refunds are usually faster.",
      "alternates": [
        "refund kab aayega",
        "when will I get my money back"
      ],
      "collection": 3
    }'
  ```

  ```python Python theme={null}
  import os

  import requests

  response = requests.post(
      "https://api.fireflo.au/v1/agents/knowledge/sources",
      headers={"Authorization": f"Bearer {os.environ['OMNI_API_KEY']}"},
      json={
          "kind": "faq",
          "title": "How long does a refund take?",
          "body": "Refunds reach your account 5–7 working days after we receive the item. UPI refunds are usually faster.",
          "alternates": [
              "refund kab aayega",
              "when will I get my money back"
          ],
          "collection": 3
      },
  )
  print(response.status_code, response.json())
  ```

  ```javascript Node theme={null}
  const response = await fetch("https://api.fireflo.au/v1/agents/knowledge/sources", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.OMNI_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "kind": "faq",
      "title": "How long does a refund take?",
      "body": "Refunds reach your account 5–7 working days after we receive the item. UPI refunds are usually faster.",
      "alternates": [
        "refund kab aayega",
        "when will I get my money back"
      ],
      "collection": 3
    }),
  });
  console.log(response.status, await response.json());
  ```
</CodeGroup>

## Response

`201 Created` — the source, `processing`. A source has its `id`, `kind` (`article`, `faq`, `file` or `website`), `title` (an FAQ's question), its `collection`, whether agents use it (`active`) and when it last changed. `status` is `processing` while it is read, then `ready` — or `failed`, with the reason in `error`. An article or FAQ has its `body`; a website its `url`, how often it is checked for changes (`refresh`) and how many `pages` it reads; a file its `file` type and size in bytes.

```json theme={null}
{
  "id": "b7e4c1d2-5a3f-4e8b-9c6d-1a2f3e4b5c6d",
  "kind": "faq",
  "title": "How long does a refund take?",
  "collection": {
    "id": 3,
    "name": "Returns & warranty"
  },
  "status": "processing",
  "error": "",
  "active": true,
  "updated_at": "2026-10-06T09:45:02+05:30",
  "body": "Refunds reach your account 5–7 working days after we receive the item. UPI refunds are usually faster."
}
```

A website, added with `"kind": "website"`, `"url": "https://help.sharmaelectronics.in/returns"`, three `pages` and `"refresh": "weekly"`, answers:

```json theme={null}
{
  "id": "0c9a8b7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d",
  "kind": "website",
  "title": "help.sharmaelectronics.in/returns",
  "collection": {
    "id": 3,
    "name": "Returns & warranty"
  },
  "status": "processing",
  "error": "",
  "active": true,
  "updated_at": "2026-10-06T09:48:33+05:30",
  "url": "https://help.sharmaelectronics.in/returns",
  "refresh": "weekly",
  "pages": 3
}
```

## Errors

Every refusal is `{"error": {"code", "message", "field"}}`; `field` is there when one input is at fault.

| Status | Error code | When |
| :- | :- | :- |
| 400 | `invalid_request` | Something is missing or not allowed — `field` names it: `kind`, `title`, `body`, `alternates`, `collection`, `url`, `pages`, `crawl` or `refresh`. Also when an FAQ with that question, an article with that title or that website is already there. |
| 404 | `module_off` | The account doesn't have AI agents on: they aren't in its plan, or are switched off for it. |
| 403 | `scope_missing` | The key doesn't have the `agents.knowledge:write` scope. |

Any request can also be refused for its key, its account or its rate (`key_required`, `invalid_key`, `account_suspended`, `plan_excludes_api`, `address_not_allowed`, `rate_limited`); see [the overview](/api-reference/overview).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.