Documentation Index
Fetch the complete documentation index at: https://docs.dualentry.com/llms.txt
Use this file to discover all available pages before exploring further.
Building a Custom Integration
A DualEntry integration connects a partner system to a customer’s DualEntry organization, transforms data between the two systems’ models, and persists it through DualEntry’s Public API. Every integration that ships through the partner program must satisfy the requirements on this page before it goes live to mutual customers.
Architecture overview
DualEntry is a cloud accounting and ERP platform. Integrations connect a partner system to a DualEntry organization, transform data between the two systems’ models, and persist it through DualEntry’s APIs. Depending on your use case, data moves in either direction - or both.
A typical integration includes the following layers:
- Auth layer - Establishes a secure connection between your system and a DualEntry organization. DualEntry supports OAuth 2.0 (recommended) and API key authentication. Credentials are scoped per organization.
- Sync layer - Moves data on a schedule, in response to webhooks, or on demand. Most integrations run as background jobs on the partner side.
- Mapping layer - Translates fields between your data model and DualEntry’s. Some mappings are fixed; others are configurable by the customer in the DualEntry UI.
- Deduplication layer - Prevents duplicate records using stable external IDs and upsert semantics.
- Error and retry layer - Handles transient failures with backoff (see Errors and Rate limiting), surfaces persistent failures to customers via DualEntry’s Sync History view.
Integration categories
Not all integrations follow the same pattern. The category yours falls into determines the setup flow, mapping requirements, and certification expectations.
- Standard transactional - The most common. The customer authenticates, maps accounts, and data flows on a schedule. Examples: corporate cards, payment processors, payroll, billing platforms.
- Bank feed - Bank account data sync rather than transactional record mapping. Different setup paradigm.
- Data warehouse / BI push - One-way data push for analytics or reporting. No record-level sync.
- File-based - Data exchanged via structured file transfer (CSV, EDI, etc.) rather than synchronous API calls. Typically not customer-self-service to set up.
- ERP migration - One-time or staged historical data import from a legacy system.
Complexity tiers
Integration complexity shapes how much setup UI, configuration, and testing it needs.
- Tier 1 - Simple: API key auth, single entity, one-way sync, minimal mapping.
- Tier 2 - Standard: OAuth, account or vendor mapping, scheduled sync, bidirectional flow on a few record types.
- Tier 3 - Complex: Multi-entity mapping, classification or department mapping, custom field mapping, multi-currency, cross-company.
Before you start
Get partner access
Before writing any code, you need:
- A signed partner agreement with DualEntry.
- API credentials for your partner account.
- Access to a DualEntry sandbox organization for development and certification testing.
- Access to the partner API documentation (request through your partnership contact).
Contact the partnerships team to get these set up. Don’t start coding against a customer’s production org - sandbox first.
Define your integration scope
Work with the integrations team to nail down the following before you write code:
- Data flow direction - Pull-only, push-only, or bidirectional.
- Record types in scope - Customers, vendors, invoices, bills, journal entries, payments, etc.
- Field mapping - Which fields on your side map to which DualEntry fields, and what transformations are needed.
- DualEntry modules affected - Accounts Payable, Accounts Receivable, General Ledger, Revenue Recognition, Payroll.
- Multi-entity support - Whether customers need multiple instances of your integration in a single DualEntry org (for example, one per legal entity).
- Attachment handling - Whether you sync files (PDFs, receipts) along with records.
Key questions to resolve early
- Does your platform support sandbox or test environments? You need one for end-to-end testing.
- Does your API return paginated results? What’s the maximum page size? See Pagination for DualEntry’s conventions.
- Do you support webhooks, or does DualEntry need to poll? What polling interval is acceptable?
- What are your rate limits? What’s your recommended backoff strategy? See Rate limiting for DualEntry’s limits.
- Do you return stable, immutable external IDs that DualEntry can use for deduplication?
- If syncing attachments: what’s the maximum file size, and what file types do you support?
Implementation
Authentication
Implement the auth flow that fits your security model and your customers’ expectations. See Authentication for DualEntry’s supported flows in detail.
OAuth 2.0 (recommended). This is the best experience for customers and the easiest to maintain.
- Implement the authorization redirect and callback handler.
- Store access and refresh tokens encrypted, scoped to the customer’s organization.
- Refresh tokens automatically before expiry.
- Handle revocation gracefully - if the customer disconnects on either side, the integration fails closed, not continues retrying.
- Request the minimum API scopes you need; don’t over-scope.
API key. Acceptable for simpler integrations or where OAuth isn’t practical.
- Store the key encrypted, scoped to the customer’s organization.
- Validate the key on save by making a lightweight API call before persisting it.
- If your UI exposes fields like Client ID or Client Secret, use clear labels and inline help text - ambiguous auth fields are a top source of failed setups.
Sync engine
Build the sync logic that moves data between systems.
Pull integrations (DualEntry consumes data from your platform):
- Run sync as a scheduled background task on your side, or expose endpoints DualEntry can poll.
- Support configurable sync intervals: 30 minutes, hourly, or daily (with time-of-day for daily).
- Implement a “sync-from” timestamp that defaults to the last successful sync.
- Support manual trigger (“Sync Now”) from the DualEntry UI.
- Support full sync, sync-from-last-synced-date, and custom date range modes.
Push integrations (your platform consumes data from DualEntry):
- Trigger on relevant events (record creation, status change, void, etc.).
- Queue outbound work asynchronously to avoid blocking the originating request.
- Implement retry logic with exponential backoff for failures (see Errors).
Webhook-based integrations:
- Register a webhook endpoint during the customer setup flow.
- Validate webhook signatures or HMACs on every inbound payload - never trust unsigned webhooks.
- Acknowledge receipt immediately and process the payload asynchronously.
- Make webhook processing idempotent - partners (and DualEntry) replay webhooks on failure.
For all sync types:
- Expose the next scheduled sync time to the customer in the UI.
- Report every sync run to DualEntry’s Sync History so customers can see what happened and when.
- Add tracing or logging around your core sync steps so issues can be diagnosed quickly.
Maintain a clear mapping between your data model and DualEntry’s. This becomes part of the integration documentation and your certification artifacts.
A typical mapping looks like:
| Your field | DualEntry field | Type | Required | Transformation |
|---|
invoice.amount | transaction.amount | Decimal | Yes | Convert minor units to major (cents → dollars) |
invoice.currency | transaction.currency_code | String (ISO 4217) | Yes | Validate against DualEntry’s supported currencies |
invoice.date | transaction.date | Date | Yes | Normalize to ISO 8601 |
Common transformations:
- Monetary amounts - Many APIs use minor units (cents). DualEntry uses decimal major units (dollars). Convert explicitly; don’t rely on automatic coercion.
- Dates - Normalize to ISO 8601. Pay attention to timezones - partner timestamps may be UTC, local, or ambiguous, and getting this wrong causes off-by-one-day bugs.
- Statuses and enums - Map your statuses to DualEntry statuses explicitly. Document any statuses that don’t have a clean mapping.
- External IDs - Always store your stable external ID on the DualEntry record. This is what makes deduplication and incremental updates possible.
Default values:
- Define explicit behavior when a source field is null, missing, or invalid.
- Use the integration-level defaults the customer configured during setup (for example, default company, default GL account).
- Never create placeholder records like “Unknown Company” - this corrupts the customer’s data and creates cleanup work.
Cut-off date enforcement
Customers set a cut-off date during setup that defines the earliest record date your integration should sync. Records dated before the cut-off are out of scope and must not flow into DualEntry.
Requirements:
- Accept the cut-off date during initial setup and store it in your integration config.
- Filter sync queries by cut-off date at the query level, not by fetching everything and filtering after - this is a recurring source of bugs.
- Apply the cut-off on initial sync and every subsequent sync.
- Handle edge cases:
- Records dated exactly on the cut-off date → include them.
- Records backdated by your platform after the cut-off → exclude them if their effective date is before the cut-off.
Cut-off enforcement is one of the most common bug sources during certification. Test with records dated just before, on, and just after the cut-off, and verify that re-sync after a long pause still respects it.
Duplicate prevention
Duplicate records are one of the most disruptive integration bugs - they corrupt customer ledgers and require manual cleanup. Get this right from day one.
Requirements:
- Use a stable external ID from your system as the deduplication key.
- Implement upsert logic: if a record with the same external ID already exists in DualEntry, update it instead of creating a new one.
- Make re-sync idempotent - running it twice in a row must never produce duplicates.
- Handle concurrent sync workers correctly. Use upsert semantics or proper locking so that two workers processing the same record don’t race into a duplicate write or an integrity error.
If a customer reports duplicates, the investigation usually comes down to one of: missing external ID, an external ID that changed between syncs, or a race condition in concurrent workers. Make sure none of these are possible by design.
Locked / read-only records
Records imported from your platform may be locked from manual editing in DualEntry to prevent the customer’s accounting data from drifting from your source of truth.
- Define which fields are editable in DualEntry vs. locked to integration-only updates.
- Make the locking behavior visible to customers - they shouldn’t be confused about why a field is greyed out.
- If admin override is supported, document the unlock flow.
Error handling and retry
Robust error handling separates a good integration from a flaky one.
- Classify errors as transient (retry) or permanent (surface to user). Don’t retry indefinitely on a permanent failure.
- Use exponential backoff for transient failures: timeouts, rate limits, 5xx responses. See Errors for DualEntry’s error model and Rate limiting for backoff guidance.
- Respect rate limits. Read rate limit headers from API responses where available and adjust your throughput accordingly.
- Surface persistent failures in DualEntry’s Sync History with actionable error messages. “Sync failed” is not actionable; “Account mapping missing for vendor
Acme Co. - assign a GL account in Settings → Integrations” is.
- Handle integrity errors and duplicate-key violations gracefully in async workers - don’t let one bad row kill the whole sync.
Environments
- Build and test in a sandbox DualEntry organization.
- Maintain a sandbox account on your end too, so customers and the solutions team can demo the integration end-to-end.
- Don’t ship until your integration works cleanly in both sandbox and production environments.
Multi-currency and cross-company
If your integration moves money or creates journal entries - Money-In, Money-Out, Journal Entries, Intercompany Journal Entries, or Bank Transfers - multi-currency and cross-company handling are required.
Multi-currency
- Sync the original transaction currency, not just an amount converted to the customer’s base currency.
- Decide explicitly where the exchange rate comes from: your platform, DualEntry’s daily rate, or a market rate. Document this so customers know what to expect.
- Calculate and post FX gain/loss entries where applicable.
- Handle partial payments in different currencies than the underlying invoice or bill.
- Handle currency mismatches (e.g., an invoice in EUR paid in USD) and document your resolution logic.
Cross-company / intercompany
- Handle transactions that span multiple DualEntry entities.
- Create intercompany journal entries following DualEntry’s intercompany rules.
- Generate elimination entries where required.
- For bank transfers across entities, post to the correct accounts in each entity.
Multi-instance support
Some customers need multiple instances of your integration in a single DualEntry organization - for example, a customer with multiple entities on your platform mapped to multiple DualEntry companies.
If you support this:
- Allow multiple instances of the integration to be created within one DualEntry org.
- Differentiate instances by your platform’s entity ID.
- Run sync schedules independently per instance.
- In any mapping or settings UI surfaced inside DualEntry, make it unambiguous which instance maps to which DualEntry company.
Attachments
Not every integration needs to handle files. If yours does:
- Pull or push the relevant files (PDFs, receipts, supporting documents) along with their parent record.
- Respect file size limits and supported file types on both sides.
- Handle missing or inaccessible attachments gracefully - never fail the entire sync because one file couldn’t be retrieved.
Certification checklist
Before your integration ships to mutual customers, every applicable item below must pass. This is the pre-launch checklist and what the integrations team reviews during certification.
Functional
- New record creation syncs correctly.
- Record updates sync correctly.
- Voids and deletes sync correctly.
- Field mapping matches the documented mapping table.
- Defaults apply correctly when source fields are null or missing.
- Mapping UI only exposes tabs and options relevant to your integration.
- Account and classification mappings invalidate cleanly when settings change.
- Mapping dropdowns are unambiguous (include disambiguating info like account number or type when names alone could collide).
Cut-off date
- Cut-off date is enforced - no records before the cut-off sync into DualEntry.
- Records dated exactly on the cut-off are included.
- Re-sync respects the cut-off.
- Backdated records from your platform respect the cut-off.
Duplicate prevention
- Initial sync produces no duplicates.
- Re-sync is fully idempotent.
- Concurrent sync workers do not produce duplicates or integrity errors.
Multi-currency (if applicable)
- Non-base-currency transactions sync with the correct currency code.
- Exchange rates apply correctly.
- FX gain/loss entries are generated where applicable.
- Partial payments in different currencies are handled.
Cross-company / intercompany (if applicable)
- Intercompany journal entries are created correctly.
- Cross-entity bank transfers post to the correct accounts in each entity.
- Elimination entries are generated as expected.
Money-In / Money-Out (if applicable)
- AR / invoice transactions sync correctly.
- AP / bill transactions sync correctly.
- Received payments are matched and applied.
- Sent payments are recorded accurately.
- Refunds and credits are handled correctly.
Attachments (if applicable)
- Attachments sync alongside their parent records.
- File size limits are respected.
Resilience
- Partner API downtime is handled gracefully with retry.
- Large batch syncs complete without timeout.
- Rate limits are respected.
- Locked records cannot be edited manually in DualEntry.
- Sync History reports every sync run, success or failure.
- Failed syncs surface actionable error messages.
Multi-instance (if applicable)
- Multiple instances per organization run independently.
- Each instance is clearly mapped to the correct DualEntry company.
Common pitfalls
These are the issues that come up most often during certification reviews and post-launch support.
| Pitfall | What to do instead |
|---|
| Records syncing in from before the cut-off date | Filter by cut-off in the sync query, not after fetching |
| Duplicate records on re-sync | Implement upsert by stable external ID with proper concurrency handling |
| Placeholder records like “Unknown Company” appearing in customer data | Use integration-level defaults the customer configured at setup |
| Customers getting stuck on confusing auth fields | Use clear labels and inline help text; validate credentials on save |
| Mapping screens showing raw UUIDs | Resolve and cache display names at sync time |
| Sync failing silently with no record in DualEntry and no error | Log every gap and surface failures in Sync History |
| Duplicate entries in mapping dropdowns | Deduplicate before rendering |
| Migration or initial connect appearing to hang indefinitely | Implement timeout detection and surface clear status to the user |
| AI-driven mapping suggestions feeling laggy | Debounce input and cache results |
| UI not refreshing after a successful connect | Refresh integration status after the connect callback |
| Ambiguous account mappings (multiple accounts with similar names) | Include disambiguating info in dropdowns (account number, type) |
Troubleshooting reference
Common symptoms
| Symptom | Likely cause | Where to look |
|---|
| Sync isn’t triggering | Webhook misconfigured, schedule not set, or integration disabled | Webhook registration, schedule config, integration enable state |
| Duplicate records | Missing or unstable external ID, or concurrent sync race | External ID matching, async worker concurrency |
| Amount mismatches | Currency conversion issue or minor/major unit confusion | Field transformations, decimal precision |
| OAuth auth failure | Token expired, scopes changed, or revoked on partner side | Token refresh logic; prompt customer to reconnect |
| API key auth failure | Key invalid or rotated | Validate with a lightweight API call; prompt re-entry |
| Records appearing from before cut-off | Cut-off filter missing or applied post-fetch | Cut-off logic in sync query |
| Mapping screen shows UUIDs instead of names | Display name resolution missing | Add lookup or cache name resolution |
| Initial connect hangs indefinitely | Timeout or partner API unreachable | Add timeout detection, surface clear status |
| ”Unknown” records appearing | Sync not using customer-configured defaults | Default to integration config, never invent placeholders |
Re-sync procedures
- Manual re-sync - Triggered by the customer via Sync Now in DualEntry.
- Date range re-sync - Re-pull records within a specific window.
- Full re-import - Clear and re-import all data. Use cautiously, and only if your idempotency guarantees are bulletproof.
Observability
- DualEntry exposes integration sync status to customers in the admin UI.
- Integration health metrics flow into the partner observability dashboards - your support team can be granted access on request.
- Detailed sync logs are available for specific runs through the partner portal.
New integration kickoff checklist
Use this when starting a new integration to make sure nothing slips:
- Partner agreement signed.
- API credentials and sandbox org provisioned.
- Field mapping spec agreed with DualEntry’s integrations team.
- Integration category and complexity tier identified.
- Partner sandbox or test environment ready on your side.
- Auth flow implemented and tested.
- Sync engine built with the right schedule and trigger model.
- Field mapping and transformations implemented.
- Cut-off date enforcement implemented.
- Deduplication and idempotency implemented.
- Multi-currency handling implemented (if applicable).
- Cross-company / intercompany handling implemented (if applicable).
- Mapping UI configured with the correct tabs visible.
- Error handling and retry logic implemented.
- Sync History reporting verified.
- Observability and tracing in place.
- All applicable certification checklist items pass.
- Partner-facing documentation published.
Support and resources
- Partner API documentation - Available in the partner portal once your account is provisioned. Request access through your partnership contact.
- Partner support - Reach out through your partnership contact for technical questions, certification scheduling, or post-launch support.
- Status and observability - Integration health dashboards are accessible to your team through the partner portal.
- Public API reference - See the V2 API Reference for endpoint-level documentation.