---
title: "Certinia to Sage Intacct Migration: Technical Guide & Data Mapping"
slug: certinia-to-sage-intacct-migration-technical-guide-data-mapping
date: 2026-08-28
author: Raajshekhar Rajan
categories: [Sage Intacct, Migration Guide, ERP, Certinia]
excerpt: "A technical guide to migrating from Certinia (FinancialForce) to Sage Intacct — covering data extraction, COA-to-dimension mapping, API constraints, and validation."
tldr: "Certinia-to-Intacct migration requires Salesforce Bulk API extraction, COA-to-dimension restructuring, strict load sequencing, and trial balance validation to the penny."
canonical: https://clonepartner.com/blog/certinia-to-sage-intacct-migration-technical-guide-data-mapping
---

# Certinia to Sage Intacct Migration: Technical Guide & Data Mapping


# Certinia to Sage Intacct Migration: Technical Guide & Data Mapping

Migrating from Certinia (formerly FinancialForce) to Sage Intacct means moving financial data out of a Salesforce-native managed package and into a standalone cloud ERP with a fundamentally different data model. This is not a flat export/import. It is a model redesign: the chart of accounts, dimension structure, entity hierarchy, customer/vendor records, and API extraction method all need rethinking.

Certinia stores ledgers, journals, and invoices as Salesforce custom objects. Sage Intacct is built around a multi-dimensional general ledger where transactions are tagged with independent dimensions rather than relying on segmented account strings or relational lookups. If you treat this as a table copy, the load can technically succeed while the migration fails. The real breakpoints are entity ownership, party masters, COA structure, and reconciliation.

This guide covers the architecture gap between the two platforms, object-by-object data mapping, API constraints on both sides, transformation logic, intercompany mechanics, and the migration sequence that keeps your trial balance intact.

## Architecture Differences That Drive Migration Complexity

Understanding the structural gap between these two platforms is the most important step before writing any migration code.

### Certinia: A Salesforce Managed Package

Certinia stores all financial data inside Salesforce custom objects within managed packages. As with other [ecosystem-native platforms](https://clonepartner.com/blog/blog/desk365-to-jira-service-management-migration-guide), this tightly couples your data extraction to the host environment's constraints. The two primary namespace prefixes are:

- **`c2g__`** — FinancialForce Accounting (FFA) objects: `c2g__codaInvoice__c`, `c2g__codaJournal__c`, `c2g__codaTransaction__c`
- **`fferpcore__`** — Foundations/ERP Core objects: `fferpcore__BillingDocumentLineItem__c`

Because it runs on Salesforce, all data extraction is subject to Salesforce's multi-tenant governor limits:

- **100 SOQL queries per synchronous transaction**, 200 for asynchronous
- **50,000 total rows** returned per transaction across all queries
- **Daily API call limits** that vary by license edition (typically 100,000–1,000,000+)

Key architectural traits:

- **Lookups and Master-Detail Relationships:** A single transaction often spans multiple objects. A journal entry line (`c2g__codaJournalLineItem__c`) looks up to a header, a GL account, and custom dimension objects (Dimensions 1–4).
- **Company Model:** Certinia defines a company as a discrete, self-balancing accounting unit. Many sObjects use company queues for record ownership and visibility. ([help.certinia.com](https://help.certinia.com/TechnicalReference/2024.2/Accounting/Apex/TheCompanyQueue.htm))
- **Storage Limits:** Salesforce data storage is expensive. Older orgs may have archived or purged transactional data, meaning historical records might live in external data warehouses rather than Salesforce itself.

> [!WARNING]
> Certinia's managed package objects are read-only at the schema level. You cannot modify field definitions, and some fields may not be queryable via SOQL depending on your package version and permission sets. Validate field accessibility in a sandbox before building extraction scripts.

### Sage Intacct: Dimensional Cloud-Native ERP

Sage Intacct is a standalone cloud financial management platform. Its defining feature is **dimensional accounting** — instead of encoding reporting segments into account numbers, you tag transactions with independent dimensions.

Standard dimensions include:

| Dimension | Purpose |
|---|---|
| Location | Entity or office |
| Department | Cost center or team |
| Project | Job or engagement |
| Customer | AR counterparty |
| Vendor | AP counterparty |
| Employee | Staff member |
| Item | Product or service |
| Class | Flexible grouping |

You can also add **User-Defined Dimensions (UDDs)** for custom tracking.

Sage Intacct's multi-entity shared companies work differently from Certinia's company model: top-level administration shares lists such as users, chart of accounts, customers, vendors, and employees across entities, with inter-entity activity using mapped due-to/due-from accounts. A Certinia company might map to an Intacct entity, a location structure, or a separate target company. Do not assume 1:1. ([help.certinia.com](https://help.certinia.com/TechnicalReference/2024.2/Accounting/Apex/TheCompanyQueue.htm))

### Customer and Vendor Design

Certinia extends the standard Salesforce `Account` object for both customer and vendor use. Source designs often duplicate what users think of as one customer because AR or AP control accounts can be company-specific — Certinia's own docs show one customer needing separate account records per company when local GLAs differ. ([help.certinia.com](https://help.certinia.com/main/2023.3/Content/Accounting/Features/Accounts/SetupCustomers.htm))

In Sage Intacct, customers and vendors live in shared lists and can be restricted by entity. When you move to Intacct, Customer and Vendor records become standalone — they no longer inherit data from the Salesforce Account. Consolidation of party masters is a design job to complete before migration testing starts.

### Contracts and Revenue Recognition

Contract and revenue data need extra care. Billing Central stores lifecycle state on contract lines with fields such as Amount Billed Externally and Billed Externally To, and active lines can be locked against direct edits. ([help.certinia.com](https://help.certinia.com/main/2026.1/Content/BillingCentral/Features/Contract/ContractFields.htm))

Intacct imports contract headers separately from lines and expenses, with revenue schedules generated from contract-line setup and revenue templates. State-based recreation — rebuilding the contract in Intacct to reflect the current commercial position rather than replaying every historical billing event — usually works better than mirroring every source billing schedule row. Move active commercial terms, billed-through dates, deferred revenue position, and open obligations; archive the rest. ([intacct.com](https://www.intacct.com/ia/docs/en_US/help_action/More/Uploading_Data/Contracts/import-contracts.htm))

Decide these four things before you build anything:

- Whether each Certinia company becomes an Intacct entity, a location strategy, or a separate target company
- Whether duplicate Salesforce Account records should collapse into one Intacct customer or vendor
- Which source codes become GL accounts versus dimensions
- Whether billing, revenue, projects, and CRM workflows stay in Salesforce or move into native Intacct flows

## API Constraints on Both Sides

Both platforms have hard limits that shape batch sizes, scheduling, and error handling.

### Extracting from Certinia (Salesforce Side)

For any migration involving more than a few thousand records, you need the **Salesforce Bulk API 2.0**. Standard Data Loader works for smaller reference tables under 500K rows, but Bulk API is the only practical option for transactional data.

- **Namespace-prefixed fields** are mandatory in all queries. Forgetting `c2g__` or `fferpcore__` prefixes is the most common extraction error.
- Compound fields (addresses, names) must be exported as individual component fields.
- File attachments (e.g., invoice PDFs in Salesforce Files) require a separate extraction workflow.

> [!TIP]
> Always filter SOQL queries by `CreatedDate` or `SystemModstamp` when extracting historical data. This enables chunking and avoids query timeout limits on massive tables like `c2g__codaTransactionLineItem__c`.

### Loading into Sage Intacct

Sage Intacct enforces **Performance Tiers** for API transaction limits (a throttling model similar to the [API access tiers](https://clonepartner.com/blog/blog/jobscore-vs-teamtailor-architecture-tco-migration-guide) found in enterprise ATS platforms):

| Tier | Monthly API Transactions | Offline Concurrency |
|---|---|---|
| Tier 1 (included) | 100,000 | 1 job |
| Tier 2–4 (paid) | Up to 2,500,000 | Multiple jobs |

Each API call can carry multiple records, so efficient batching matters — 100,000 API calls is not 100,000 records. The platform enforces up to **1,296,000 requests per day** and **150 concurrent requests**. XML requests time out after 15 minutes; keep write batches under 100 affected records per request and read queries under 1,000 records per request.

Sage documents 429 throttling and recommends backoff/retry logic. ([developer.intacct.com](https://developer.intacct.com/web-services/error-handling/))

**Common API error responses to expect during a migration load:**

- `BL01001973` — Object not found: a referenced dimension value, GL account, or vendor does not exist. Caused by loading transactions before master data is complete.
- `BL34000061` — The period is not open: the journal date falls in a closed or not-yet-opened accounting period. Requires period setup before historical TB loads.
- `XL03000006` — Required field missing: a mandatory Intacct field has no source value. Common on tax details and payment terms when source system had nulls.

> [!TIP]
> For a typical mid-market migration with 3–5 years of history, Tier 1 will not be sufficient. Budget for a temporary Tier 2+ upgrade during the migration window, then step back down after go-live.

Sage Intacct offers two API protocols: **REST API** and the legacy **XML Web Services API**. Sage now recommends REST for new client applications, but the XML API remains more feature-complete for certain object types commonly used in migrations. If you use XML Web Services, you need a developer license, sender ID and password, company authorization, and a Web Services user. ([intacct.com](https://www.intacct.com/ia/docs/en_US/help_action/More/Customization_and_Platform_Services/Platform_Services_only/developer-resources.htm))

One API trap worth noting: Intacct transaction line items are owned objects. You do not update them as standalone records — you update the transaction header and include the line data in that payload. That matters when replaying invoice, bill, or journal corrections during cutover. ([developer.intacct.com](https://developer.intacct.com/web-services/))

## Object-by-Object Data Mapping

This is the core technical work. Certinia's Salesforce-native objects do not map 1:1 to Sage Intacct objects.

### Master Data

| Certinia Object | Sage Intacct Object | Key Mapping Notes |
|---|---|---|
| `c2g__codaAccountingCurrency__c` | Currency | Multi-currency setup is company-level in Intacct |
| `c2g__codaCompany__c` | Company / Entity | May map to entity, location, or separate company |
| `c2g__codaGeneralLedgerAccount__c` | GL Account | Restructure for dimensional model |
| `c2g__codaDimension1–4__c` | Dimensions (Location, Dept, etc.) | Requires explicit design decisions |
| Salesforce `Account` (customer) | Customer | Deduplicate; Certinia shares the CRM Account object |
| Salesforce `Account` (vendor) | Vendor | Same object in Salesforce, split in Intacct |
| `c2g__codaTaxCode__c` | Tax Detail | Tax code structures differ significantly |

### Transactional Data

| Certinia Object | Sage Intacct Object | Notes |
|---|---|---|
| `c2g__codaInvoice__c` / Line Items | AR Invoice / Line Items | Match payment terms, due dates, dimensions |
| `c2g__codaPurchaseInvoice__c` | AP Bill | Vendor mapping must resolve first |
| `c2g__codaJournal__c` / Lines | Journal Entry / Lines | Historical journals often migrated as summary entries |
| `c2g__codaCashEntry__c` | Cash Receipt / Payment | Bank account mapping required |
| `c2g__codaBankReconciliation__c` | Bank Reconciliation | Consider migrating only post-cutover |
| `c2g__codaTransactionLineItem__c` | GL Transaction Line | Source-of-truth table for TB extraction; carries both `c2g__TransactionCurrency__c` and `c2g__HomeValue__c` |

### The Chart of Accounts Redesign

This is where most migrations succeed or stall. Certinia orgs often end up with bloated charts of accounts because analysis dimensions (Dimension 1–4) are underused or poorly structured. The migration is the right time to flatten the COA and push reporting segments into Intacct's native dimensions.

**Example:** A Certinia COA with 2,000+ accounts encoding location and department in the account number (e.g., `4100-NYC-MKT`) should collapse to 200–400 natural accounts, with Location = NYC and Department = MKT assigned as dimension values.

You must build a mapping table that translates:

`Certinia GL Account + Dim 1 + Dim 2` → `Intacct GL Account + Department + Location`

Here is what that mapping looks like as a SQL transformation:

```sql
-- Certinia source: GL account + dimension combination
-- Target: Intacct natural account + dimension values

SELECT
    tl.c2g__GeneralLedgerAccount__r.c2g__ReportingCode__c    AS source_gl_code,
    tl.c2g__Dimension1__r.Name                                AS source_dim1,
    tl.c2g__Dimension2__r.Name                                AS source_dim2,
    tl.c2g__Value__c                                          AS home_currency_amount,
    tl.c2g__TransactionCurrencyValue__c                       AS transaction_currency_amount,
    tl.c2g__TransactionCurrency__r.Name                       AS transaction_currency,

    -- Lookup against pre-built COA mapping table
    coa_map.intacct_account_no,
    coa_map.intacct_department_id,
    coa_map.intacct_location_id

FROM c2g__codaTransactionLineItem__c tl
LEFT JOIN coa_mapping coa_map
    ON  coa_map.source_gl_code = tl.c2g__GeneralLedgerAccount__r.c2g__ReportingCode__c
    AND coa_map.source_dim1    = tl.c2g__Dimension1__r.Name
    AND coa_map.source_dim2    = tl.c2g__Dimension2__r.Name

WHERE tl.CreatedDate >= '2020-01-01T00:00:00Z'
```

The `coa_mapping` table is the artifact your controller must sign off on before any data moves. It is the single source of truth for the COA redesign and the basis of every trial balance reconciliation.

This is not a data-only task. The controller or CFO must sign off on the new reporting structure before any data moves.

## Intercompany and Multi-Entity Mechanics

Multi-entity Certinia orgs frequently carry intercompany journal lines — entries where one company debits an account and a related company credits it. Certinia stores these as standard journal lines on `c2g__codaJournalLineItem__c` records, tagged to their respective company via `c2g__OwnerCompany__c`. The intercompany relationship is implicit in the pair of offsetting entries.

Sage Intacct makes intercompany activity explicit. The platform uses mapped **due-to/due-from GL accounts** per entity pair. When you post an intercompany transaction in Intacct, the system automatically generates the offsetting entry in the counterpart entity using those mapped accounts.

**What this means for migration:**

1. Extract all journal lines where `c2g__OwnerCompany__c` differs from the journal header company. These are your intercompany lines.
2. Identify the entity pairs involved. For each pair (e.g., Entity A ↔ Entity B), you need a due-to account in A and a due-from account in B configured in Intacct before any transactions load.
3. Historical intercompany balances are typically migrated as period-end net settlement entries — one due-to/due-from pair per entity pair per period — rather than replaying individual intercompany journals.
4. Open intercompany receivables and payables require transaction-level migration so they can be matched and eliminated during consolidation.

> [!WARNING]
> If you load historical intercompany transactions without configuring the due-to/due-from account mapping in Intacct first, the entries will post without generating the offsetting leg. Your consolidated trial balance will be out of balance from the start.

## Historical Data Strategy

Migrating every historical transaction line from Certinia into Intacct is a common anti-pattern. It bloats the new ERP, complicates the timeline, and increases API failure rates. Intacct's own historical import behavior signals this: historical AP/AR imports are supported but behave differently from live posting, and Sage recommends against importing paid or partially paid bills.

**The recommended approach:**

1. **Closed historical years:** Migrate monthly net changes (trial balance) per GL account and dimension combination via Intacct journal entries.
2. **Current fiscal year:** Migrate monthly net changes up to the cutover month, or detailed transactions for the current year only.
3. **Open transactions:** Migrate open AR and AP at the transaction level so they can be paid/received in Intacct.
4. **Legacy archive:** Closed invoices, retired contracts, and workflow artifacts stay in the source system or a keyed archive.

### Period Setup and Opening Balance Dates

A frequently missed failure mode: loading historical trial balance entries into an accounting period that Intacct has not yet opened, or into a period that was subsequently closed, causes `BL34000061` errors at load time and can distort period-to-date reporting if periods are opened out of sequence.

Before loading any historical TB journals:

- Open all target accounting periods in Intacct back to your earliest historical date.
- Set the journal date to the last day of each period (e.g., 2022-12-31 for the FY2022 closing entry).
- After validation, close historical periods in chronological order so the period-to-date figures are locked.
- Post the cutover opening balance as of the first day of the go-live period — not the last day of the prior period — so it appears correctly in period-open reports.

Contracts follow a similar pattern. Intacct contract imports are layered — header first, then lines, then expenses — and revenue templates are tied to company configuration. Move active commercial terms, billed-through dates, deferred revenue position, and open obligations. Archive the rest.

## Data Extraction from Certinia

Because Certinia is Salesforce-native, extraction means using Salesforce tools. For large volumes, script the export around API calls rather than human-run reports.

### The Source of Truth

In Certinia, `c2g__codaTransaction__c` and `c2g__codaTransactionLineItem__c` represent the absolute source of truth for the general ledger. While you extract invoices and payables for open AR/AP, historical financial extraction should prioritize the transaction tables to ensure trial balance integrity.

### Example SOQL Extraction

The extraction query must capture both home-currency and transaction-currency values. Omitting the transaction currency fields is the most common cause of multi-currency rounding discrepancies during reconciliation:

```sql
SELECT 
    Id,
    c2g__Journal__r.Name,
    c2g__LineType__c,
    c2g__GeneralLedgerAccount__r.c2g__ReportingCode__c,
    c2g__Value__c,
    c2g__HomeValue__c,
    c2g__TransactionCurrencyValue__c,
    c2g__TransactionCurrency__r.Name,
    c2g__Dimension1__r.Name,
    c2g__Dimension2__r.Name,
    c2g__Dimension3__r.Name,
    c2g__Dimension4__r.Name,
    c2g__OwnerCompany__r.Name,
    c2g__Period__r.c2g__StartDate__c,
    c2g__Period__r.c2g__EndDate__c
FROM c2g__codaTransactionLineItem__c
WHERE c2g__OwnerCompany__r.Name = 'CompanyA'
  AND c2g__Period__r.c2g__StartDate__c >= 2020-01-01T00:00:00Z
ORDER BY c2g__Period__r.c2g__StartDate__c ASC
```

Key field notes:
- `c2g__Value__c` — the signed GL value in home currency (debit positive, credit negative)
- `c2g__HomeValue__c` — same as Value in single-currency orgs; differs in revalued multi-currency scenarios
- `c2g__TransactionCurrencyValue__c` — the original transaction-currency amount before conversion
- `c2g__OwnerCompany__r.Name` — required for company context filtering; intercompany lines may appear in multiple company extracts

### Extraction Constraints

- **Deleted Records:** Use `queryAll` if you need to audit soft-deleted records, though typically only active records are migrated.
- **Formula Fields:** Bulk API can extract formula fields, but complex cross-object formulas increase extraction times significantly.
- **Company Context:** Carry the source company on every extracted record. Certinia uses company queues for record ownership, and many operations require single-company context. ([help.certinia.com](https://help.certinia.com/TechnicalReference/2024.2/Accounting/Apex/TheCompanyQueue.htm))
- **Custom Objects Outside `c2g__`:** Orgs that heavily customized Certinia often have custom objects outside the managed package namespace that impact financials. A pure extraction of `c2g__` objects will miss this data. Conduct a full metadata audit before extraction.
- **Custom Fields on Packaged Objects:** Many Certinia implementations add custom fields prefixed with the org's own namespace. These don't appear in standard export templates and must be explicitly listed in SOQL queries.

> [!TIP]
> Keep one immutable crosswalk between source IDs and target IDs. That crosswalk is what lets you reconcile balances, trace errors, re-run deltas, and answer audit questions without reverse-engineering the transformation weeks later.

## Loading Data into Sage Intacct

### Load Sequence

Sage Intacct enforces referential integrity strictly. Loading records out of sequence produces validation errors and rejected batches. Follow this dependency chain:

1. **Company / Entity setup** — Multi-entity consolidation rules, intercompany due-to/due-from account mapping, base currency
2. **Chart of Accounts** — The redesigned GL account structure
3. **Accounting periods** — Open all historical periods before loading any TB journals
4. **Dimensions** — All dimension values (Locations, Departments, Projects, Classes, UDDs)
5. **Master data** — Customers, Vendors, Employees, Items, Payment Terms, Tax Details
6. **Historical trial balances** — Via journal entries at each period end, oldest period first
7. **Open AR/AP** — Unpaid or partially paid invoices and bills, with aging intact
8. **Active contracts** — Headers first, then lines, then expenses, then revenue schedule review
9. **Bank accounts and reconciliation** — Set up feeds and reconcile from cutover forward

### Loading Mechanisms

Sage Intacct offers CSV import, the newer import service, and API access. Use CSV or the import service when finance owns the batch and wants template-driven validation in the UI. Be strict about templates: blank CSV fields can overwrite existing values, and headers must match the official template exactly. ([intacct.com](https://www.intacct.com/ia/docs/en_US/help_action/More/ImportService/import-service-vs-CSV-import.htm))

For repeatable loads, delta replays, and cutover automation, use the API.

### Example XML Payload for a Journal Entry

```xml
<content>
  <function controlid="test-journal-1">
    <create_glbatch>
      <journal>GJ</journal>
      <batch_date>10/31/2023</batch_date>
      <batch_title>Historical TB - Oct 2023</batch_title>
      <entries>
        <glentry>
          <accountno>4000</accountno>
          <trtype>1</trtype>
          <amount>5000.00</amount>
          <currency>USD</currency>
          <exchratedate>10/31/2023</exchratedate>
          <exchratetype>Intacct Daily Rate</exchratetype>
          <departmentid>SALES</departmentid>
          <locationid>NY</locationid>
        </glentry>
        <glentry>
          <accountno>1100</accountno>
          <trtype>-1</trtype>
          <amount>5000.00</amount>
          <currency>USD</currency>
          <exchratedate>10/31/2023</exchratedate>
          <exchratetype>Intacct Daily Rate</exchratetype>
          <departmentid>SALES</departmentid>
          <locationid>NY</locationid>
        </glentry>
      </entries>
    </create_glbatch>
  </function>
</content>
```

Note the explicit `currency`, `exchratedate`, and `exchratetype` fields. Omitting these in a multi-currency migration causes Intacct to apply the current rate rather than the historical rate, producing balance discrepancies that are difficult to find after the fact.

### Contract Migration Payload Structure

Intacct contract imports follow a strict three-layer sequence. Each layer must succeed before the next can reference it:

**Layer 1 — Contract Header:**
```xml
<create>
  <contract>
    <contractid>CNT-2023-001</contractid>
    <customerid>CUST-001</customerid>
    <name>Annual SaaS Agreement</name>
    <begindate>01/01/2023</begindate>
    <enddate>12/31/2023</enddate>
    <billingfrequency>Monthly</billingfrequency>
    <currency>USD</currency>
  </contract>
</create>
```

**Layer 2 — Contract Line:**
```xml
<create>
  <contractdetail>
    <contractid>CNT-2023-001</contractid>
    <itemid>SaaS-Platform</itemid>
    <price>1000.00</price>
    <quantity>1</quantity>
    <startdate>01/01/2023</startdate>
    <enddate>12/31/2023</enddate>
    <revenuetemplatename>Monthly Straight-Line</revenuetemplatename>
    <billedthroughdate>10/31/2023</billedthroughdate>
  </contractdetail>
</create>
```

After loading lines, revenue schedules are generated by Intacct based on the revenue template. Do not attempt to import individual revenue schedule lines — let Intacct regenerate them from the contract line configuration. Validate the generated schedule against the billed-through date and deferred revenue balance from your Certinia extract.

### Handling Open AR and AP

Open invoices must come in as standard AR/AP bills in Intacct, not as journal entries. This ensures they appear in subledgers and can be selected for payment.

Do not migrate fully paid invoices as transactions. Their financial impact is already captured in the historical trial balance journal entries. If you bring in paid invoices, you also have to migrate the historical payments and apply them via the API — unnecessary complexity with a high risk of subledger mismatch.

## Rebuilding the Salesforce Integration

If Salesforce remains the CRM of record, treat the post-migration integration as part of the migration scope — not an afterthought. If your sales team depends on seeing invoice status inside Salesforce, that sync needs to be designed before cutover.

Sage Intacct's **Advanced CRM Integration** supports contract billing workflows, account and contact sync, product and price book sync, GL and journal entry, and project and task support. Synchronization runs in real time when enabled. Sage recommends turning synchronization off during setup and enabling data domains in phases after validation. ([intacct.com](https://www.intacct.com/ia/docs/en_US/salesforce/Salesforce/AdvancedCRMIntegration/AdvancedCRM-paths.htm))

Hard boundaries to know:

- Production connects to production, sandbox to sandbox — cross-environment is not supported
- Multi-currency settings must match between Intacct and Salesforce
- One Salesforce org cannot connect to multiple Intacct companies under this integration
- Intacct recommends an integration user with admin rights in both systems

> [!NOTE]
> Advanced CRM Integration's audit trail tracks synchronization and source-selection changes, but not field mapping changes or Order Entry document changes. Keep your mapping workbook and transformation logic under version control outside the product. ([intacct.com](https://www.intacct.com/ia/docs/en_US/salesforce/Salesforce/AdvancedCRMIntegration/Troubleshooting/SFDC-troubleshooting.htm))

Note that Intacct contacts are children of customers/vendors, not a shared global object like Salesforce Contacts. Contact data does not migrate the same way.

## Cutover and Validation

No ERP migration should go live without at least two full test cycles in an Intacct sandbox. Sage Intacct requires paid instances for development and testing — factor this into your budget.

### The Cutover Pattern

1. **Freeze the target model.** Lock entity design, dimension structure, tax behavior, intercompany account mapping, and contract ownership before the final extract.
2. **Run a full rehearsal in sandbox.** Same transformation code, same load order, same reconciliation reports you will use in production.
3. **Load setup before transactions.** Chart, entities, periods, dimensions, parties, items — all before any transactional data.
4. **Run a final delta pass.** Freeze source posting, extract changes since the rehearsal snapshot, replay only the delta.
5. **Reconcile before enabling users.** Do not turn on integrations or user entry until balances and open items tie out.
6. **Enable Salesforce sync in phases.** Only the domains you have validated, widening scope after users confirm correct behavior.

### Trial Balance Reconciliation Method

"Trial balance parity to the penny" requires a comparable report structure from both systems. Here is the reconciliation query pattern:

**Step 1 — Export Certinia closing TB:**
```sql
SELECT
    c2g__GeneralLedgerAccount__r.c2g__ReportingCode__c  AS gl_code,
    c2g__Dimension1__r.Name                              AS dim1,
    c2g__Dimension2__r.Name                              AS dim2,
    c2g__OwnerCompany__r.Name                            AS company,
    SUM(c2g__HomeValue__c)                               AS balance_home_currency
FROM c2g__codaTransactionLineItem__c
WHERE c2g__Period__r.c2g__EndDate__c <= :cutover_date
GROUP BY 
    c2g__GeneralLedgerAccount__r.c2g__ReportingCode__c,
    c2g__Dimension1__r.Name,
    c2g__Dimension2__r.Name,
    c2g__OwnerCompany__r.Name
```

**Step 2 — Export Intacct opening TB via API or report:**
Pull the Trial Balance report from Intacct filtered to the opening period, grouped by GL account, Location, and Department. Export as CSV.

**Step 3 — Join and compare in staging:**
```sql
SELECT
    c.gl_code,
    c.company,
    c.dim1,
    c.dim2,
    c.balance_home_currency   AS certinia_balance,
    i.balance                 AS intacct_balance,
    c.balance_home_currency - COALESCE(i.balance, 0) AS variance
FROM certinia_tb c
LEFT JOIN intacct_tb i
    ON  i.account_no   = coa_map.intacct_account_no
    AND i.locationid   = coa_map.intacct_location_id
    AND i.departmentid = coa_map.intacct_department_id
LEFT JOIN coa_mapping coa_map
    ON  coa_map.source_gl_code = c.gl_code
    AND coa_map.source_dim1    = c.dim1
    AND coa_map.source_dim2    = c.dim2
WHERE ABS(c.balance_home_currency - COALESCE(i.balance, 0)) > 0.01
ORDER BY ABS(variance) DESC
```

Any row returned by this query is a reconciling item that must be resolved before go-live. Penny-level variances on multi-currency accounts are typically caused by rounding; book these to a dedicated **Migration Rounding** GL account rather than forcing incorrect rates.

### Validation Checklist

- **Trial balance parity** — Closing TB in Certinia must match opening TB in Intacct to the penny, for every account and dimension combination
- **Open AR/AP aging** — Run aging reports in both systems and compare line by line (due dates, amounts, currency)
- **Dimension integrity** — Every transaction that carried a Dimension 1–4 value in Certinia must land on the correct Intacct dimension. Spot-check at least 10% of records
- **Multi-currency balances** — Validate both home-currency and transaction-currency amounts; check that `c2g__TransactionCurrencyValue__c` maps to the correct Intacct transaction currency amount
- **Tax code mapping** — Run a tax summary report in both systems for the same period
- **Intercompany balances** — Due-to/due-from accounts in Intacct must net to zero at the consolidated level; any imbalance indicates a missing intercompany leg
- **Deferred revenue and contract state** — Billed-through dates and open obligations for active contracts; regenerated revenue schedules must match the Certinia deferred revenue balance
- **Attachment counts** — Missing document checks against source
- **Source-to-target count checks** — By object and status, using source record ID and document number for spot checks
- **Period-to-date reporting** — Open the first live period in Intacct and confirm opening balances flow correctly into the period's beginning balance; period-locked historical periods should show no activity

> [!CAUTION]
> Do not skip the trial balance reconciliation. If the opening balances don't tie out, every financial report in Intacct will be wrong from day one. Do not let users begin transacting until the variance query returns zero rows.

### Multi-Currency and Exchange Rates

If your Certinia instance uses multi-currency, ensure the base currency of each Intacct entity matches the base currency of the corresponding Certinia company. Extract historical exchange rates from Salesforce (`DatedConversionRate`) or use Intacct's native OANDA integration — but apply the exact rate used in Certinia to prevent rounding discrepancies in the historical trial balance.

When loading multi-currency TB journal entries into Intacct, specify both the transaction currency amount and the home currency amount explicitly. If you let Intacct recalculate the home currency amount using its current rate table, you will get rounding variances on any account that held foreign-currency balances.

Create a dedicated **Migration Rounding** GL account to absorb penny-level multi-currency translation variances. Set a materiality threshold (typically < $50 per account) above which variances require root-cause investigation rather than rounding-account absorption.

### Bank Reconciliation Cutover

Bank reconciliation is notoriously difficult during ERP migrations. Extract uncleared checks and deposits from Certinia and load them into Intacct as legacy transactions or initial open items. When the bank feed is activated, old uncleared items can be matched against new bank statement lines without double-counting the GL impact.

## Common Failure Modes

Based on patterns across ERP migrations of this type:

1. **Underestimating COA redesign.** Finance teams often want to "just move what we have." Much like attempting a lift-and-shift [CMS migration](https://clonepartner.com/blog/blog/wix-to-webflow-migration-a-complete-technical-guide), this defeats the purpose of dimensional accounting and creates bloat in Intacct.
2. **Salesforce governor limits during extraction.** Large Certinia orgs with 5+ years of data will hit Bulk API limits. Plan extraction batches by date range and company.
3. **Loading transactions before dimensions exist.** Intacct rejects any transaction referencing a dimension value that hasn't been created. Error: `BL01001973`.
4. **Inactive reference data.** Certinia transactions often reference users, vendors, or dimensions marked "Inactive." Intacct's API rejects transactions referencing inactive dimensions. Temporarily activate them during load or remap to a generic "Legacy" dimension.
5. **API field truncation.** Large text fields in Certinia can exceed Intacct's character limits (description fields are often capped at 1,000 characters). Migration scripts must truncate or map overflow to custom fields.
6. **Intacct API tier exhaustion.** A full historical load on Tier 1 (100K transactions/month) can take weeks. Upgrade the tier temporarily.
7. **Namespace confusion.** Orgs that heavily customized Certinia often have custom objects outside `c2g__` that impact financials (e.g., custom revenue recognition schedules). A pure extraction of `c2g__` objects misses this data.
8. **Missing the Salesforce–Intacct integration plan.** If your company keeps Salesforce CRM, the migration does not solve ongoing data flow. Design the forward-looking sync before cutover.
9. **Forgetting custom fields on packaged objects.** Many Certinia implementations add custom fields prefixed with the org's own namespace. These don't appear in standard export templates and must be listed explicitly in extraction queries.
10. **Intercompany legs not configured.** Historical intercompany journals loaded without due-to/due-from mapping produce one-sided entries. The consolidated balance will be out of balance and the error is difficult to find post-load.
11. **Period not open at load time.** Journal entries posted to unopened or closed Intacct periods fail with `BL34000061`. Open periods in sequence before loading historical data.
12. **Omitting transaction currency fields from the SOQL extract.** Migrating only `c2g__HomeValue__c` without `c2g__TransactionCurrencyValue__c` makes it impossible to validate multi-currency subledger balances in Intacct.

## Timeline and Effort

Migration timelines vary based on data volume, entity count, and COA complexity:

| Scenario | Timeline | Primary Complexity Driver |
|---|---|---|
| Single entity, 1–2 years of history, clean COA | 4–8 weeks | COA mapping approval |
| Multi-entity, 3–5 years, COA redesign | 3–6 months | Dimension design + intercompany setup |
| Complex multi-entity with rev rec, project accounting, custom integrations | 6–12 months | Contract migration + Salesforce re-integration |

The data migration engineering work — extraction, transformation, and loading — typically takes 2–4 weeks for a mid-market organization with a single entity and clean data. The remaining timeline is COA design and controller sign-off, intercompany account mapping, stakeholder alignment, testing cycles, and integration design. For multi-entity orgs, the intercompany due-to/due-from configuration and consolidated TB reconciliation add 4–8 weeks independently of data volume.

## Getting the Data Layer Right

A Certinia-to-Sage Intacct migration is a structural transformation: from a CRM-embedded financial system to a standalone cloud ERP with a different philosophy about how financial data should be organized. The technical risk lives in five places — the COA redesign, the Salesforce extraction constraints, the Intacct API tier limits, the intercompany due-to/due-from mapping, and the period-setup sequence. Get those right, and the rest is execution.

Attempting this with basic CSV exports and manual data loader tools usually results in broken subledgers, out-of-balance historicals, and weeks of downtime. Automation, strict staging environments, programmatic mapping, and a TB reconciliation query that returns zero rows before go-live are required to execute accurately.

> Migrating from Certinia to Sage Intacct? ClonePartner engineers build programmatic migration pipelines that handle namespace-prefixed extraction, COA-to-dimension mapping, API tier management, intercompany configuration, and trial balance validation. Book a 30-minute call and we'll scope it with you.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### How long does a Certinia to Sage Intacct migration take?

For a single entity with clean data, 4–8 weeks. Multi-entity with COA redesign takes 3–6 months. Complex organizations with revenue recognition and project accounting can take 6–12 months. The data migration engineering work itself is typically 2–4 weeks.

### Should I migrate all historical transactions from Certinia to Sage Intacct?

No. Best practice is to migrate closed historical years as monthly summary journal entries (trial balances) and only migrate open AR and AP at the transaction level. Sage recommends against importing paid or partially paid bills into Intacct.

### What are Sage Intacct API rate limits for data migration?

The default Performance Tier 1 allows 100,000 API transactions per month with one concurrent offline job. Higher tiers support up to 2.5 million monthly transactions. Each API call can carry multiple records, so efficient batching matters. Budget for a temporary Tier 2+ upgrade during the migration window.

### Do I need to redesign my chart of accounts when moving to Sage Intacct?

Usually yes. Certinia orgs often encode location, department, or project segments in account numbers. Sage Intacct uses dimensional accounting — you should flatten the COA to natural accounts and move segments into Intacct dimensions for cleaner reporting.

### Can Sage Intacct stay connected to Salesforce after the migration?

Yes. Sage Intacct's Advanced CRM Integration supports contract billing, account and contact sync, product and price book sync, GL and journal entry, and project and task support. Production must connect to production (no cross-environment), and multi-currency settings must match between the two systems.
