Skip to main content

Custom Accounting Integration Setup Guide

Learn how to connect INGENIOUS.BUILD to your accounting system using webhooks, so approved financial data — invoices, budgets, contracts, and changes — flows directly from your projects into your accounting platform of choice.

Written by Cara Alva

Overview

The Custom Accounting Integration pushes approved financial records out of INGENIOUS.BUILD via webhooks. Because every accounting system has its own API, the integration is intentionally system-agnostic: INGENIOUS sends a standard JSON payload to a webhook URL you control, and middleware on your side (n8n, Retool, Zapier, Jitterbit, or a custom service) transforms that payload and forwards it to your accounting system's API.

This gives you full control over how data lands in your accounting system, while keeping that system as the source of truth for posted transactions.

Supported objects to sync out:

  • Budgets

  • Budget Changes

  • Vendor Contracts

  • Vendor Contract Changes

  • Vendor Invoices


Prerequisites

  • Workspace admin access in INGENIOUS.BUILD (Company Settings → Integrations Hub)

  • An HTTPS endpoint that can accept POST requests with JSON bodies and custom headers — provided by your middleware tool or built in-house

  • Access to your accounting system's API, or a middleware tool that can call it

  • For loading data into INGENIOUS: an Access Token or OAuth client (see the API Overview & Reference Guide)

Heads up: Coupa, SAP, and similar systems are not plug-and-play. Your middleware is responsible for transforming the INGENIOUS payload into the format your accounting system expects. Tools like Jitterbit can help with Coupa specifically, but the choice of middleware is yours.


How It Works

Data moves in two directions, and it's important to understand the difference before you start.

Outbound: INGENIOUS → your accounting system

When a user clicks Sync to Accounting on an approved record, INGENIOUS sends a POST request with a JSON payload to your configured webhook URL.

Trigger: A user clicks Sync to Accounting on a record that meets prerequisites (for invoices, typically internally approved).

Result: Your endpoint receives a JSON payload. Your middleware transforms it and calls your accounting system's API.

Inbound: your accounting system → INGENIOUS

Webhooks only push data out. To bring accounting data into INGENIOUS — vendors, GL accounts, cost codes, projects, business units — use the Public API or, where available, UI / CSV import.

Object

How to load into INGENIOUS

Accounting Cost Codes

Public API or CSV import

Accounting Companies (Vendors)

Public API or Accounting companies module

Accounting Entities (GL Accounts)

Public API

Projects

Public API

Business Units

Public API

Important Distinction: Outbound (Webhooks) vs. Inbound (Public API)

The Custom Accounting Integration (CAI) feature exclusively uses a Webhook “Push” model for Outbound data. INGENIOUS automatically pushes the payload to the customer’s middleware endpoint the exact moment a user clicks Sync to Accounting. If a customer’s IT team intends to run a scheduled script to poll INGENIOUS to export data (e.g., querying the API every 15 minutes for invoices in the submitted_to_accounting state), they do not need to enable or use the CAI feature. They should simply build a standard integration using our Public API, but retrieve the invoices in any of the approved statuses. Mixing these two approaches for outbound data is an anti-pattern.

Note: Customers using CAI Webhooks for outbound data MUST still use the Public API for Inbound data, such as creating Accounting Companies or syncing Payments back to INGENIOUS.

Comparing Approaches: CAI Webhooks vs. API Polling

When discussing integration design with customers, you can help them choose the right path by sharing these trade-offs:

Advantages of using CAI (Webhooks):

  • Built-in Validation (“No map, no button”): CAI enforces Mapping Requirements (e.g., verifying the Accounting Company, Cost Code, or Project are assigned) before the user can even click Sync to Accounting. This guarantees that records are properly linked to existing accounting objects before the data is ever sent, drastically reducing downstream errors.

  • Real-Time Data: The payload is pushed instantly the moment the user clicks the button. There is no waiting for the next scheduled polling cycle.

Advantage of using Public API (Polling) exclusively:

  • Simplified Infrastructure: The customer avoids having to host, secure, and maintain webhook receiver endpoints, relying entirely on their own scheduled API GET requests.


Process

Step 1: Enable the Custom Accounting Integration

  1. Log in to INGENIOUS.BUILD.

  2. Navigate to Company Settings → Integrations Hub.

  3. Select Custom Accounting Integration.

  4. Click Start Integration.

Step 2: Configure Mapping Requirements

This is the first decision in setup, and it controls how strictly INGENIOUS validates records before allowing them to sync to your accounting system.

In the Mapping Requirements panel, choose which of the following must be mapped on a record before it can be synced:

  • Accounting Entity (GL Account)

  • Project

  • Cost Code

  • Cost Type

  • Business Unit

  • Company (Vendor)

All boxes can be left unchecked.

What happens depending on your choice:

  • Nothing required — INGENIOUS will never block Sync to Accounting. The webhook payload will contain only INGENIOUS-native data with no external accounting IDs. It's on your middleware to identify and match resources on its own.

  • Some required — INGENIOUS will block Sync to Accounting until those mappings are filled in on the record.

Tip: Start with no required mappings during testing, then turn requirements on as your middleware matures and you're ready to enforce data quality.

Step 3: Add webhook URLs and headers

For each object type you plan to sync (Budgets, Budget Changes, Contracts, Contract Changes, Invoices):

  1. Paste the webhook URL for that object type.

  2. Add any authorization headers your endpoint expects, for example: Authorization: Bearer your-token-here.

You only need to fill in URLs for the objects you actually plan to sync — leave the others blank.

Step 4: Load accounting data into INGENIOUS

It is best if those accounting object records exist in INGENIOUS first. Use the Public API or CSV import (where supported) to create them.

Best practice — always set a custom_id:

When you create accounting objects in INGENIOUS (via Public API or CSV), include a custom_id value that matches the corresponding record's identifier in your accounting system. That same custom_id appears in every webhook payload, so your middleware can match records directly with no extra lookups. Skipping this means slower syncs and more API calls back to INGENIOUS.

Step 5: Map fields on records (if required)

If you enabled any Mapping Requirements in Step 2, those fields need to be filled in on the record itself before it can sync:

  • Select the Accounting Company for the vendor on an invoice

  • Assign Accounting Cost Codes to each line item

  • Assign the Accounting Entity / GL Account to the record

  • And so on for any other required field

If you didn't require any mappings, skip this step.

Step 6: Test with a sample record

  1. Create a small invoice (or other supported record) and take it through approval.

  2. Map the required fields, if any are enforced.

  3. Click Sync to Accounting.

  4. Confirm your middleware received the payload.

  5. Confirm your middleware successfully forwarded the data to your accounting system.

For a fast end-to-end test, you can temporarily point your webhook URL at a request bin tool to inspect the raw payload before wiring up the full middleware pipeline.

Confirmation message

When the sync succeeds in INGENIOUS, you'll see:

"Successfully Synced"

All payloads share the same top-level shape:

json

{   "name": "...",   "subject": "...",   "data": { ... } }

The data object contains the record's contents plus the accounting mapping identifiers.

Accounting identifier fields

Each payload includes both INGENIOUS-native IDs (id, vendor_id, project_id, contract_id, cost_code_id, etc.) and accounting object fields:

  • accounting_project_id, accounting_project_custom_id

  • accounting_company_id, accounting_company_custom_id

  • accounting_cost_code_id, accounting_cost_code_custom_id

  • accounting_entity_id, accounting_entity_custom_id

For line items, you'll also see fields like unit_value, gross_value, qty, and any per-line accounting mappings.


How the accounting fields behave

The behavior depends on your Mapping Requirements configuration and whether you set a custom_id on the accounting object:

Scenario

accounting_*_id

accounting_*_custom_id

What it means for your middleware

Mapping not required

Empty

Empty

Your middleware matches records on its own

Mapping required, no custom_id set

Populated (INGENIOUS internal ID)

Empty

You can call the matching Public API Get endpoint to retrieve full record data — but it's an extra call per record

Mapping required, custom_id set

Populated

Populated

Ideal — your middleware matches directly, no extra lookups

For full payload schemas for each object type, see the Webhook Payloads reference.


Common Questions

Can we use this with Coupa, NetSuite, QuickBooks, SAP, or our custom ERP?

Yes. INGENIOUS is agnostic of your accounting system. Your middleware handles the translation from the INGENIOUS payload to whatever API your system uses. Some accounting platforms have native integrations such as QuickBooks that you can try instead. No middleware or coding needed on your side.

Do webhooks also import data into INGENIOUS?

No. Webhooks only push data out when a user clicks Sync to Accounting. To bring data into INGENIOUS, use the Public API or CSV imports.

What needs to exist before we can export an invoice?

The invoice has to meet your workspace's export prerequisites — typically internally approved — and all fields you've marked as required in Mapping Requirements must be filled in on the record.

If a vendor exists in INGENIOUS but not in our accounting system, will the export create it there?

No. INGENIOUS does not create new records in your accounting system. Your middleware is responsible for that logic if you need it. Typically, vendors should already exist in both systems and be linked via Accounting Company.

Can we push existing accounting data from our accounting system into INGENIOUS automatically?

Yes — but not through this webhook integration. Use the Public API to write that data into INGENIOUS. You would build that flow in the opposite direction of the sync-out webhook.

Which middleware should we use?

That's your call. Common choices include n8n, Retool, Zapier, Jitterbit (often used for Coupa), or a custom service. Anything that can receive a webhook and call your accounting system's API will work.


Troubleshooting

No payload arrives at your endpoint

  • Confirm the webhook URL is correct and reachable over HTTPS

  • Confirm the authorization header matches what your server expects

  • Confirm any required Mapping Requirements are filled in on the record

Your endpoint returns 400 or 401

  • Pull your endpoint logs — the root cause is almost always on the middleware side

  • Common culprits: missing or incorrect auth header, wrong content type, schema assumptions that don't match the actual payload

  • Re-check the payload against the Webhook Payloads reference

Line items are missing accounting identifiers

  • Confirm Accounting Cost Codes have been created in INGENIOUS

  • Confirm cost codes are mapped on the line items

  • If Cost Codes are required in your Mapping Requirements, the sync will be blocked until they're mapped — that's expected behavior

Vendor isn't recognized in your accounting system

  • Confirm an Accounting Company exists in INGENIOUS for that vendor

  • Confirm the Accounting Company is linked to the vendor on the record

  • Confirm the matching vendor record exists in your accounting system, and that your middleware is matching on the right field (accounting_company_custom_id)

accounting_*_id is populated but accounting_*_custom_id is empty

This means the mapping is required, but the accounting object in INGENIOUS was created without a custom_id. You have two options:

  1. Quick fix: Use the accounting_*_id and call the matching Get Public API endpoint to retrieve the full record. Adds an extra API call per record.

  2. Right fix: Update the accounting object in INGENIOUS to include a custom_id so future payloads are self-contained.

Fast-path test for any issue

Create a small approved invoice with one line, map a known Accounting Company and Accounting Cost Code, paste a test webhook URL (a request bin works), click Sync to Accounting, and inspect what arrived against the Webhook Payloads reference. This isolates whether the problem is on the INGENIOUS side, the network, or your middleware.

Setup Checklist

  • HTTPS endpoint ready, accepts JSON with headers

  • Webhook URL(s) and auth header(s) added under Custom Accounting Integration settings

  • Mapping Requirements configured (or intentionally left blank for testing)

  • Accounting Companies, Cost Codes, Entities, Projects, and Business Units loaded in INGENIOUS — with custom_id set on each where possible

  • Required fields mapped on the test record

  • Test record approved

  • Test record synced via Sync to Accounting

  • Payload received by middleware and successfully forwarded to accounting system


Summary

The Custom Accounting Integration gives you a flexible, system-agnostic way to push approved financial data from INGENIOUS.BUILD into any accounting system you use. Webhooks handle the outbound flow; the Public API and CSV imports handle the inbound flow. With Mapping Requirements thought through up front and custom_id values set on every accounting object, your middleware can match records cleanly without extra lookups — and your accounting system stays the source of truth for posted transactions.

Did this answer your question?