# NocoDB Connector

> Two-way row sync between NocoDB tables and Odoo models, with base and table metadata import, idempotent binders and dry-run safety.

- **What it is:** Two-way row sync between NocoDB tables and Odoo models, with base and table metadata import, idempotent binders and dry-run safety.
- **For:** Extra Tools
- **Odoo versions:** 16.0, 17.0, 18.0, 19.0, 20.0 - Community and Enterprise
- **Runs on:** Odoo.sh or Odoo you host yourself - not Odoo Online, which accepts no third-party apps
- **Price:** 89 EUR, one-time, on the Odoo Apps Store
- **Technical name:** bambooforge_nocodb_connector
- **Run for real:** Tested for real against a current NocoDB release: 2 bases and 2 tables (a Deals table with 5 rows) came into Odoo with 0 errors, using an API token created for the purpose.
- **Not for:** The connector reads bases, tables and per-table row counts from your NocoDB and writes the corresponding NocoDB Base / NocoDB Table records in Odoo. It never writes back to NocoDB.; The API token is stored in an administrator-only field.; In scope today: base import, table import, live row counts, scheduled re-import/reconciliation, dry-run, validation, rollback snapshots, SSRF guard.; Out of scope / roadmap: importing the actual table records (row data); webhook/push intake from NocoDB; writing any data back to NocoDB.
- **Manual:** https://docs.bambooforge.dev/bambooforge_nocodb_connector/
- **Live demo:** https://demo20.bambooforge.dev/odoo/action-bambooforge_nocodb_connector.action_nocodb_control_tower
- **Store page:** https://apps.odoo.com/apps/modules/20.0/bambooforge_nocodb_connector
- **Manual last updated:** 2026-10-15

---
# NocoDB Connector

A read-only importer that brings your NocoDB (the open-source no-code database /
Airtable alternative) workspace into Odoo 20: it imports your **bases** and the
**tables** inside each base, with a live **row count** for every table, so you
get an auditable inventory of your NocoDB data without leaving Odoo. Nothing is
ever written back to NocoDB.

This page is the complete manual. If you follow it top to bottom you can install,
connect, run your first import, automate it, and fix the common issues **without
contacting support**.

## Overview

The connector reads from the NocoDB REST/Meta API (`api/v2`) and mirrors the
metadata into dedicated Odoo models. It covers:

- **Bases** — every NocoDB base (database/project) from `GET /api/v2/meta/bases`,
  imported into **NocoDB Base** records (the base id and its title).
- **Tables** — the tables inside each base from
  `GET /api/v2/meta/bases/<baseId>/tables`, imported into **NocoDB Table**
  records. Each table links back to its base (resolved from the table's `baseId`).
- **Row counts** — a live record count per table, read from
  `GET /api/v2/tables/<tableId>/records?limit=1` ->
  `pageInfo.totalRows` and stored on the table at import time.

Direction of sync: **Odoo <- NocoDB** (import only). This connector never writes
to NocoDB — no create, update or delete is ever sent to your workspace. Bases are
imported before tables so each table can link back to its base.

Importing the actual *table records* (the row data itself) is a roadmap item; v1
imports the base/table inventory and row counts only.

Every remote call goes through a queue: nothing is written to Odoo until a job
runs, jobs retry with back-off on transient failures, and a circuit breaker
pauses an instance that keeps failing.

## Tested against the real thing

Automated tests run against a bundled mock on every release; the line below is the part no mock can give you - the connector pointed at the real platform, with real records.

Tested for real against a current NocoDB release: 2 bases and 2 tables (a Deals table with 5 rows) came into Odoo with 0 errors, using an API token created for the purpose.

## Requirements

- **Odoo**: 20.0, Community or Enterprise.
- **NocoDB**: any NocoDB exposing the v2 Meta/REST API (`/api/v2/meta/bases`,
  `/api/v2/meta/bases/<id>/tables`, `/api/v2/tables/<id>/records`) with
  `xc-token` header auth. NocoDB must be reachable from the Odoo server.
- **Python**: no extra libraries beyond a standard Odoo 20 install.
- **Odoo access**: any internal user can use the connector screens. The NocoDB
  API token is stored in a system-only field, so only the **Settings /
  Administration** user can read or change it.
- **Network**: outbound HTTP/HTTPS from Odoo to your NocoDB server. By default the
  connector refuses internal/loopback/private hosts as an SSRF safeguard (see
  *Safety features*).

## Installation

1. Copy `bambooforge_nocodb_connector` into your Odoo addons path.
2. Restart the Odoo service.
3. Open **Apps**, click **Update Apps List**, search for *NocoDB*, and press
   **Activate / Install**. The only dependencies are *base* and *mail*.

No live NocoDB server is required to evaluate the connector: a mock NocoDB API
ships inside the module, so you can install, explore and run the full import flow
against sample data before pointing it at a real NocoDB.

## Step 1 — Create an API token in NocoDB

NocoDB authenticates with a single API token, sent as the `xc-token` header on
every request. To create one:

1. In NocoDB, open **Account Settings** (your avatar, top of the sidebar).
2. Go to the **Tokens** section.
3. Click **Create / Add new token**, give it a description such as `Odoo`, and
   create it.
4. Copy the generated token. You will paste it into Odoo in Step 2.

Because the connector is read-only, the token only ever needs read access to your
bases, tables and records.

## Step 2 — Create the connection in Odoo

Open **NocoDB Connector ▸ Configuration ▸ Instances** and create a record.

![NocoDB instance / connection cockpit](01-connection-cockpit.png)

Key fields:

| Field | What to enter |
|---|---|
| Name | A label for this connection, e.g. *My NocoDB*. |
| Base URL | Your NocoDB server root, e.g. `https://nocodb.example.com` or `http://localhost:8200`. |
| Authentication | *API Token (xc-token)* — the only option NocoDB supports. |
| API Token | The token from Step 1 (visible to administrators only). Sent as the `xc-token` header on every request. |
| API Path | Leave the default `api/v2` unless your NocoDB differs. The client builds `<Base URL>/<API Path>/meta/bases` and so on. |
| Verify SSL | Keep on for production. Turn off only for self-signed test certificates. |
| Allow internal host | Off by default. Turn on only to reach a NocoDB on localhost or a private network (lowers the SSRF guard — see *Safety features*). |

Then click **Test Connection**. The connector lists your bases as a lightweight
auth + connectivity check. A green *Connected* state means the token and URL are
correct. If it fails, the exact error is shown on the form and recorded in
**Logs** (see *Troubleshooting*).

![An imported NocoDB base with its tables](02-synced-base.png)

## Step 3 — First import (dry-run, then live)

New instances start with **Dry-run** ON. In dry-run, import jobs *simulate*
writes: instead of changing data they produce **Validation Results** you can
review under **NocoDB Connector ▸ Operations ▸ Validation Results**. This lets you
confirm what *would* happen before anything is written.

To run a first import:

1. On the instance, click **Queue Base Import** (and/or **Queue Table Import**).
   This enqueues jobs; it does not block the UI.
2. Jobs are processed by the **Nocodb Queue Processor** scheduled action (every
   minute), or immediately if you run it manually from **Operations ▸ Queue Jobs**.
3. Review **Validation Results** while still in dry-run.
4. When satisfied, open the instance, turn **Dry-run** OFF, and run the imports
   again to write the records for real.

Imported records land in **NocoDB Connector ▸ Imported Data ▸ Bases** and
**▸ Tables**. Each carries its NocoDB id, so re-imports update the same record
instead of duplicating it. Bases are imported before tables so each table links
back to its base.

![Imported NocoDB tables with live row counts](03-tables-list.png)

## Field mapping & customization

- **Field Mappings** (Configuration) map NocoDB fields to Odoo fields per entity.
  Use **Generate suggested mappings** on the instance to seed the core ones, then
  adjust.
- **Schema Fields** lists the discovered fields per entity. Run **Schema
  Introspection** on the instance to refresh it: it records the Odoo target
  fields and samples one live NocoDB record (falling back to the bundled mock when
  the API is unreachable) so you can see both sides.
- **Import limits** on the instance cap how much is pulled per run: *Bases import
  limit* (default 100) and *Tables import limit* (default 200), with matching
  *reconcile* limits. Raise them if your workspace is larger.

Because the connector is read-only, there are no stock/image/tax/order toggles —
it imports the base and table inventory and row counts, nothing more.

## Automation (scheduled actions & webhooks)

The module ships these scheduled actions (**Settings ▸ Technical ▸ Scheduled
Actions**):

| Scheduled action | Default | Purpose |
|---|---|---|
| Nocodb Queue Processor | every 1 min | Processes queued import jobs. |
| Nocodb Reconciliation | every 15 min | Pulls recent remote ids for enabled entities and queues what is missing. |
| Nocodb Maintenance | every 1 hr | Recovers stale/locked jobs and trims old jobs and logs. |
| Nocodb Flow Scheduler | every 5 min | Runs scheduled import flows. |
| Nocodb Flow Metrics | every 1 hr | Aggregates flow-run metrics. |
| Nocodb Auto Recover | every 15 min | Reopens a tripped circuit breaker once NocoDB is healthy again. |

Turn on **Auto import** / **Auto reconcile** per entity on the instance
(*Auto import bases*, *Auto import tables*, *Auto reconcile bases*, *Auto
reconcile tables*) to let the scheduled actions keep the inventory current
hands-free.

**Webhooks**: this connector is a pull-only importer. The route
`/nocodb/webhook` exists only as a neutralized stub that always answers a clear
"not supported" response (HTTP 501) — there is **no** webhook intake. A genuine
push path (NocoDB does support per-table webhooks) is a roadmap item, not part of
this read-only v1. The scheduled reconciliation keeps your inventory current
without it.

## Safety features

- **Read-only by design** — the connector only ever issues authenticated `GET`
  calls to NocoDB. There is no write path, so it cannot create, change or delete
  anything in your workspace.
- **Dry-run mode** — simulate Odoo-side writes and review Validation Results
  before going live (*Dry-run* field, ON by default).
- **Business validation profiles** — *Minimal / Standard / Strict* gate risky
  writes (*Business validation profile* field).
- **Resilient queue** — every import is a job with retry and exponential back-off
  (*Retry limit*, *Backoff policy*, *Backoff base/cap minutes*).
- **Circuit breaker** — after repeated failures (or an auth/configuration error)
  an instance auto-pauses (*Tripped*); the Auto Recover action reopens it once
  NocoDB responds again (*Auto-pause threshold*, default 5).
- **Rollback snapshots** — when enabled, imports capture a snapshot so you can
  undo a batch from **Operations ▸ Rollback Snapshots** (*Rollback enabled*).
- **SSRF guard** — the connector refuses internal/loopback/private/link-local/
  reserved hosts unless *Allow internal host* is explicitly enabled.

## Troubleshooting

| Symptom | Cause and fix |
|---|---|
| Test Connection fails with 401 / 403 | Wrong or missing API token. The `xc-token` is invalid or was revoked. Re-create it in NocoDB (**Account Settings ▸ Tokens**) and paste it into the **API Token** field (Step 1). |
| "NocoDB API token (xc-token) is required." | The **API Token** field is empty. Paste the token; only an administrator can see or edit this field. |
| "...is not allowed because it resolves to the non-public address..." | Base URL points at localhost/private/loopback/link-local IP. Enable *Allow internal host* on the instance (test/self-hosted only). |
| "the URL must start with http:// or https://" | The Base URL has no scheme. Enter the full root, e.g. `https://nocodb.example.com`. |
| SSL errors on Test Connection | Self-signed certificate. Use a valid cert, or turn off *Verify SSL* for testing only. |
| 404 on bases/tables | The **API Path** is wrong for your NocoDB. The default is `api/v2`; adjust it if your server exposes the API elsewhere. |
| Row counts all show 0 | The token cannot read records, or the table is empty. Confirm the token has read access; the count comes from `pageInfo.totalRows` on `/tables/<id>/records`. |
| Jobs stay in *Pending* | The Queue Processor is off or the instance is paused. Check **Scheduled Actions** is active and the instance is not *Paused*. |
| Instance shows *Tripped* | Circuit breaker tripped after repeated failures (or an auth error). Fix the token/URL; Auto Recover reopens it, or click **Resume**. |
| Nothing happens after Import | You are in **Dry-run**. Review Validation Results, then turn dry-run off and re-run. |
| Tables imported but not linked to a base | The base was not imported yet. Import bases first (the connector does this automatically when both run); re-run the table import. |

For anything else, **Operations ▸ Logs** records every API call and error with a
timestamp.

## Frequently asked questions

**Which versions are supported?**
Odoo 20.0 on the Odoo side. On the NocoDB side, any server exposing the v2
Meta/REST API with `xc-token` auth. Validate your exact build with the bundled
mock first.

**Do I need NocoDB installed to evaluate it?**
No. A mock NocoDB API ships inside, so you can install, explore and demo the full
import flow before connecting a real server.

**How does authentication work?**
Create an API token in NocoDB under **Account Settings ▸ Tokens** and paste it
into the **API Token** field. The connector sends it as the `xc-token` header on
every request.

**Does the connector write anything to NocoDB?**
No. It is read-only: every call is an authenticated `GET`. It cannot create,
update or delete bases, tables or records in your workspace.

**Does it import the actual rows in my tables?**
Not in v1. It imports the base/table inventory and a live row count per table.
Importing the row data itself is on the roadmap.

**How does it keep the inventory current?**
The scheduled actions (Queue Processor + Reconciliation) re-import on a schedule
when you enable *Auto import* / *Auto reconcile*. There is no webhook intake.

**Is it safe to run against production data?**
Yes. It only reads from NocoDB, and on the Odoo side dry-run is ON by default,
validation gates risky writes, and rollback snapshots let you undo. You decide
when to go live.

**What support and refund policy do I get?**
Every request is answered within 24 hours, setup help included. If you report a
bug within 2 months of purchase and it is not resolved within 15 days, you are
entitled to a full money-back refund.

## Data, privacy & limits

- The connector **reads** bases, tables and per-table row counts from your NocoDB
  and writes the corresponding **NocoDB Base** / **NocoDB Table** records in Odoo.
  It never writes back to NocoDB.
- The API token is stored in an administrator-only field.
- **In scope today**: base import, table import, live row counts, scheduled
  re-import/reconciliation, dry-run, validation, rollback snapshots, SSRF guard.
- **Out of scope / roadmap**: importing the actual table records (row data);
  webhook/push intake from NocoDB; writing any data back to NocoDB.

## Support & updates

- Support: [support@bambooforge.dev](mailto:support@bambooforge.dev) — answered within 24 hours, setup help
  included.
- Refund: report a bug within 2 months of purchase; if unresolved within 15 days,
  full refund.
- Full source is included. Updates track the supported Odoo 20 / NocoDB v2 API line.

## Upgrading & version compatibility

This build targets **Odoo 20.0**. Each Odoo major series (16.0, 17.0, 18.0, 19.0, 20.0) has its
own dedicated build of this module — always install the build that matches your Odoo
version. Mixing a build with a different Odoo series is not supported.

### Patch upgrades (same series, e.g. 20.0.1.0.0 → later)

1. **Back up** your database and filestore first.
2. Replace the module folder with the newer build.
3. Restart Odoo with the module updated:
   
   ```
   ./odoo-bin -c your.conf -u bambooforge_nocodb_connector -d your_db
   ```
4. Odoo applies any schema/data changes automatically. Your existing records and
   configuration are preserved.

### Cross-version migration (moving to a newer Odoo)

Upgrading Odoo itself is a database migration handled by Odoo's standard upgrade
tooling. When you migrate the database to the next Odoo series, install the matching
build of this module for that series. Data created by this module carries over with
the database migration.

After any upgrade the module's scheduled actions resume on their normal cadence —
no manual re-activation is required.

## Uninstallation

You can remove this module at any time from **Apps → (this module) → Uninstall**,
or from the command line. Uninstalling is clean and reversible by reinstalling —
but note what is and is not deleted.

### What is removed

- The module's own tables and every record in them (23 models, prefixed `nocodb.*`) — this is the data this module created.
- The menus, actions, views and reports this module installed.
- Its scheduled actions (cron jobs) — they stop immediately on uninstall.
- Connection records, credentials, field mappings, queue jobs and sync logs stored in Odoo.

### What is preserved

- **Your remote platform is never touched.** Uninstalling only removes the Odoo-side
  connector; products, customers and orders on the external store/service are untouched.
- Records already imported into standard Odoo models (e.g. contacts, products, sales
  orders) remain — they are ordinary Odoo records once created.
- Attachments and chatter messages on standard records are kept.

As always, take a database backup before uninstalling in production.

## Changelog

### 20.0.1.0.2

- Built for Odoo 20: record rules and access rights rewritten onto Odoo 20's single ir.access model, the screens rebuilt on Owl 3, and every icon moved to the icon set Odoo 20 ships.

### 20.0.1.0.0

Current release for Odoo 20.0. This build includes:

- Odoo 20 connector for NocoDB: two-way row sync (import/export) between selected NocoDB tables and Odoo models, plus base/table metadata import.
- Resilient queue, binder-based idempotency, dry-run, SSRF-guarded.

Feature additions and fixes ship as new builds on the Odoo Apps store; this page and
the module's `version` reflect the current published release. Always keep the build
matched to your Odoo series (see *Upgrading & version compatibility*).

## How we make sure it works

Before every release, **66 automated checks** run against this app on Odoo 16, 17, 18, 19 and 20.
Among them:

- Base and table bindings do not collide.
- Dry run export pushes nothing.
- Dry run import writes nothing.
- Reimport updates not duplicates.
- Lock claims pending then refuses second claim.

Tested for real against a current NocoDB release: 2 bases and 2 tables (a Deals table with 5 rows) came into Odoo with 0 errors, using an API token created for the purpose.

The complete list is in the source you receive.
