COMING SOON SuiteHeroes Network — a marketplace for NetSuite talent. Get early access

Case study · 2026 · representative engagement

NetSuite × iSAMS & Famly: one finance picture across schools and nurseries.

Connecting iSAMS (schools) and Famly (nurseries) to NetSuite OneWorld across 40 subsidiaries — billing, payments, occupancy and funded free-hours flowing in via API, with consolidated receivables, revenue-leakage detection and term-based revenue recognition.

iSAMS Famly NetSuite OneWorld SuiteScript 2.1 SuiteTax ARM
40
Subsidiaries consolidated
2
Source systems unified
~3 days
Group month-end close
Hourly
Sync into NetSuite

1The challenge

A UK independent education group ran each of its schools on iSAMS and each of its nurseries on Famly, while group finance consolidated in NetSuite OneWorld. The three systems didn't talk to each other, so finance lived in spreadsheets and manual exports. The pain showed up everywhere:

  • Manual rekeying at scale — fee invoices, receipts and pupil records were exported from 40 systems and re-entered into NetSuite every month, slow and error-prone
  • No consolidated view — there was no single debtor ledger, no group occupancy picture, and no way to compare projected revenue to budget without rebuilding spreadsheets each term
  • Revenue leakage — pupils enrolled but never invoiced went unnoticed; nobody could see enrolment and billing side by side
  • Funded-hours gaps — local-authority funded free-hours entitlement for the nurseries was reconciled by hand, if at all
  • A ten-day close — because every figure depended on manual exports, the group month-end stretched across roughly ten working days

The group needed the operational data in iSAMS and Famly to land in NetSuite automatically, accurately, and per-subsidiary — without a fragile integration that quietly corrupts the ledger.

2The approach

A fully native integration — built entirely inside NetSuite with SuiteScript 2.1 and no third-party iPaaS. iSAMS and Famly are reached directly over their own REST and Batch APIs using N/https callouts and RESTlet webhook receivers; orchestration, mapping, error-handling and monitoring all live in NetSuite as custom records and Suitelets.

1 · Source systems iSAMSREST + Batch API FamlyREST API Webhookspush events 2 · Connectivity tier — native SuiteScript Map/Reduce pollerspaginated N/https RESTlet receiversinbound webhooks Token managerOAuth2 · N/secret 3 · Staging & orchestration — custom records Staging recordspayload + status Mapping engineCOA · tax · subs Dead-letter queueretry + reprocess 4 · NetSuite OneWorld posting AR recordsinvoices, payments ARM + SuiteTaxrevenue recognition ConsolidationOneWorld rollup 5 · Control & observability Admin Suitelettokens · mappings Sync log / auditGoBD retention Reconciliationcounts · alerts External systems Native NetSuite (SuiteScript) Control & monitoring writeback
Five native tiers, all inside NetSuite: source APIs → SuiteScript connectivity → staging & orchestration → OneWorld posting → control & observability, with an optional status writeback to the source systems.

The design is layered so each tier has one job, and every hard problem in a finance integration is handled explicitly rather than hoped away.

1 · Connectivity tier (native SuiteScript)

  • Paginated polling — scheduled Map/Reduce scripts page through the iSAMS REST/Batch and Famly REST endpoints with N/https, cursoring through large result sets without hitting script timeouts.
  • Webhook receivers — RESTlets accept near-real-time push from the source systems, secured with Token-Based Authentication under a dedicated, least-privilege integration role.
  • OAuth2 token manager — client credentials and refresh tokens live in N/secret / encrypted fields, with a keep-alive job refreshing tokens before expiry so no run fails on a stale token.
  • Rate-limit & back-off — outbound calls respect each API's throttling limits, with exponential back-off and jitter on 429 / 5xx responses.

2 · Staging & orchestration

  • Staging records — every raw payload lands in a custom staging record and moves through pending → validated → posted → error, so nothing posts half-mapped and any record is replayable.
  • Mapping engine — custom records resolve subsidiary, fee code → item / GL, chart of accounts, tax code and currency; an unmapped value fails loudly into the queue rather than posting to the wrong place.
  • Idempotency & echo-loop guard — external IDs de-duplicate inbound records, and a last-sync hash stops an update bouncing back as a new change.
  • Dead-letter queue — after a capped number of retries a record is parked for review and one-click reprocessing from the admin Suitelet.
  • Governance management — Map/Reduce yielding and unit budgeting keep long runs inside NetSuite's governance limits, rescheduling rather than failing mid-batch.

3 · Posting, control & observability

  • Per-subsidiary posting — customers, invoices, credit memos and payments are written to the correct one of 40 subsidiaries and consolidate natively in OneWorld.
  • Revenue & tax — term fees feed Advanced Revenue Management for correct period recognition; SuiteTax handles the education VAT treatment.
  • Admin Suitelet — a single console for token / connection status, mapping management and run / queue monitoring.
  • Audit & reconciliation — every run is logged to a custom record with GoBD-conformant retention, and nightly reconciliation jobs compare source vs NetSuite counts and alert finance on any drift.
  • Optional writeback — once a payment is applied in NetSuite, clearance status can be pushed back to iSAMS / Famly over N/https.

3Record mappings

The integration is only as trustworthy as its mappings. Below are the core object and field mappings from each source system into NetSuite, the custom control records that drive them, and the per-object sync behaviour.

iSAMS — schoolsNetSuite OneWorldFamly — nurseriesSchool / divisionSchool ManagerSubsidiaryone per settingsitessiteIdYear / form / houseClass / DepartmentsegmentgroupsroomsPupil / Studentpupil idCustomer : Jobsub-customerchildrenchildIdBilling contactfinancial resp.Customer (AR)id write-backbillPayersbillPayerIdContactparental resp.ContactcontactsFee / charge codeItem (+ GL + tax)via feecode_maplines.account.reference/ planFee billbill idInvoiceexternalIdinvoicesinvoiceIdCharge lineInvoice lineinvoices.lines[]Payment / receiptCustomer Paymentapply to invoicepaymentsexternalSystemCredit noteCredit MemocreateCreditNoteBursary / awardregisterDiscount item / neg. lineby award typediscount line— not applicable —Item + LA-funding customerfunded incomefunded hoursdiscoveryMapping & identity records (NetSuite) govern the transforms:feecode_map · coa_map · tax_map · currency_map · subsidiary_map · payer_xref · sync_log · custbody_sh_last_sync_hash (echo-loop guard)
Data Record Map — source records on each side converge on the NetSuite record of record (centre).
iSAMS → NetSuite (schools)
iSAMS sourceNetSuite targetKey / logic
School / division (School Manager)SubsidiaryOne per setting; resolved via the subsidiary map
Year group / form / houseClass / Department segmentVia the structure map
Academic year / term + datesAccounting period + custbody_termDrives the ARM recognition schedule
Pupil / Student (pupil id)Customer : Job (sub-customer)External ID ISAMS-{host}-{pupilId}; idempotent upsert; entry/leaving dates retained
Billing contact (financial resp.)Customer (AR account)Only financially-responsible contacts become AR customers
Contact (parental resp.)Contact linked to customer / jobNon-paying; not an AR account
Split-billing % per bill payerMultiple invoices / split linesMirrors iSAMS split billing across payers
Fee / charge code (TUIT · LUNCH · TRIP · UNIFORM · WRAP-CARE · REG-DEP)Item (+ GL + tax)Resolved via the fee-code map; an unmapped code fails loudly into the queue
Fee bill (header + lines)InvoiceExternal ID ISAMS-INV-{host}-{billId}; bill number to memo
Charge line (code, qty, net)Invoice line itemItem, GL & tax from the fee-code map
VAT treatmentSuiteTax codeTuition VAT-exempt; extras at the correct rate
Deferred income (fees in advance)ARM deferral + recognitionRecognised across the term; replaces manual monthly journals
Bursary · scholarship · sibling · staffDiscount item / negative lineBy award type; reported separately, not netted into fees
Receipt / payment (DD · card · BACS)Customer PaymentApplied to the originating invoice
Credit noteCredit MemoLeaver credits / refunds
Famly → NetSuite (nurseries) — Public GraphQL fields
Famly source fieldNetSuite targetKey / logic
sites (siteId)Subsidiary / LocationExternal ID FAMLY-{siteId}; via subsidiary map
groups (rooms)Class / DepartmentPer site
children (childId)Customer : Job (sub-customer)External ID FAMLY-CHILD-{id}; sitesRelation.firstDay/lastDay → enrolment / leaver dates
billPayers (billPayerId)Customer (AR account)NetSuite internal id written back to billPayers.externalId
billPayers.children[].share.multiplierSplit ratio across jobsMirrors split billing
billPayers.accountNumber / sortCodeBank details (Direct Debit)Masked in UI; access-controlled
contacts (contactId)ContactLinked to job(s); parental / guardian / emergency
invoices (invoiceId · invoiceNumber)InvoiceExternal ID FAMLY-INV-{id}
invoices.lines[].account.referenceItem + GL (via fee-code map)Famly nominal code → NetSuite item / GL / tax
invoices.lines[].childId · info · amountInvoice linePer-child line; BadMoney decimal parsed to currency
payments (id)Customer PaymentexternalSystem = CUSTOM tag = echo-loop guard
payments.invoices[].invoiceIdApplication to NetSuite invoiceMatched on invoice external ID
payments.viaFamlyPay · isDeposited · depositDateClearing / deposit referenceBank reconciliation
createCreditNoteCredit MemoRefunds / leaver credits
Funded free-hours / LA fundingFunded item + LA-funding customerSee note below — reconciled expected → claimed → LA-paid → posted
Identity, idempotency & write-back
MechanismHow it works
Natural keys / external IDsEvery source record is stored as a NetSuite externalId (ISAMS-… / FAMLY-…) so re-processing is idempotent — upsert, never duplicate
Payer cross-reference payer_xrefResolves an iSAMS contact / Famly billPayerId to one NetSuite customer, then reuses it
Echo-loop guard custbody_last_sync_hashA content hash is compared before posting; unchanged payloads are skipped, so an update never ping-pongs back as a new change
Write-back to sourceNetSuite id stamped to billPayers.externalId (Famly) and an agreed external-reference field (iSAMS); synced payments tagged externalSystem = CUSTOM
Lineage custbody_source / _idEach transaction carries its source system + id for figure → transaction → source drill-through
Authentication & security
SystemCredentialStorage & scope
iSAMS RESTAPI client credentials · per-key module permissions (Pupil Manager, Contacts, Fee Billing, School Manager)In N/secret; least-privilege; server-side N/https over TLS
iSAMS BatchAPI key + selected Batch MethodsRead-only; nightly reconciliation snapshot (XML)
FamlyX-Famly-Accesstoken — org or site token, expiring (7-day pre-expiry reminder)In N/secret; minimum scopes; Public API preferred, Internal API isolated behind an adapter
NetSuiteDedicated Token-Based-Auth integration roleLeast-privilege; full sync-log audit trail; pupil / young-child data minimised under UK GDPR
Custom control & mapping records
RecordPurpose
customrecord_subsidiary_mapMaps each iSAMS school / Famly setting to its NetSuite subsidiary
customrecord_fee_code_mapMaps source fee / billing codes to NetSuite items and GL accounts
customrecord_coa_mapMaps any source GL account to its NetSuite counterpart — unmapped fails loudly
customrecord_tax_mapMaps source tax treatment to SuiteTax codes
customrecord_currency_mapCurrency code + exchange-rate handling for any non-GBP flows
customrecord_sync_logPer-run logging: counts, durations, errors, payload references
custbody_last_sync_hashEcho-loop protection — stops an update bouncing back as a new change
customrecord_payer_xrefCross-references each source payer (iSAMS contact / Famly billPayerId) to its NetSuite customer
customrecord_dead_letterParks failed records with the error and a one-click re-queue action
custbody_source / custbody_source_idStamps source system + id on each transaction for full lineage
Sync behaviour by object
ObjectDirectionTriggerFrequency
CustomersinboundNew / changed payerHourly
InvoicesinboundBilling runHourly (REST) / nightly (Batch)
PaymentsinboundReceipt postedHourly
Occupancy snapshotinboundScheduledDaily
Payment / clearance statuswritebackPayment applied in NetSuiteOptional · hourly

Funded free-hours & Local-Authority funding. The Famly Public API exposes invoices, lines and payments but not a discrete funded-hours object. We model the funded element as dedicated line types (e.g. FUNDED-15H / FUNDED-30H) mapped to a funded-hours item with the Local Authority as the funding customer, then reconcile expected → claimed → LA-paid → posted; where that data is not in the Public API it is read through an isolated Internal-API adapter.

Field and record names shown are representative of how SuiteHeroes structures this integration; exact identifiers are agreed per engagement.

4What it unlocks

One consolidated debtor ledger

A single AR view with aging and a collections worklist across all 40 entities — replacing 40 separate logins and a stack of spreadsheets.

Occupancy that feeds revenue

Pupil and booking counts from iSAMS and Famly drive projected revenue, so unfilled places become a number leadership can act on.

Revenue-leakage detection

Pupils enrolled but not yet invoiced are flagged automatically — fees that would otherwise quietly go uncollected.

Funded free-hours reconciliation

Local-authority funded entitlement for the nurseries is matched against claims, surfacing any unreconciled balance per setting.

Revenue recognised properly

Term-based tuition and nursery fees feed Advanced Revenue Management for correct period recognition, not a cash-in-cash-out posting.

A faster, calmer close

With rekeying gone, the group month-end moved from around ten days to roughly three, and finance manages by exception.

5Technologies used

NetSuite OneWorldSuiteScript 2.1N/https calloutsRESTlet webhooksScheduled Map/ReduceOAuth2 / N/secretiSAMS REST + Batch APIFamly REST APISuiteTaxAdvanced Revenue ManagementCustom records (staging & audit)SuiteQLGovernance management
"Schools and nurseries don't have a NetSuite problem — they have a join problem. The operational systems know who's enrolled and what's owed; NetSuite is the ledger. Put a disciplined staging layer between them and the whole group becomes visible in one place."
Raja Saqib
Founder, SuiteHeroes

Run on iSAMS, Famly and NetSuite?

If your operational systems and your finance system don't talk to each other, that's exactly the kind of integration I build. See the demo, then let's scope yours.