Connector templates
Start a connector from a template. Each template is a complete connector: every entrypoint it needs, the shared modules, a README with every setting and secret, and test settings for the toolkit. The same templates are in the admin portal under Global → Connector Templates; a customer connector created from one starts with exactly this code (version 1), and from then on the code belongs to that customer.
The templates are built from the helpers, so the code you adapt is short: connector logic and field mapping, nothing else.
The templates
There is one template per way of logging in, so the connection code is already right for the customer's system.
ERP over REST
Master data from the ERP into Nuntiq (organizations, suppliers, purchase
orders, receipts, payments, exchange rates, one custom table), invoices from
Nuntiq into the ERP (push_invoice, sync or async) and the ERP's outcome back
(get_invoice_status).
| Template | Login | Typical systems |
|---|---|---|
erp_rest_api_key | API key in a header or query parameter | many SaaS APIs |
erp_rest_basic | user name and password (HTTP Basic) | older on-premise APIs |
erp_rest_oauth2_client_credentials | OAuth 2 client credentials, token kept between runs, warning before the client secret expires | Microsoft Entra ID (Business Central), most SaaS ERPs |
erp_rest_oauth2_refresh_token | OAuth 2 refresh token from a one-time authorization; a rotated refresh token is stored by the connector | Xero, QuickBooks, Exact Online |
erp_rest_oauth2_jwt | OAuth 2 with a JWT signed by a private key | Google service accounts, Salesforce, Entra ID certificate credentials |
erp_rest_oauth1_tba | OAuth 1.0a request signing (HMAC-SHA256) | NetSuite token-based authentication |
erp_rest_mtls | client certificate (mutual TLS), optionally plus an API key | banks, government networks, API gateways |
erp_rest_session | login call, session cookie or token, logout | SAP Business One Service Layer |
ERP over SOAP
| Template | Login |
|---|---|
erp_soap_wssecurity | WS-Security UsernameToken (plain or digest) |
ERP over files
Export files from the ERP (CSV, XML or Excel) for master data, one file per invoice (CSV or XML, plus the PDF) for the ERP to import, and ack or error files back. Optional PGP encryption.
| Template | Login |
|---|---|
erp_sftp_password | SFTP with a password |
erp_sftp_key | SFTP with a private key (optional passphrase, optional password as well) |
erp_sftp_certificate | SFTP with an OpenSSH certificate signed by the customer's CA |
erp_s3 | the customer's own S3 bucket, with an access key the customer creates for us |
Invoices in
get_invoice takes invoices from an external system (an e-invoicing
network, a scanning service, a supplier portal, a folder) into Nuntiq. The
target setting decides how Nuntiq reads them:
capture: the PDF goes through capture, like an e-mail to the receiving inbox;einvoice: the data file (UBL, XML, CSV, JSON) is read by the customer's inbound file formats;json: the connector builds the invoice from the source data and it is imported as it is.
| Template | Source and login |
|---|---|
inbound_rest_api_key | REST API, API key |
inbound_rest_oauth2_client_credentials | REST API, OAuth 2 client credentials |
inbound_rest_oauth2_refresh_token | REST API, OAuth 2 refresh token |
inbound_sftp_password | SFTP, password |
inbound_sftp_key | SFTP, private key |
inbound_sftp_certificate | SFTP, OpenSSH certificate |
inbound_s3 | the customer's S3 bucket |
A real ERP
zoho_books is a complete Zoho Books connector (vendors, purchase orders,
bills and expenses with the PDF, vendor payments back) on the same helpers:
the worked example for what a finished connector looks like.
Pick one
- Which direction? Master data in and invoices out: an
erp_*template. Invoices into Nuntiq from somewhere else: aninbound_*template. - Which transport? An API (REST or SOAP), or files on SFTP or S3.
- Which login? Ask the customer's IT how their system authenticates API clients or SFTP users; pick the template with that login.
If the transport is right but the login is not among the templates, take the
closest one and replace only shared_conn.py (see the
helpers for every login method).
Adapt it
Every template marks the places to change:
shared_mapping.py, section ADAPT: field mapping: the field names of the customer's system (the right-hand side). Keep the Nuntiq side.shared_erp.py(APIs) orshared_files.py(files), section ADAPT: endpoints, paging, folder layout, file formats.shared_conn.py: only when the login differs from the template's.
Keep the entrypoint file names: the file name is the entrypoint key, and the key decides what the run may do in Nuntiq.
Charges, discounts and deductions
Every template that sends invoices out or brings them in carries the invoice's charges and discounts (part of the net amount) and its deductions: amounts subtracted after the invoice total, such as retainage on a progress bill, withholding tax (Italian ritenuta d'acconto, Spanish IRPF, Mexican ISR or IVA retenido) or a deposit already paid. The gross amount is the total before deductions; the amount due is what the supplier is paid (gross minus deductions). Withholding is a deduction, never negative tax.
| Templates | What they do with deductions |
|---|---|
erp_rest_*, erp_soap_wssecurity | The payload has charges, discounts, total (gross) and amount_due. The setting deductions_mode picks: array (a deductions list with type, description, rate, base amount and amount), lines (a negative line per deduction on the GL account deduction_accounts names for its type) or refuse (such an invoice fails with DEDUCTIONS_NOT_SUPPORTED). |
erp_sftp_*, erp_s3 | The invoice file has deductions_total and amount_due in the header columns. CSV: a record_type column (LINE, then one CHARGE, DISCOUNT or DEDUCTION row each with the adjustment_* columns); XML: <Charges>, <Discounts>, <Deductions>. deductions_mode refuse fails such an invoice instead. |
zoho_books | A bill gets the deductions as a negative adjustment with an adjustment_description, so the bill total is the amount due (deductions_mode adjustment), or keeps the gross amount and lists them in the notes (notes), or fails (refuse). An expense with deductions fails with DEDUCTIONS_ON_EXPENSE unless the mode is notes. |
inbound_* (target json) | The source record's amount_due, charges, discounts and deductions become the imported invoice's; the source's words for a deduction type (retention, ritenuta, prepayment, ...) are translated in shared_inmap.DEDUCTION_TYPES. |
A deduction is never dropped silently: an invoice whose deductions the target cannot take fails with a code the AP team sees.
Test it in the toolkit
The toolkit ships every template in templates/<key>/, with a
settings.example.json:
cp templates/erp_sftp_key/settings.example.json settings/acme_files.json
# fill in the secrets and settings
python nuntiq.py acme_files get_supplier
For a file template, set config.local_folder to a folder on your PC with
sample files in it: the template then reads and writes that folder instead
of the server. For an API template, point base_url at the customer's
sandbox. Nuntiq itself is simulated in the toolkit, so nothing reaches a
real tenant.
Set it up in the admin portal
- Customer → Integrations → Connectors → Add, start from the template. Every entrypoint arrives disabled.
- Settings & Secrets: fill the settings and secrets the template's README lists. The template already lists the secrets the connector may update itself (a rotated refresh token, the cached access token).
- Entrypoints and Shared code: paste the files you adapted (same names), enable the entrypoints the customer uses.
- Scheduler Tasks (type
connector_dispatch) for the pulls, for a batch push and for the status run; Integration Rules send invoices topush_invoicefrom the workflow. Give an async push a timeout long enough for the customer's system to answer. - Run once by hand and read the run output.
Network
Connectors reach the customer's system from Nuntiq's fixed outbound IP address, on port 443 (HTTPS) or 22 (SFTP). Ask the customer to allow that address. Another SFTP port can be opened on request. A system on a private network or behind a VPN cannot be reached; it has to be published to the internet for our address. Plain HTTP, FTP and FTPS are not supported.