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

# Import and export

> REST import (including browse, preview, saved connections, and file ingest) and export formats.

## Import

Bulk import data into your knowledge base. The import endpoint accepts the same source configuration options as the `kiwifs import` CLI command.

```bash theme={null}
curl -X POST 'http://localhost:3333/api/kiwi/import' \
  -H "Content-Type: application/json" \
  -H "X-Actor: agent:importer" \
  -d '{
    "source": "postgres",
    "connection": "postgres://user:pass@localhost:5432/mydb",
    "query": "SELECT id, title, body FROM articles WHERE updated_at > '\''2026-01-01'\''",
    "mapping": {
      "path": "articles/{{id}}.md",
      "title": "{{title}}",
      "content": "{{body}}"
    }
  }'
```

```json theme={null}
{"imported": 42, "skipped": 0, "archived": 3, "errors": []}
```

<ResponseField name="imported" type="integer">Pages created or updated.</ResponseField>
<ResponseField name="skipped" type="integer">Rows unchanged since last import.</ResponseField>
<ResponseField name="archived" type="integer">Pages tombstoned with `_archived_at` during a full sync (when source rows disappear).</ResponseField>
<ResponseField name="errors" type="array">Per-row error messages.</ResponseField>

<AccordionGroup>
  <Accordion title="Source types">
    | Source        | Config value    | Description                         |
    | ------------- | --------------- | ----------------------------------- |
    | PostgreSQL    | `postgres`      | Import from PostgreSQL queries      |
    | MySQL         | `mysql`         | Import from MySQL queries           |
    | MongoDB       | `mongodb`       | Import from MongoDB collections     |
    | SQLite        | `sqlite`        | Import from SQLite databases        |
    | CSV           | `csv`           | Import from CSV files               |
    | JSON          | `json`          | Import from JSON or JSONL files     |
    | Notion        | `notion`        | Import from Notion workspace        |
    | Airtable      | `airtable`      | Import from Airtable bases          |
    | Google Sheets | `gsheets`       | Import from Google Sheets           |
    | Confluence    | `confluence`    | Import from Confluence spaces       |
    | Obsidian      | `obsidian`      | Import from Obsidian vaults         |
    | DynamoDB      | `dynamodb`      | Import from DynamoDB tables         |
    | Redis         | `redis`         | Import from Redis keys              |
    | Elasticsearch | `elasticsearch` | Import from Elasticsearch indices   |
    | Firestore     | `firestore`     | Import from Google Firestore        |
    | YAML          | `yaml`          | Import from YAML files              |
    | Excel         | `excel`         | Import from `.xlsx` spreadsheets    |
    | Markdown      | `markdown`      | Import from a folder of `.md` files |
  </Accordion>

  <Accordion title="Mapping template syntax">
    Use double-brace templates to map source fields to KiwiFS file paths and frontmatter:

    ```json theme={null}
    {
      "path": "concepts/{{slug}}.md",
      "title": "{{name}}",
      "content": "{{body}}",
      "frontmatter": {
        "source": "postgres",
        "source_id": "{{id}}",
        "status": "draft"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

<Warning>
  Large imports can take time. The endpoint responds synchronously. For very large datasets, consider using the CLI `kiwifs import` command with progress output.
</Warning>

## Upload file for import

Upload a file to the server for import processing.

```http theme={null}
POST /import/upload
Content-Type: multipart/form-data
```

The uploaded file is stored temporarily and can be referenced by subsequent `POST /import` calls.

## List supported sources

```http theme={null}
GET /import/sources
```

Returns the list of supported import source types and their required configuration fields.

```json theme={null}
["postgres", "mysql", "sqlite", "mongodb", "firestore", "dynamodb", "redis", "elasticsearch", "csv", "json", "jsonl", "yaml", "excel", "notion", "airtable", "gsheets", "obsidian", "confluence", "markdown"]
```

## Import browse

List **tables or collections** for a source before you run a full import. Same base URL prefix: `http://localhost:3333/api/kiwi`.

```http theme={null}
POST /import/browse
Content-Type: application/json
```

Body fields depend on `from` (same family as `POST /import`):

| `from`      | Required fields (typical)              |
| ----------- | -------------------------------------- |
| `postgres`  | `dsn`                                  |
| `mysql`     | `dsn`                                  |
| `mongodb`   | `uri` (or `dsn`), `database`           |
| `firestore` | `project`, optional `credentials` JSON |

```json theme={null}
{ "from": "postgres", "dsn": "postgres://user:pass@localhost:5432/db" }
```

```json theme={null}
{ "tables": [{ "name": "articles" }, { "name": "comments" }] }
```

Unsupported `from` values return **`400`** when browse is not implemented for that source.

## Import preview

Fetch sample rows **without writing** pages. Uses the same JSON shape as `POST /import`, plus optional `limit` (default **5**, max **20**).

```http theme={null}
POST /import/preview
Content-Type: application/json
```

```json theme={null}
{
  "records": [
    {
      "path": "postgres/acme.md",
      "frontmatter": { "_source": "postgres", "_source_id": "...", "title": "Acme" },
      "body_preview": "# Acme\n\n> Auto-imported from postgres (row ...)"
    }
  ]
}
```

## Import connections

When a connection store is enabled, the server persists **metadata only** (never secrets). Re-runs require credentials in the request body.

| Method   | Path                           | Purpose                                                                                                                                                                                             |
| -------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET`    | `/import/connections`          | List saved connections (empty array if disabled).                                                                                                                                                   |
| `POST`   | `/import/connections`          | Save or update metadata (`from`, `name`, `dsn`, `uri`, `table`, `collection`, `database`, `database_id`, `base_id`, `table_id`, `project`, `prefix`, `id_column`, `columns`, last-run stats, etc.). |
| `DELETE` | `/import/connections/:id`      | Remove a connection. **`204`**.                                                                                                                                                                     |
| `POST`   | `/import/connections/:id/run`  | Run import again. Body may include `credentials` and/or `api_key` for that run only. Response matches `POST /import`: `{ "imported", "skipped", "archived", "errors" }`.                            |
| `POST`   | `/import/connections/:id/sync` | Enable, pause, or change auto-sync interval. Body: `{ "enabled": true, "interval": "1h" }`.                                                                                                         |

## Ingest from files

Convert supported office and document formats to markdown (MarkItDown pipeline).

```http theme={null}
POST /ingest
Content-Type: application/json
```

```json theme={null}
{
  "file": "/tmp/report.pdf",
  "split_mode": "single",
  "prefix": "imports/",
  "extract_keywords": true,
  "max_keywords": 10,
  "convert_crossrefs": false,
  "actor": "ingest-bot"
}
```

* `file` must use an extension the server accepts for MarkItDown.
* `split_mode` defaults to `single`.

## Export

Export your knowledge base in structured formats.

<ParamField query="format" type="string" required>
  Output format: `jsonl`, `csv`, or `parquet`.
</ParamField>

<ParamField query="path" type="string">
  Scope export to a subdirectory (e.g. `concepts`).
</ParamField>

<ParamField query="columns" type="string">
  Comma-separated frontmatter fields to include as columns.
</ParamField>

<ParamField query="include-content" type="boolean" default="false">
  Include the full markdown body in the export.
</ParamField>

<ParamField query="include-links" type="boolean" default="false">
  Include outgoing wiki links for each page.
</ParamField>

<ParamField query="include-embeddings" type="boolean" default="false">
  Include vector embeddings (if available).
</ParamField>

<ParamField query="limit" type="integer">
  Maximum number of pages to export.
</ParamField>

<CodeGroup>
  ```bash Export as JSONL theme={null}
  curl 'http://localhost:3333/api/kiwi/export?format=jsonl&path=concepts&include-content=true'
  ```

  ```bash Export as CSV theme={null}
  curl 'http://localhost:3333/api/kiwi/export?format=csv&columns=title,status,updated&path=concepts'
  ```

  ```bash Export with links and embeddings theme={null}
  curl 'http://localhost:3333/api/kiwi/export?format=jsonl&include-content=true&include-links=true&include-embeddings=true'
  ```
</CodeGroup>

### JSONL output

Each line is a JSON object representing one page:

```json theme={null}
{"path":"concepts/auth.md","title":"Authentication","status":"verified","content":"# Authentication\n\nOAuth2 + JWT...","links":["users","billing"]}
{"path":"concepts/billing.md","title":"Billing","status":"draft","content":"# Billing\n\nStripe integration...","links":["users"]}
```

### CSV output

```csv theme={null}
path,title,status,updated
concepts/auth.md,Authentication,verified,2026-04-25
concepts/billing.md,Billing,draft,2026-04-20
```

<Tip>
  Use JSONL export with `include-content=true` to create backups or to feed your knowledge base into external pipelines.
</Tip>

## Document export

Render markdown to PDF, HTML, slides, or a static site:

```http theme={null}
POST /export/document
Content-Type: application/json
```

See [Document export](/export/documents) for the full request body and examples.

## Airbyte endpoints

| Method | Path                                |
| ------ | ----------------------------------- |
| `POST` | `/import/airbyte/spec`              |
| `POST` | `/import/airbyte/check`             |
| `POST` | `/import/airbyte/discover`          |
| `POST` | `/import/airbyte-cloud/check`       |
| `POST` | `/import/airbyte-cloud/discover`    |
| `GET`  | `/import/airbyte-cloud/connections` |
| `POST` | `/import/airbyte-cloud/sync`        |
| `GET`  | `/import/sync/status`               |

See [Airbyte import](/import/airbyte).
