# Core Concepts

The parts of Senso and how they fit together — the knowledge base and its nodes, search, gaps, industries and prompts, the brand kit, content types, product lines, and the content Senso writes.

Senso keeps what your organization knows in a **knowledge base**, answers questions from it with sources, and writes content from it. This page explains each part and the words Senso uses for it. Each section names the endpoints that work with it and links to them in the [API Reference](https://docs.senso.ai/api-reference), where every request and response is documented.

Every request uses the base URL `https://apiv2.senso.ai/api/v1` and your key in an `X-API-Key` header. [API Keys](https://docs.senso.ai/docs/api-keys) shows how to get one.

**What your organization can use depends on its Senso products.** Gaps need Senso's Fetch product. An industry's results, prompts, and everything under "How Senso writes for you" and "Generated content" need Senso's GEO product (Generative Engine Optimization). Without the product, a request answers `403`.

**Most work costs credits:** processing a document, a search, an evaluation, a generated page, and each scheduled run of your prompts. An organization out of credits gets `402`.

## At a glance

| Term | What it is |
|------|------------|
| **Organization** | Your workspace. Everything below belongs to one organization. |
| **Knowledge base** | The documents your organization gives Senso, in folders. What Senso answers and writes from. |
| **Node** | One item in the knowledge base: a **folder** or a **content node**. |
| **Content node** | A document in the knowledge base: text you wrote, a page from your website, or a file you uploaded. |
| **Version** | Each edit to a document saves a new version. Earlier versions stay readable. |
| **Search** | A question answered from your knowledge base, with the documents behind the answer. |
| **Gap** | A question your knowledge base could not answer, recorded so someone can fill it. |
| **Evaluation** | A check of a text's claims against your knowledge base, claim by claim. |
| **Industry** | A market Senso tracks, with the questions people ask AI models about it. |
| **AI model** | An AI assistant Senso asks those questions, such as ChatGPT or Google AI Overviews. |
| **Prompt** | A question your organization tracks, and asks AI models on a schedule. Also called a GEO question. |
| **Brand kit** | Your organization's voice: name, description, tone and writing rules. |
| **Content type** | A template for a kind of page, such as an FAQ article. |
| **Product line** | One thing you sell, described for the Builder in the Senso app. |
| **CTA** | A call-to-action card shown on your published pages. |
| **Generated content** | A page Senso writes from your knowledge base to answer a prompt. |
| **Destination** | Where a page is published, such as citeables.com. |

## Your organization

`GET /org/me` returns your organization: its name, websites, industry, the AI models it tracks under `models`, the countries it asks from under `locations`, and whether scheduled runs and generation are on.

API Reference: [Organization](https://docs.senso.ai/api-reference?tag=organization)

## The knowledge base

### Everything is a node

The knowledge base is a tree. Every item in it is a **node**, and every node is one of two types:

| `type` | What it is |
|--------|------------|
| `folder` | Holds other nodes. |
| `content` | A document. It points to the document's text and its versions. |

Each organization has one root folder, named **Root**. Every other node has a `parent_id`, the folder it sits in:

```
Root                                folder
├── Policies                        folder
│   ├── Refund policy               content  (raw text)
│   └── shipping-policy.pdf         content  (file)
└── shared-context                  folder
    └── Existing-customer pricing   content  (raw text)
```

A content node's `content.type` says what kind of document it is:

| `content.type` | What it is |
|----------------|------------|
| `raw` | Text or markdown: sent through the API, written in the Senso app, or a page imported from your website |
| `file` | A file you uploaded, such as a PDF, DOCX or TXT |

A content node, as the API returns it:

```json
{
  "kb_node_id": "6d982360-...",
  "parent_id": "73b78a4e-...",
  "content_id": "fba6665f-...",
  "type": "content",
  "name": "Refund policy",
  "content": {
    "id": "fba6665f-...",
    "type": "raw",
    "content_type": "text/markdown",
    "title": "Refund policy",
    "summary": "How long customers have to ask for a refund.",
    "version_num": 1,
    "processing_status": "complete"
  },
  "tags": [{ "name": "refund-policy" }],
  "effective_role": "admin"
}
```

### Two IDs for every document

| ID | What it identifies | Where you use it |
|----|--------------------|------------------|
| `kb_node_id` | The document's place in the tree | Every `/org/kb/nodes/{id}` endpoint: read, edit, move, rename, delete, tag, share |
| `content_id` | The document itself | Scoping a search with `content_ids`, and in search results |

Creating a document returns both. Search results return both too.

### Adding documents

There are three ways in:

- **Text.** Send text or markdown with `POST /org/kb/raw`, into a folder you choose or Root. Markdown files go in this way too.
- **Files.** Describe up to 10 files with `POST /org/kb/upload`, each up to 100 MB. Senso returns an upload URL for each, and you upload the file there within the hour. The URL carries its own authorization, so the upload takes no API key.
- **Your website.** `POST /org/website-import` brings in your home page and up to 19 more of your pages as `raw` documents, in a folder named **Website**, and drafts a brand kit if you have none. It imports the website on file for your organization, and usually finishes within a minute. See [Website Import](https://docs.senso.ai/api-reference?tag=website-import) in the API Reference.

Text identical to a document you already have is refused with `409`. A file already in your knowledge base comes back from the upload request with the status `conflict`, naming the existing document.

### Processing

Senso processes every document you add before search can use it. **Nothing is searchable until `processing_status` is `complete`.** Read it from the node with `GET /org/kb/nodes/{id}`:

| `processing_status` | Meaning |
|---------------------|---------|
| `pending` | Waiting for the file upload. |
| `processing` | Senso is processing it. |
| `complete` | Ready. Search can use it. |
| `failed` | Processing failed, or your organization ran out of credits. The node's `error_code` says which. Replace the file or text to try again. |

A short text document can be complete within seconds; a long file takes longer. Senso also tags each document by topic, such as `refund-policy`, and leaves tags you set alone.

### Reading, editing and organizing

- **Read.** A text document's text is at `GET /org/kb/nodes/{id}/content`. An uploaded file has no text there; `GET /org/kb/nodes/{id}/download-url` gives a link to download it.
- **Browse.** Start at `GET /org/kb/root` and list each folder's children, or find nodes by name anywhere with `GET /org/kb/find`. Lists return 50 nodes at most; page through longer ones with `limit` and `offset`.
- **Edit.** Every edit saves a new version, and Senso processes it again. Search answers from the new version once it is `complete`. A file is replaced by uploading the new one in its place.
- **Earlier versions.** Read any of them with `?version=` on `/content`.
- **Rename and move.** Renaming a document changes its title too.
- **Delete.** **Deleting a folder deletes everything in it.** A document that is still processing answers `409`; try again when it is complete.

Who can see and change each node is on [Permissions](https://docs.senso.ai/docs/permissions).

API Reference: [Knowledge Base](https://docs.senso.ai/api-reference?tag=knowledge-base)

## Search

Search answers a question from your knowledge base and returns the passages behind the answer, with the document each came from. Five endpoints take the same request and differ in what they return:

| Endpoint | Returns |
|----------|---------|
| `POST /org/search` | An answer, and the passages it was written from. Start here. |
| `POST /org/search/full` | An answer written from the whole of each matching document, not only the matching passages. |
| `POST /org/search/stream` | The `/org/search` answer as it is written, as Server-Sent Events. |
| `POST /org/search/context` | The passages only, with no answer. For your own model or agent to answer from. |
| `POST /org/search/content` | Only which documents match: their IDs and titles. |

Each result is a passage: `chunk_text` is its text, `title`, `kb_node_id` and `content_id` name its document, and `version_id` is the version it came from.

| Request field | Description |
|---------------|-------------|
| `query` | The question. Required. |
| `max_results` | How many passages to return. Default 5. Anything above 20 returns 20. |
| `content_ids` | Search only these documents, by content ID. |
| `require_scoped_ids` | When `true`, a request with no `content_ids` fails with a `400` instead of searching everything. A guard for code that must never search outside the documents it names. |

The stream sends `token` events as the answer is written, then one `sources` event with the passages, then `done`, or an `error` event if something goes wrong partway.

Search only returns documents the caller can see. A key restricted to some folders searches only those.

API Reference: [Search](https://docs.senso.ai/api-reference?tag=search)

## Gaps

When `/org/search`, `/org/search/full` or `/org/search/stream` finds nothing, Senso records the question as a **gap**: something your knowledge base cannot answer yet. Context and content searches do not record gaps.

- The first time a question finds nothing from the API, its gap is `weak`, and left out of the default list. Asked again, by anyone, it becomes `open`.
- A later search that answers the question resolves its gap.
- Senso also records claims an [evaluation](https://docs.senso.ai/docs/why-senso) found unsupported by your documents, or contradicted by them.

`GET /org/gaps` lists the gaps that need work: `open`, `reopened` and `addressed`. You can filter the list by status, such as `weak`, and by where a gap came from. `POST /org/gaps/{gapId}/resolutions` records what was done about a gap, such as `answered` or `dismissed`.

**Keep test and monitoring searches out of your gaps** with the header `X-Senso-Signals: off`. The search still runs and still costs credits; it just never records a gap.

API Reference: [Gaps](https://docs.senso.ai/api-reference?tag=gaps)

## Industries, AI models and prompts

These are how Senso sees what AI models say about your market.

### Industries

An **industry** is a market Senso tracks, such as accounting and tax software, or AI agent platforms in Canada. Each industry has up to 1,000 **industry prompts**: questions people ask AI models about that market. Senso asks the AI models those questions on a schedule and records every answer: which brands it names, and which websites it cites.

`GET /org/industries` lists Senso's catalog. For any industry in it, you can see:

- how often each brand is named across the industry, over the last 30 days;
- each industry prompt, with how often each AI model named you, and its three most-named brands;
- which of the industry's prompts your organization does not track yet.

Your organization belongs to one industry, set with `PUT /org/me/industry`. It is the industry you import prompts from. Setting it does nothing else on its own: it creates no prompts and starts no runs. Changing it later keeps the prompts you already imported.

API Reference: [Industries](https://docs.senso.ai/api-reference?tag=industries)

### AI models

An **AI model** is an AI assistant Senso asks questions, such as ChatGPT, Google AI Overviews or Perplexity. `GET /org/me` lists the ones your organization tracks under `models`, and the countries it asks from under `locations`.

### Prompts

A **prompt** is a question your organization tracks: Senso asks it on your organization's schedule, and it is what generated content answers. Write your own with `POST /org/prompts`, or import your industry's with `POST /org/industries/{id}/prompts/import`.

Importing copies over the answers Senso has already collected for those prompts, for the AI models and countries your organization runs, so their analytics start with data. Follow that copy with [History Imports](https://docs.senso.ai/api-reference?tag=history-imports).

**Importing also activates your organization and starts its scheduled runs**, and each run costs credits. You can only import from your own industry, and a question you already track is skipped, not added twice.

`type` is where the question sits in a customer's journey: `awareness`, `consideration`, `evaluation` or `decision`. An industry prompt's `funnel_stage` becomes its `type` when you import it.

> **One thing, two names.** The API also calls a prompt a **GEO question**. A `geo_question_id` is a prompt's `prompt_id`.

API Reference: [Prompts](https://docs.senso.ai/api-reference?tag=prompts)

## How Senso writes for you

Three settings shape what Senso writes: the **brand kit** (how you sound), **content types** (the shape of a page) and **product lines** (what you sell).

### Brand kit

One per organization, used for everything Senso writes. Its `guidelines` take these six keys, and any other key is a `400`:

| Key | What it holds |
|-----|---------------|
| `brand_name` | Your brand's name |
| `brand_domain` | Your website |
| `brand_description` | What you do |
| `voice_and_tone` | How the writing should sound |
| `author_persona` | Who the writing speaks as |
| `global_writing_rules` | A list of rules every page follows |

`PATCH /org/brand-kit` changes only the keys you send. **`PUT /org/brand-kit` replaces the whole kit**, and a key you leave out is cleared.

API Reference: [Brand Kit](https://docs.senso.ai/api-reference?tag=brand-kit)

### Content types

A **content type** is a template for one kind of page, such as an FAQ article or a comparison page. Create as many as you need.

| `config` key | What it does |
|--------------|--------------|
| `template` | The page's outline in markdown. Each heading becomes a section, and the text under it is the instruction for that section. |
| `template_spec` | The sections Senso reads from `template`. Senso fills it in; you can leave it out. |
| `cta_text`, `cta_destination` | A link added at the end of each page, such as "Contact support". |
| `writing_rules` | Rules for this type of page, on top of the brand kit's. |

Any other key is a `400`.

API Reference: [Content Types](https://docs.senso.ai/api-reference?tag=content-types)

### Product lines

A **product line** is one thing you sell: a `name`, and `details` in any shape you like, such as price, URL and who it is for.

The Builder in the Senso app uses product lines: you pick the ones a page is about. Generating a page for a prompt (`/org/content-generation/sample`, and scheduled generation) does not read them, so put facts those pages need in your knowledge base too.

API Reference: [Product Lines](https://docs.senso.ai/api-reference?tag=product-lines)

### CTAs

A **CTA** (call to action) is a card on your published pages, such as "Book a demo": a title, a button label and the URL it goes to. One can be the organization default, which every page shows unless a page picks another or none.

A CTA is not the content type's `cta_text`. That is a link inside the page's text; a CTA is a card the published page shows beside it.

API Reference: [CTA Templates](https://docs.senso.ai/api-reference?tag=cta-templates)

## Generated content

Senso writes a page that answers one of your prompts, from your knowledge base, shaped by a content type and your brand kit. You can generate a page on request, or have Senso generate for your prompts on a schedule, set in your organization's generation settings. `enable_content_generation` and `content_auto_publish` in `GET /org/me` show whether scheduled generation, and publishing without review, are on.

Generated content is not in your knowledge base. It has its own content ID and its own endpoints under `/org/content`, and nothing Senso writes is searchable unless you add it to your knowledge base yourself. Knowledge base documents are read through `/org/kb/nodes`, never `/org/content`.

### Generating a page

`POST /org/content-generation/sample` takes a prompt and a content type, and starts a job. Check the job with `GET /org/content-generation/sample-jobs/{sample_job_id}`: its `status` moves from `queued` to `running`, then ends `completed`, `failed` or `expired`. A completed job carries the page: its markdown, title, URL slug, and its content and version IDs.

**Each prompt has one piece of generated content.** Generating again for the same prompt, or saving your own draft for it with `POST /org/content-engine/draft`, adds a version rather than a second page.

API Reference: [Content Generation](https://docs.senso.ai/api-reference?tag=content-generation)

### Review

A version is in one of three states:

| `editorial_status` | Meaning |
|--------------------|---------|
| `draft` | Waiting for review. Nothing is published. |
| `published` | Live on a destination, or marked published by you. |
| `rejected` | Turned down. Restoring it makes it a draft again. |

`GET /org/content/verification` lists your generated content with each item's status. Before you publish, check the page's claims against your knowledge base with an [evaluation](https://docs.senso.ai/docs/why-senso) (API Reference: [Evals](https://docs.senso.ai/api-reference?tag=evals)).

API Reference: [Content](https://docs.senso.ai/api-reference?tag=content)

### Publishing

A **destination** is where a page goes live. Senso runs several domains that AI models read, such as citeables.com, and `GET /org/destinations` lists them with each one's `publisher_id`.

`POST /org/content-engine/publish` publishes a page to the destinations you name. Two things to know:

- **Publishing sends the page text itself.** Senso saves the `raw_markdown` you send as a new version and publishes that, so send the version you reviewed.
- **Leave out `publisher_ids` and the page goes to every destination** your organization has set up.

A published page is public, and `POST /org/content/{id}/unpublish` takes it down. To publish to a domain of your own, contact Senso at [senso.ai](https://senso.ai). [Verification Loop](https://docs.senso.ai/docs/use-cases/verification-loop) walks through generating, checking and publishing a page from start to finish.

API Reference: [Content Engine](https://docs.senso.ai/api-reference?tag=content-engine), [Destinations](https://docs.senso.ai/api-reference?tag=destinations)

## Errors

Every status the API returns, and what to do about it, is on [Errors](https://docs.senso.ai/docs/errors). Two to know first: `402` means your organization is out of credits or over its spending limit, and a `404` on a node you know exists means you cannot see it. See [Permissions](https://docs.senso.ai/docs/permissions).

## Next steps

- [API Reference](https://docs.senso.ai/api-reference) — every endpoint, request and response
- [Permissions](https://docs.senso.ai/docs/permissions) — who can see and change each folder and document
- [Verification Loop](https://docs.senso.ai/docs/use-cases/verification-loop) — generate, check and publish a page
- [CLI Reference](https://docs.senso.ai/docs/cli-reference) — every command your agent can run
