Skip to main content
Every import turns source rows or files into markdown pages with frontmatter and writes them through the normal write pipeline, so they are committed to git, indexed, and broadcast like any other write. Exports read the same files back out. All paths below are relative to http://localhost:3333/api/kiwi. A typical import has three steps:
1

Browse

For databases, list tables or collections with POST /import/browse.
2

Preview

Render sample pages with POST /import/preview and get suggested field mappings from POST /import/infer-fields. Nothing is written.
3

Import

Send the same body to POST /import. The server saves the connection (without secrets) so you can re-run it later.

Run an import

Import records from a source and write one markdown page per record. POST /api/kiwi/import from selects the source. The other fields depend on the source (see Sources). /import/preview and /import/infer-fields accept the same body.
string
required
Source type, for example postgres, csv, or obsidian.
string
Directory on the server to read from. Required for markdown and obsidian.
string
File on the server to read from. Required for csv, json, jsonl, and bibtex. Also accepted by croissant.
string
Croissant metadata URL, as an alternative to file.
string
Connection string for postgres and mysql. Also accepted as the URI for mongodb.
string
Connection URI for mongodb.
string
SQLite database file path. Required for sqlite.
string
Table to import from postgres, mysql, or sqlite. SQL sources need either table or query.
string
SQL query to run instead of reading a whole table.
string
Database name. Required for mongodb.
string
Collection name. Required for mongodb and firestore.
string
Google Cloud project ID. Required for firestore.
object
Service account JSON for firestore. Never stored.
string
Notion database ID. Required for notion.
string
Airtable base ID. Required for airtable.
string
Airtable table ID. Required for airtable.
string
API key for notion or airtable. Falls back to the NOTION_API_KEY or AIRTABLE_API_KEY environment variable. Never stored.
string
Directory to write pages into. Defaults to the source name.
string
Field used as the page filename. Defaults to the source’s primary key.
string[]
Only keep these fields in frontmatter.
object[]
Rename, retype, or skip fields. Each entry is {"source", "target", "type", "skip"}, where type is string, number, boolean, or date. When you send any mapping, unmapped fields are dropped.
boolean
default:"false"
Count what would be written without writing anything.
integer
default:"0"
Stop after this many records. 0 means no limit.
string
Force a connector path: builtin, airbyte (local Docker), or airbyte-cloud. Leave empty to pick automatically.
object
Raw Airbyte connector config. Sending it routes the import through Airbyte.
string
Override the Airbyte Docker image.
string[]
Airbyte streams to sync. Defaults to all streams.
string
default:"api-import"
Git commit author for the imported pages.
integer
Pages created or updated.
integer
Records whose page was already up to date.
integer
Pages marked with _archived_at because their source row disappeared. Omitted when zero.
string[]
Per-record error messages.
Response
Returns 400 when from or a required source field is missing or the source type is unknown, and 500 when the import fails.
path, file, and db are paths on the server’s filesystem. To import a file from your own machine, use POST /import/upload.
The request is synchronous. For syncable sources (postgres, mysql, mongodb, firestore, notion, airtable, firebase-rtdb), a run without dry_run or limit is a full sync: pages whose source rows no longer exist are archived. A successful import also saves its settings as a connection and turns on hourly auto-sync for syncable sources.

Sources

For Excel and YAML files, use the kiwifs import CLI. See Import overview for source-specific guides.

Upload a file and import it

Upload a local file and import, preview, or infer fields from it in one request. POST /api/kiwi/import/upload (multipart/form-data)
file
required
The data file. Maximum 256 MB.
string
required
One of csv, json, jsonl, bibtex, or sqlite. Excel and YAML uploads are accepted by the form but not yet imported; use the kiwifs import CLI for those.
string
default:"import"
import writes pages, preview returns the first 5 rendered records, and infer-fields returns suggested field mappings.
string
Target directory. Defaults to the uploaded filename without its extension.
string
Field used as the page filename.
string
Field mappings as a JSON-encoded array, in the same shape as POST /import.
string
Table name for sqlite. A sqlite upload needs either table or query.
string
SQL query for sqlite.
The response depends on mode: the import response, the preview response, or the infer-fields response. Returns 400 for an unsupported from and 413 when the file is over 256 MB.

List sources

List the source types this server can import from, and whether Airbyte connectors are available. GET /api/kiwi/import/sources
string[]
Sources handled natively by KiwiFS.
string[] | null
Airbyte connector sources. null when neither Docker nor an Airbyte Cloud key is available.
boolean
Whether a Docker daemon is reachable for local Airbyte connectors.
boolean
Whether an Airbyte Cloud API key is configured.
Response
The order of the lists is not guaranteed.

Browse tables and collections

List the tables or collections in a database before you import. POST /api/kiwi/import/browse
string
required
postgres, mysql, mongodb, or firestore.
string
Connection string for postgres and mysql.
string
Connection URI for mongodb. dsn also works.
string
Database name. Required for mongodb.
string
Project ID. Required for firestore.
object
Service account JSON for firestore.
object[]
Response
Returns 400 for other source types or when the connection fails.

Preview an import

Render the first few records as pages without writing anything. POST /api/kiwi/import/preview Takes the same body as POST /import, including path for markdown and obsidian and query for SQL sources, plus:
integer
default:"5"
Number of records to preview. Values outside 1–20 fall back to 5.
object[]
Response

Infer field mappings

Sample up to 100 records and suggest a field mapping with detected types. POST /api/kiwi/import/infer-fields Takes the same body as POST /import/preview, including path and query. prefix, columns, field_mappings, and limit are ignored.
object[]
Response
Fields whose names start with _ are left out. Edit the result as needed and pass it as field_mappings to preview or import.

Saved connections

A connection is the non-secret part of an import: source, table, prefix, columns, and sync settings. KiwiFS saves one automatically after each successful POST /import (one per source and prefix) and keeps them in .kiwi/state/imports.json. Credentials and API keys are never stored, so you send them again when you re-run a connection that needs them.

Connection object

string
Connection ID (UUID).
string
Source type.
string
Display name, for example postgres:articles.
string
Target directory.
various
Source settings, as sent on import.
string
RFC 3339 time of the last run.
object
imported, skipped, archived, and errors from the last run.
string
RFC 3339 creation time.
boolean
Whether auto-sync is on.
string
Go duration such as 5m, 1h, or 24h.
string
RFC 3339 time of the next scheduled sync.
string
idle, running, or error.
string
Last sync error, if any.
various
Airbyte settings, when the import ran through Airbyte.

List connections

List saved import connections. GET /api/kiwi/import/connections
Returns an array of connection objects, or [] when the connection store is unavailable.
Response
dsn and uri are saved exactly as sent, including any password inside them.

Save a connection

Create or update a connection without running an import. POST /api/kiwi/import/connections The body is a connection object. from is required, and name defaults to from. Include id to update an existing connection or omit it to create one.
Returns 200 with the saved connection, including its id. Returns 400 without from and 503 when the connection store is unavailable.

Delete a connection

Remove a saved connection. Pages it imported are not touched. DELETE /api/kiwi/import/connections/:id
Returns 204 on success and 404 for an unknown ID.

Run a connection

Re-run a saved connection’s import. POST /api/kiwi/import/connections/:id/run
string
required
Connection ID.
object
Service account JSON for this run only (firestore).
string
API key for this run only (notion, airtable).
Returns the same body as POST /import and updates last_run and last_stats. Returns 404 for an unknown ID.

Configure auto-sync

Turn auto-sync on or off for a connection, or change its interval. POST /api/kiwi/import/connections/:id/sync
string
required
Connection ID.
boolean
Turn auto-sync on or off. Omit to keep the current state.
string
Go duration such as 15m, 1h, or 24h. Invalid values fall back to 1h.
Returns the updated connection object with next_sync rescheduled. Returns 404 for an unknown ID.
Scheduled syncs run without credentials, so they only work for sources that don’t need any at run time, such as a postgres DSN that includes its password.

Sync status

List every connection with auto-sync enabled. GET /api/kiwi/import/sync/status
Returns an array of connection objects where sync_enabled is true. Check sync_status and sync_error for failures.

Airbyte endpoints

Configure Airbyte connectors, locally through Docker or through Airbyte Cloud. Airbyte Cloud needs airbyte_api_key and airbyte_workspace_id under [import] in .kiwi/config.toml, or the AIRBYTE_API_KEY and AIRBYTE_WORKSPACE_ID environment variables. The local endpoints return 503 when Docker is not running. The Cloud endpoints return 503 without an API key and 502 when Airbyte Cloud rejects the request.
See Airbyte import for the full walkthrough.

Ingest a document

Convert a PDF, Office file, image, or other document to markdown and write it as one or more pages. POST /api/kiwi/ingest
string
required
Path to the file on the server. Supported extensions: pdf, docx, pptx, xlsx, html, htm, csv, json, xml, epub, jpg, jpeg, png, gif, bmp, tiff, mp3, wav, m4a, zip.
string
default:"single"
single writes one page. sections writes one page per heading when the document has more than one section.
string
Directory for the output pages. Defaults to imports/<file-name-slug>/.
boolean
default:"false"
Extract keywords for each section.
integer
default:"10"
Keywords to extract per section.
boolean
default:"false"
Turn references like “see Section 2.1” into wiki links.
string
default:"kiwi-ingest"
Git commit author.
string
The input file.
string
Detected input format.
integer
Sections found in the converted document.
string[]
Pages written.
string[]
Extracted keywords, when requested.
Response
Returns 400 for a missing file or an unsupported extension.

Export pages

Stream every markdown page, or the pages under a path, as JSONL, CSV, or Parquet. GET /api/kiwi/export
string
default:"jsonl"
jsonl, csv, or parquet.
string
Only export pages whose path starts with this prefix, for example concepts/.
string
Comma-separated frontmatter fields to use as CSV columns. Without it, columns are detected from the first page.
boolean
default:"false"
Include the full markdown file in content.
Include outgoing (links_out) and incoming (links_in) wiki links.
boolean
default:"false"
Include vector chunks. Not supported with parquet.
integer
default:"0"
Maximum pages to export. 0 means no limit.
The response streams with Content-Type set to application/x-ndjson, text/csv, or application/vnd.apache.parquet. Each JSONL line is one page:
string
Page path.
object
Parsed frontmatter.
integer
Words in the body.
string
Full file, with include_content=true.
Outgoing wiki links, with include_links=true.
Pages linking here, with include_links=true.
object[]
chunk_idx, text, and vector for each chunk, with include_embeddings=true.
concepts.jsonl
CSV output always starts with a path column:
pages.csv
Returns 400 for an unknown format, a negative limit, or include_embeddings with parquet.

Export a document

Render a page or folder to PDF, HTML, slides, or a static site and download the result. POST /api/kiwi/export/document
string
required
pdf, html, slides, or site.
string
required
File or directory to render.
The response is the rendered file with a Content-Disposition: attachment header. Rendering times out after 5 minutes. See Document export for theme, bibliography, slide, and site options.

Import overview

Source guides and the kiwifs import CLI.

Saved connections

Re-running imports and auto-sync.

Airbyte import

Docker and Airbyte Cloud connectors.

Export overview

Formats and when to use each.
Last modified on October 19, 2026