Articles on: Resources
This article is also available in:

NetSuite integration mapping

Warning: The connector relies on several custom fields and records (custcol_iw_, CUSTOMLIST_IW_, CUSTOMRECORD_CSEG_IW_*).These elements depend on the NetSuite account's configuration. A new instance must expose equivalent fields (or be specifically mapped) before onboarding.


Connection & authentication


  • API used: SuiteQL (NetSuite's SQL query language), exposed via a single REST endpoint:

POST https://{account_id}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql

  • Authentication: OAuth 2.0 Machine-to-Machine (M2M), via a JWT assertion signed in ES256 (grant_type=client_credentials). There is no interactive OAuth flow on the user side.
  • Token endpoint: https://{account_id}.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token
  • Request headers: Authorization: Bearer <token> and Prefer: transient.
  • On a 401 response, the token is automatically regenerated and the request is replayed once; on failure, an InvalidCredentials error is raised.
  • Prerequisites on the NetSuite side:
  1. Enable the REST Web Services and OAuth 2.0 features.
  2. A role with read rights on customer, item, transaction, transactionLine, currency, classification, and any custom records, as well as access to REST Web Services / SuiteQL.


Setting up the connection


The connection is machine-to-machine: you register Fincome as a trusted application in your NetSuite account, then you enter three identifiers in Fincome. The signing private key never leaves Fincome — you only import the Fincome public certificate.


  1. Create the integration record.

Setup ▸ Integration ▸ Manage Integrations ▸ New. Check all the boxes Token-Based Authentication, OAuth 2.0, and Client Credentials (Machine to Machine) Grant, save, then note the Client ID (Consumer Key).
2. Upload the Fincome certificate.

Download the Fincome public certificate: https://fincome-public-assets.s3.eu-west-3.amazonaws.com/netsuite/fincome-netsuite.pem
Then go to Setup ▸ Integration ▸ OAuth 2.0 Client Credentials (M2M) Setup ▸ New: select the integration from step 1, import the certificate and attach it to an entity and a role with REST Web Services / SuiteQL rights (see prerequisites). Note the returned Certificate ID.
3. Fill in Fincome.

In Fincome, open the NetSuite connector and enter your Account ID (Setup ▸ Company ▸ Company Information), your Client ID (step 1), and your Certificate ID (step 2). Optionally, indicate the IDs of your custom revenue recognition fields and your recurring revenue category(ies).


Synchronized objects


The connector processes five flows, in this order:


Flow

NetSuite source

Fincome objects created

Filter condition

customer

customer table

Customer

none (full sync)

product

item table

Product + Price

none

subscription

salesorder transactions

Subscription

taxline = 'F' AND tranDate > TRUNC(CURRENT_DATE)

invoice

salesorder transactions

Invoice + InvoiceLineItem

taxline = 'F' AND tranDate <= TRUNC(CURRENT_DATE)

credit_note

creditmemo transactions

Invoice + InvoiceLineItem

taxline = 'F'



Key point — invoices vs subscriptions. Invoices and subscriptions come from the same record type (salesorder). They are separated only by the transaction date:-tranDate in the future → subscription (Subscription),-tranDate today or in the past → invoice (Invoice).



Only lines where taxline = 'F' are imported (whitelist): any other value — notably tax lines — is excluded. Tax is therefore never imported and tax_amount is always 0.

Field mapping


Customers (customer)


NetSuite field

Fincome field

Note

id

original_id


entitytitle

name


email

email


toplevelparent

root_parent_id

Only set if toplevelparent ≠ id (parent/child hierarchy), resolved via a Customer foreign key


Products & prices (product)


From the item table, the connector creates a Product and a Price:


NetSuite field

Fincome field (Product)

id

original_id

itemid

name


NetSuite field

Fincome field (Price)

id

original_id

id

product_id (foreign key to Product)

itemid

name

itemrevenuecategory

type → subscription if = "1", otherwise one_off


Invoices (invoice)


Header (Invoice):


NetSuite field

Fincome field

Note

id

original_id


tranId

invoice_number


entity

customer_id

foreign key to Customer

tranDate

date

DD/MM/YYYY format; if absent, the invoice is ignored

status

status

mapped via the salesorder table (see § Status mapping)


Lines (InvoiceLineItem):


NetSuite field

Fincome field

Note

transactionLine.id

original_id (combined with the invoice id)


invoice_id

foreign key to Invoice (line ignored if the invoice is absent)

itemrevenuecategory + period dates

type

subscription if the period is valid (period_start < period_end) and itemrevenuecategory = "1", otherwise one_off

creditforeignamount / debitforeignamount

amount_excluding_tax_after_discount

see § Amounts

tax_amount

always 0 (tax lines excluded)

quantity

quantity

transformed into -1 × ceiling(quantity)

currency.symbol

currency_code


transactionLine.memo

description


custcol_iw_rr_start_date

period_start

revenue recognition start date

custcol_iw_rr_end_date

period_end

+1 day (NetSuite bounds the end inclusively)

item

price_id

foreign key to Price


Custom dimensions (custom_axis_field):


NetSuite record

Fincome field

CUSTOMLIST_IW_CONTRACT_TYPE.name

contract_type

CUSTOMRECORD_CSEG_IW_CA_COUNTRY.name

country_name

classification.name

class


Subscriptions (subscription)


NetSuite field

Fincome field

Note

id (+ line id)

original_id

combined identifier

id (transaction)

subscription_set_id

groups the lines of the same salesorder

entity

customer_id

foreign key to Customer

custcol_iw_rr_start_date

subscription_start_date


line amount ÷ number of months of the period

monthly_value

partial months are calculated pro rata

monthly_value_main

monthly_value converted into the base currency (see § Amounts)


Credit notes (credit_note)


Identical structure to invoices, with three differences:


  • source = creditmemo transactions (and not salesorder);
  • status mapped via the creditmemo table (see § Status mapping);
  • original_id = the credit note's own id (it is not a link to an original invoice).

Status mapping


The statuses depend on the source record type.


Sales orders (salesorder) → used for invoices


NetSuite code

NetSuite label

Fincome status

A

Pending Approval

pending

B

Pending Fulfillment

open

C

Cancelled

ignored

D

Partially Fulfilled

open

E

Pending Billing/Part. Fulf.

open

F

Pending Billing

open

G

Billed

open

H

Closed

ignored

Y

Undefined

ignored


Credit notes (creditmemo)


NetSuite code

NetSuite label

Fincome status

A

Open

open

B

Fully Applied

paid

C

Undefined

ignored

D

Voided

ignored


A record moved to an ignored status (canceled/closed order, voided credit note…) is marked as deleted on the Fincome side during the next sync.

Amounts, quantities, dates & currencies


  • Amounts. NetSuite splits each line into two accounting legs. The connector reads the amounts in foreign currency:
  • creditforeignamount → positive amount;
  • otherwise debitforeignamount → negative amount (-1 ×).
  • The netamount field is not used.
  • Quantities. Inverted and rounded up: -1 × ceil(quantity).
  • Dates. Expected format DD/MM/YYYY. Period end dates (period_end) are shifted by +1 day.
  • Currencies. Amounts are expressed in the transaction's currency (*foreignamount). They are converted into the company's base currency at the transaction-date rate (*_main fields). Note: for subscriptions, this date is in the future (tranDate > today), so the conversion uses the exchange rate associated with that future date.


Incremental synchronization & pagination


  • Pagination: by limit (1000) and offset on SuiteQL.
  • Cursor: { offset, last_modified_date }. Once a flow is exhausted (hasMore = false), offset resets to 0 and last_modified_date advances to the start date of the last sync.
  • Last modification field:
  • customer → lastmodifieddate;
  • subscription / invoice / credit_note → t.lastmodifieddate.
  • Deletions. Permanent deletions on the NetSuite side are not propagated: a deleted record simply stops appearing, without being removed from Fincome. However, a record moved to an ignored status (see § Status mapping) is marked as deleted.

Required custom fields & records


These elements must exist in the NetSuite instance for a complete mapping:


Element

Fincome usage

custcol_iw_rr_start_date

period start (period_start, subscription_start_date)

custcol_iw_rr_end_date

period end (period_end)

CUSTOMLIST_IW_CONTRACT_TYPE

contract_type custom dimension

CUSTOMRECORD_CSEG_IW_CA_COUNTRY

country_name custom dimension


Note: itemrevenuecategory (which distinguishes subscription / one-off) is a standard field of the item object, not a custom field.

Updated on: 03/07/2026

Was this article helpful?

Share your feedback

Cancel

Thank you!