Skip to main content

Toolkit overview

The toolkit is a self-contained zip. Once unzipped, this is what you'll find:

nuntiq-connector-toolkit-0.2.0/
├── nuntiq.py <- entrypoint you run
├── settings.json <- your local config (gitignored)
├── settings.example.json <- template, copy to settings.json
├── requirements.txt

├── connectors/ <- your code goes here
│ ├── 01_use_settings.py
│ ├── 02_pull_suppliers.py
│ ├── 03_pull_invoices.py
│ ├── 04_poll_lifecycle_messages.py
│ ├── 05_push_invoices.py
│ └── 06_export_invoices_csv.py

├── fixtures/ <- dummy data tables (JSON, edit freely)
│ ├── supplier.json
│ ├── invoice.json
│ ├── ...
│ ├── _seed/ <- canonical state used by `r` (reset)
│ └── attachment_files/ <- raw bytes served by download_attachment()

├── docs/ <- SDK reference (also on this site)

├── lib/ <- the SDK you import in your connectors
│ ├── objects/ <- SupplierLoad, InvoiceLoad, ...
│ ├── api_client.py
│ ├── context.py
│ ├── logger.py
│ ├── delta.py
│ └── work_dir.py

└── _toolkit/ <- sandbox internals (you can ignore this)
├── runner.py
├── fake_api_client.py
└── json_store.py

The pieces

connectors/ — your code

One .py per entrypoint. Six come pre-installed as templates — they're real examples of the four most common patterns:

FilePatternUsed by
01_use_settings.pyDiagnostic — echoes settingsAnyone debugging config wiring
02_pull_suppliers.pyInbound delta sync, timestamp cursorMaster-data sync (suppliers, orgs, POs)
03_pull_invoices.pyInbound delta sync, numeric_id cursorPulling invoices into Nuntiq
04_poll_lifecycle_messages.pyOutbound lifecycle event pollNotifying external systems of status changes
05_push_invoices.pyClaim → push → ack → resultPushing invoices to a customer's ERP
06_export_invoices_csv.pyRead-only export with attachmentsReporting, archival, ad-hoc exports

Read them. They're heavily commented and cover every framework primitive you'll touch.

fixtures/ — your fake Nuntiq

Each *.json file represents one table. The fake API loads them into memory on startup and reads/writes against the in-memory copy. Edit freely — the next run picks up your changes.

fixtures/supplier.json
[
{
"supplier_number": "SUP-001",
"supplier_name": "Acme Corp",
"is_active": true,
"locations": [
{"location_code": "MAIN", "addresses": [...]}
]
}
]

Press r at the menu to reset everything from fixtures/_seed/. Run a destructive entrypoint, then r to start clean.

lib/ — the SDK

This is identical to what production has. Same module paths, same class names, same method signatures. Imports you write here continue to work when your code is deployed:

from lib.objects.supplier import SupplierLoad # ✅ same in prod
from lib.delta import delta_run # ✅ same in prod

You never edit lib/. The toolkit ships the SDK frozen at the production version it was built against.

_toolkit/ — sandbox internals

The fake API client, JSON store, and local runner. You can ignore this folder — the fact that production uses HTTP and the toolkit uses dicts is invisible to your code.

What the toolkit simulates faithfully

  • The full JobContext shape and every method
  • All read paths (get_all, search, get_by_token) including pagination
  • All write paths (new, save_all) with dirty-tracking semantics
  • Delta state lifecycle (delta_run, delta_get_state, delta_begin, etc.)
  • Invoice claim/ack/result flow with lease semantics
  • Attachment downloads (fixtures/attachment_files/{token}.bin → bytes)
  • Logger output (text format identical to production)

What it doesn't simulate

  • Multipart file uploads. upload_source_documents and upload_invoice_attachments return stub document tokens, but don't actually ingest content. Real uploads need an integration test against dev.
  • Strict status-machine validation. The fake accepts more states than production. Always smoke-test the claim → ack → result loop on dev before releasing.
  • Queues, emails, scheduling, external HTTP. The toolkit doesn't run a scheduler, doesn't send email, and doesn't make outbound requests to anything except what your code calls.
  • Lifecycle delta pagination. Returns one page, no next_cursor.
  • Multi-tenant isolation. customer_number is informational only — your one fixture folder is the only tenant.

When to leave the toolkit

The toolkit catches typos, wrong field names, broken control flow, missing imports, type errors, and most logic bugs. It is not a substitute for an end-to-end test against dev before shipping a connector.

The deploy flow when you're ready:

  1. Push your connectors/your_thing.py into the connector's source repository.
  2. Register the entrypoint key against your connector instance in the admin portal.
  3. Trigger a one-off run via the scheduler.
  4. Watch the live log stream.

What's next