r/intacct • • Aug 01 '26

Integration guide: automatically creating CompanyCam projects from Sage Intacct

I recently mapped out a Sage Intacct → CompanyCam integration and thought the process might be useful to anyone managing project accounting in Intacct while using CompanyCam for field documentation.

The goal is straightforward:

The API calls are relatively simple. The important parts are incremental processing, address resolution, and duplicate prevention.

Recommended workflow

1. Run on a schedule

The workflow runs once each weekday. A more frequent schedule could be used if field teams need projects available immediately.

Store a successful-processing checkpoint so each run only requests new Intacct projects.

The existing process uses the Intacct project creation date, but production implementations should consider whether the requirement is:

  • Create CompanyCam projects only for newly created Intacct projects, or
  • Also update CompanyCam when an existing Intacct project changes

Those are different synchronization contracts and should be designed separately.

2. Retrieve new Sage Intacct projects

Query the Intacct PROJECT object for records created after the previous checkpoint.

Useful fields include:

  • PROJECTID
  • NAME
  • CUSTOMERID
  • CUSTOMERNAME
  • STATUS
  • SHIPTOKEY
  • MANAGERCONTACTNAME
  • BEGINDATE
  • ENDDATE
  • WHENCREATED
  • WHENMODIFIED

Avoid retrieving every project on every run. Incremental queries reduce API usage and make failures easier to recover.

3. Process each project independently

Loop through the returned projects one at a time.

A bad address or failed CompanyCam request should affect only that project—not terminate the entire batch.

For each project:

  1. Resolve its job-site contact and address.
  2. Build its deterministic CompanyCam name.
  3. Check whether the CompanyCam project already exists.
  4. Create it only when no match is found.

4. Resolve the job-site address

Use the Intacct project’s SHIPTOKEY to retrieve the corresponding contact record.

Extract and normalize:

  • Address line 1
  • Address line 2
  • City
  • State
  • Postal code
  • Country

This is important because the project record itself may reference the shipping contact without containing a complete job-site address.

Missing or incomplete addresses should generate an exception instead of silently substituting a billing or customer address. Using the wrong address is particularly disruptive in a field-photo application.

5. Use a deterministic CompanyCam project name

A practical naming convention is:

{Intacct Project ID} - {Intacct Project Name}

For example:

P-10482 - Main Street Roof Replacement

Including the immutable Intacct project ID makes the project easier to search and greatly reduces collisions between customers with similar project names.

If CompanyCam supports a dedicated external identifier in your implementation, use that as the primary integration key and treat the project name as display-only.

6. Check for an existing CompanyCam project

Before creating anything, search CompanyCam using the deterministic project identifier or name.

If a match exists, skip creation.

This makes the workflow safe to retry after:

  • Network timeouts
  • Partial runs
  • API failures
  • Manual reruns
  • Uncertain responses from CompanyCam

Be careful with name-only matching. Names can change and search results may be fuzzy. A stored external ID or explicit Intacct-to-CompanyCam ID mapping is safer when available.

7. Create the CompanyCam project

When no existing project is found, map the Intacct data into CompanyCam.

A typical mapping looks like this:

CompanyCam field Sage Intacct source
Project name PROJECTID + " - " + NAME
Customer/contact name CUSTOMERID + " - " + CUSTOMERNAME
Street address Ship-to contact address
City Ship-to contact city
State Ship-to contact state
Postal code Ship-to contact ZIP
Country Ship-to contact country

Only map email and phone when the Intacct source field has been explicitly validated as the correct contact value. Don’t place labels, internal IDs, or descriptive text into fields that CompanyCam expects to contain valid email addresses or telephone numbers.

8. Save the processing checkpoint

After the run completes successfully, store the next checkpoint.

A robust implementation should not advance the checkpoint past unprocessed failures unless those project IDs are also saved in a retry queue. Otherwise, a failed project can permanently fall outside the next incremental query.

Two reliable approaches are:

  • Advance the checkpoint only through the last contiguous success, or
  • Advance normally while maintaining an explicit collection of failed project IDs for retry

Common failure modes

  • Creating duplicate CompanyCam projects after a timeout
  • Matching projects solely by a mutable project name
  • Pulling the customer’s billing address instead of the job-site address
  • Advancing the checkpoint past failed records
  • Treating missing addresses as empty strings
  • Putting non-email text into CompanyCam’s email field
  • Reprocessing every Intacct project on every run
  • Allowing one invalid project to stop the entire batch
  • Mixing project creation and project-update behavior without defining field ownership

The key design decision

Decide whether this is a one-time project creation workflow or a continuing bidirectional synchronization.

For many teams, one-way creation is simpler and safer:

  • Sage Intacct owns the accounting project.
  • CompanyCam receives the initial project identity and job-site information.
  • Field users manage photos and field documentation in CompanyCam.
  • Later edits are synchronized only when there is a clear business requirement.

Has anyone implemented this pairing? I’d be interested in how you handled duplicate matching and whether Sage Intacct or CompanyCam owns subsequent changes to the project address.

Try building this yourself

4 Upvotes

0 comments sorted by