Standalone ARM — Integration Specification
1. Overview
The standalone ARM connects to external systems through a standardized adapter pattern. Each adapter implements a common interface, isolating core ARM logic from vendor-specific API details.
Integration Categories
| Category |
Systems |
Direction |
| ERP |
NetSuite, Microsoft Dynamics 365 |
Bi-directional |
| SIS |
[PLACEHOLDER: specific SIS vendors] |
Read (import students) |
| Payment Gateway |
eway, ABA (direct debit), B Pay, Edstart |
Outbound (process) / Inbound (response) |
| Portal |
Parent Payment Portal |
Internal |
| Authentication |
SSO/JWT (e.g., My Pymble), OTP |
Inbound |
| Notifications |
Email (SMTP/SendGrid/SES), SMS [PLACEHOLDER] |
Outbound |
2. ERP Integration Framework
2.1 Adapter Interface
All ERP adapters implement the following interface:
ERPAdapter {
// Connection
connect(config: ERPConfig): Promise<void>
disconnect(): Promise<void>
testConnection(): Promise<ConnectionStatus>
// Debtor / Customer
syncDebtors(direction: "push" | "pull" | "bidirectional"): Promise<SyncResult>
getDebtor(externalId: string): Promise<DebtorDTO>
createDebtor(debtor: DebtorDTO): Promise<string> // returns external ID
updateDebtor(externalId: string, debtor: DebtorDTO): Promise<void>
// Items
syncItems(direction: "push" | "pull"): Promise<SyncResult>
getItem(externalId: string): Promise<ItemDTO>
createItem(item: ItemDTO): Promise<string>
// Transactions
pushInvoice(invoice: TransactionDTO): Promise<string> // returns external ID
pushCreditNote(creditNote: TransactionDTO): Promise<string>
pushPayment(payment: PaymentDTO): Promise<string>
getInvoiceStatus(externalId: string): Promise<InvoiceStatusDTO>
// Reconciliation
reconcilePayments(dateRange: DateRange): Promise<ReconciliationResult>
// Metadata
getChartOfAccounts(): Promise<AccountDTO[]>
getTaxCodes(): Promise<TaxCodeDTO[]>
}
2.2 Sync Strategy
| Approach |
When |
Description |
| Real-time push |
Transaction creation, payment recording |
ARM pushes changes to ERP immediately |
| Scheduled pull |
Debtor/student updates |
ARM pulls updates from ERP on a schedule |
| Webhook |
Status changes in ERP |
ERP notifies ARM of changes (where supported) |
| Batch sync |
Initial migration, daily reconciliation |
Full or delta sync of entity sets |
2.3 Conflict Resolution
When the same record is modified in both ARM and ERP:
- Last-write-wins — default, configurable per entity type
- ARM-authoritative — ARM value takes precedence (recommended for billing data)
- ERP-authoritative — ERP value takes precedence (recommended for customer master data)
- Manual resolution — flag conflicts for admin review
3. NetSuite Adapter
3.1 Connection Methods
| Method |
Protocol |
Use Case |
| SuiteTalk (SOAP) |
XML/SOAP |
Legacy; full record access, search, bulk operations |
| REST Web Services |
REST/JSON |
Modern; recommended for new integrations |
| RESTlet |
REST/JSON |
Custom endpoints hosted in NetSuite, for specific operations |
| Scheduled Scripts |
SuiteScript |
ARM-side scripts running inside NetSuite (transition path) |
Recommended approach: REST Web Services for standard operations + RESTlets for custom ARM operations.
3.2 Authentication
- Token-Based Authentication (TBA) — recommended
- Consumer Key/Secret + Token ID/Secret
- No password expiry concerns
- Account-level or role-level scope
3.3 Entity Mapping
3.3.1 Customer → Debtor
| NetSuite Field |
ARM Debtor Field |
Notes |
internalId |
external_id |
NetSuite customer internal ID |
entityId |
debtor_code |
Customer number |
companyName |
billing_title |
Or concatenation of firstName + lastName |
email |
primary_email |
|
phone |
phone |
|
defaultAddress |
address |
Address subrecord → JSONB |
isInactive |
status |
true → inactive |
3.3.2 Item → Item
| NetSuite Field |
ARM Item Field |
Notes |
internalId |
external_id |
|
itemId |
item_code |
|
displayName |
name |
|
description |
description |
|
rate / basePrice |
amount |
From pricing matrix |
incomeAccount |
metadata → gl_account |
Revenue account |
taxSchedule |
tax_treatment |
Map schedule to ARM tax treatment |
Record type: ServiceItem |
category: charge |
|
Record type: DiscountItem |
category: discount |
|
3.3.3 Transaction → Invoice / Sales Order
| NetSuite Field |
ARM Transaction Field |
Notes |
internalId |
external_id |
|
tranId |
transaction_number |
|
Record type Invoice |
type: invoice |
|
Record type SalesOrder |
type: billing_order |
|
status |
status |
Status mapping table below |
tranDate |
issue_date |
|
dueDate |
due_date |
|
total |
total_amount |
|
amountPaid |
amount_paid |
|
amountRemaining |
amount_outstanding |
|
line items → item, quantity, rate, amount |
Transaction Line Items |
|
3.3.4 Customer Payment → Payment Record
| NetSuite Field |
ARM Payment Field |
Notes |
internalId |
external_id |
|
tranId |
payment_number |
|
total |
amount |
|
tranDate |
payment_date |
|
paymentMethod |
payment_method |
Enum mapping required |
Applied-to invoice internalId |
transaction_id |
Via ARM lookup on external_id |
3.4 NetSuite-Specific Custom Records
During the transition period, ARM may need to read/write NetSuite custom records:
| Custom Record |
Purpose |
Transition Plan |
| Billing Profile |
Container for billing instructions |
Move entirely to ARM; keep ERP sync summary |
| Billing Instruction |
Item assignment rules |
Move entirely to ARM |
| Billing Instruction Applied To |
Student/debtor assignment |
Move entirely to ARM |
| RPS Record |
Payment schedule entries |
Move entirely to ARM |
3.5 Rate Limits & Throttling
- NetSuite governance limits: [PLACEHOLDER: specific account tier limits]
- REST API: max 10 concurrent requests per account
- SuiteTalk: max 25 concurrent requests per account
- ARM strategy: queue-based with configurable concurrency, exponential backoff on 429/503
4. Microsoft Dynamics 365 Adapter
4.1 Connection Methods
| Method |
Protocol |
Use Case |
| Dataverse Web API |
REST/OData v4 |
Standard CRUD operations |
| Business Central API |
REST/JSON |
Financial transactions |
| Power Automate |
Webhook/Flow |
Event-driven integration |
4.2 Authentication
- OAuth 2.0 — Azure AD app registration
- Client credentials flow (service-to-service)
- Authorization code flow (user-delegated)
- Tenant ID + Client ID + Client Secret
4.3 Entity Mapping
| Dynamics 365 Field |
ARM Debtor Field |
Notes |
accountid |
external_id |
GUID |
accountnumber |
debtor_code |
|
name |
billing_title |
|
emailaddress1 |
primary_email |
|
telephone1 |
phone |
|
address1_composite |
address |
Address fields → JSONB |
statecode |
status |
0 = active, 1 = inactive |
4.3.2 Product → Item
| Dynamics 365 Field |
ARM Item Field |
Notes |
productid |
external_id |
GUID |
productnumber |
item_code |
|
name |
name |
|
description |
description |
|
price |
amount |
From price list |
producttypecode |
category |
Mapping required |
4.3.3 Sales Invoice → Transaction
| Dynamics 365 Field |
ARM Transaction Field |
Notes |
invoiceid |
external_id |
GUID |
invoicenumber |
transaction_number |
|
totalamount |
total_amount |
|
datedelivered |
issue_date |
|
duedate |
due_date |
|
statecode |
status |
Status mapping table below |
4.4 Rate Limits
- Dataverse API: [PLACEHOLDER: specific limits per license tier]
- ARM strategy: same queue-based approach as NetSuite adapter
- Service protection limits: 6,000 requests per 5-minute sliding window per user
5. SIS Integration
5.1 Integration Patterns
| Pattern |
Description |
Use Case |
| API (Real-time) |
Direct API call to SIS for student/family data |
Ideal for SIS vendors with REST APIs |
| File-Based Import |
CSV/Excel file upload or SFTP drop |
Al Faisal pattern (CSV), Pymble pattern (Excel) |
| Data Warehouse / View |
Read from a shared database or view |
When SIS exposes a read replica or warehouse |
| Webhook |
SIS pushes enrollment changes to ARM |
Real-time enrollment updates |
5.2 SIS Data Requirements
ARM requires from the SIS:
| Data |
Required |
Description |
| Student ID |
Yes |
Unique student identifier |
| First Name |
Yes |
|
| Last Name |
Yes |
|
| Family/Account ID |
Yes |
Maps to Debtor |
| Year/Grade Level |
Yes |
For billing configurator item mapping |
| Campus |
No |
For multi-campus institutions |
| Student Type |
No |
For fee segmentation |
| Enrollment Status |
Yes |
Active, withdrawn, graduated |
| Enrollment Date |
No |
For mid-year pro-ration |
| Withdrawal Date |
No |
For mid-year adjustments |
student_id,first_name,last_name,family_id,year_level,campus,student_type,status
STU001,Sarah,Smith,FAM001,7,Main,all,active
STU002,James,Smith,FAM001,5,Main,all,active
[PLACEHOLDER: exact column mapping from Pymble Excel billing files]
5.4 Automated Wizard (Saint Edwards Pattern)
The Saint Edwards implementation provides an automated step-by-step wizard that:
- Imports student data
- Applies appropriate fee structure per year level
- Generates billing instructions automatically
This pattern should be preserved as a configurable template in the standalone ARM.
6. Payment Gateway Integration
6.1 eway (Credit Card)
Connection
| Setting |
Value |
| API URL (Production) |
https://api.ewaypayments.com |
| API URL (Sandbox) |
https://api.sandbox.ewaypayments.com |
| Authentication |
API Key + Password (Basic Auth) |
| Protocol |
REST/JSON |
Operations
| Operation |
API Endpoint |
ARM Action |
| Create Token |
POST /customers |
Store payment method securely |
| Process Payment |
POST /Transaction |
Process RPS credit card payment |
| Query Transaction |
GET /Transaction/{id} |
Check payment status |
| Refund |
POST /Transaction/{id}/Refund |
Process refund |
Payment Flow
ARM RPS Scheduler
│
▼
Query "pending" RPS records for today
│
▼
For each RPS record:
│
├── Retrieve encrypted card token
│
├── POST /Transaction to eway
│ ├── Amount
│ ├── Customer Token ID
│ ├── Transaction Type: "MOTO" or "Recurring"
│ └── InvoiceReference
│
├── Response:
│ ├── ResponseCode "00" → Success
│ ├── ResponseCode != "00" → Failed
│ └── TransactionID → gateway_reference
│
├── Success → Create Payment Record, update RPS status = "processed"
│
└── Failure → Update RPS status = "failed", log failure_code + failure_reason
Error Handling
| eway Response Code |
Meaning |
ARM Action |
00 |
Approved |
Mark RPS processed, create payment |
05 |
Do Not Honour |
Mark failed, schedule retry (configurable) |
51 |
Insufficient Funds |
Mark failed, notify admin |
54 |
Expired Card |
Mark failed, notify parent for card update |
S9995 |
Timeout |
Retry with exponential backoff |
6.2 ABA (Direct Debit)
Overview
ABA (Australian Bankers' Association) is a fixed-width file format submitted to the bank for batch direct debit processing.
| Record Type |
Description |
Position |
| Type 0 |
Descriptive record (header) |
Line 1 |
| Type 1 |
Detail records (one per payment) |
Lines 2..N-1 |
| Type 7 |
File total record (footer) |
Last line |
ABA File Generation Flow
ARM ABA Scheduler (configurable schedule per tenant)
│
▼
Query "pending" RPS records with payment_method = "direct_debit" for date range
│
▼
Generate ABA file:
├── Header: BSB, account, institution name, date
├── Detail: For each RPS → BSB, account, amount, lodgement ref, debtor name
└── Footer: Total count, total amount, hash total
│
▼
Store ABA file (File Record entity)
│
▼
Admin downloads and submits to bank
│
▼
Bank processes (typically 2-3 business days)
│
▼
[FUTURE] Bank returns response file → ARM processes results
[CURRENT] Admin manually updates RPS statuses based on bank statement
ABA Record Fields
Detail Record (Type 1):
| Position |
Width |
Description |
Source |
| 1 |
1 |
Record Type = "1" |
Fixed |
| 2-8 |
7 |
BSB Number |
Debtor bank details |
| 9-17 |
9 |
Account Number |
Debtor bank details |
| 18 |
1 |
Indicator |
Space (blank) |
| 19-20 |
2 |
Transaction Code |
"13" (externally initiated debit) |
| 21-30 |
10 |
Amount (cents) |
RPS amount × 100 |
| 31-62 |
32 |
Account Name |
Debtor name |
| 63-80 |
18 |
Lodgement Reference |
Transaction number |
| 81-87 |
7 |
Trace BSB |
Institution BSB |
| 88-96 |
9 |
Trace Account |
Institution account |
| 97-112 |
16 |
Remitter Name |
Tenant name |
| 113-120 |
8 |
Tax Withholding |
"00000000" |
6.3 B Pay
Overview
B Pay is an Australian bill payment system where parents pay via their bank using a biller code and reference number.
Integration
| Setting |
Description |
| Biller Code |
Institution-specific, assigned by bank |
| Reference Number |
Generated per debtor or per transaction |
| Receipt Method |
Bank settlement report (file-based or API) |
Flow
ARM generates billing order/invoice
│
▼
Include B Pay details on invoice:
├── Biller Code: [tenant biller code]
└── Reference: [unique reference per transaction]
│
▼
Parent pays via their bank's B Pay
│
▼
Bank settles and provides settlement report
│
▼
ARM processes settlement report:
├── Match reference number → transaction
├── Create Payment Record
└── Update transaction status
6.4 Edstart
Overview
Edstart is a third-party tuition payment plan provider. Parents enter an arrangement directly with Edstart, which pays the school.
Integration
| Setting |
Description |
| API |
[PLACEHOLDER: Edstart API documentation] |
| Authentication |
[PLACEHOLDER: Edstart auth method] |
| Settlement |
Edstart pays school; ARM records payment |
Flow
Parent applies for Edstart plan (external)
│
▼
Edstart approves and notifies ARM (webhook or file)
│
▼
ARM records Edstart as payment method on recurrence
│
▼
Edstart makes periodic payments to institution
│
▼
ARM receives settlement notification
│
▼
ARM creates Payment Record against appropriate transaction
7. Parent Payment Portal Integration
7.1 Architecture
The parent payment portal is a web application (part of the standalone ARM) that provides families with:
- Outstanding balances view
- Payment method selection and setup
- Payment schedule configuration
- Payment history
- Invoice/receipt download
7.2 Authentication Methods
| Method |
Implementation |
Current Client |
| OTP (One-Time Password) |
ARM generates and sends OTP to parent email/phone; validates on entry |
Saint Edwards, Al Faisal |
| SSO via JWT |
External portal (e.g., My Pymble) generates a JWT; ARM validates and creates session |
Pymble |
| Username/Password |
[PLACEHOLDER: future method if required] |
— |
OTP Flow
Parent enters debtor code + email on portal login page
│
▼
ARM validates debtor code + email match
│
▼
ARM generates 6-digit OTP, stores hash with expiry (5 min)
│
▼
ARM sends OTP to registered email
│
▼
Parent enters OTP on verification page
│
▼
ARM validates OTP hash + expiry
│
▼
ARM creates session token (JWT, 24-hour expiry)
│
▼
Parent is authenticated, can view billing and make payments
SSO/JWT Flow (Pymble Pattern)
Parent logs in to external portal (My Pymble)
│
▼
External portal generates JWT with claims:
├── sub: debtor_code
├── email: parent_email
├── iss: portal_identifier
├── exp: token_expiry
└── custom claims: [PLACEHOLDER]
│
▼
External portal redirects to ARM portal with JWT in URL/header
│
▼
ARM validates JWT signature using shared secret / public key
│
▼
ARM maps debtor_code → Debtor entity
│
▼
ARM creates session, parent is authenticated
7.3 Portal API Endpoints
| Endpoint |
Method |
Description |
/portal/auth/otp/request |
POST |
Request OTP |
/portal/auth/otp/verify |
POST |
Verify OTP and get session |
/portal/auth/sso/validate |
POST |
Validate SSO JWT |
/portal/billing/summary |
GET |
Current billing summary |
/portal/billing/transactions |
GET |
Transaction list |
/portal/billing/transactions/{id} |
GET |
Transaction detail |
/portal/billing/transactions/{id}/pdf |
GET |
Download invoice PDF |
/portal/payments/methods |
GET |
Available payment methods |
/portal/payments/setup |
POST |
Set up payment plan |
/portal/payments/history |
GET |
Payment history |
/portal/payments/{id}/receipt |
GET |
Download payment receipt |
/portal/profile |
GET |
Debtor profile |
7.4 "Paid from Portal" Anti-Duplication Logic
When a parent sets up payment through the portal:
- ARM marks the billing order as
paid_from_portal = true
- The billing order's
is_closed = true flag is set
- If only some items are covered, specific line items are flagged
- This prevents:
- Duplicate invoices being generated for the same billing order
- Double-charging when the scheduled RPS process runs
- Admin dashboard shows portal-initiated payments separately
8. Notification Integration
8.1 Email Provider
| Provider |
Environment |
Configuration |
| [PLACEHOLDER: primary email provider] |
Production |
API key in environment variables |
| SMTP |
Development/Fallback |
SMTP host, port, credentials |
8.2 Email Events
| Event |
Trigger |
Template |
| Invoice generated |
Transaction status → "sent" |
invoice |
| Payment reminder |
Configurable days before/after due date |
reminder |
| Payment received |
Payment record created |
payment_confirmation |
| Payment failed |
RPS status → "failed" |
payment_failed |
| Payment method expiring |
Card expiry within 30 days |
payment_method_expiring |
| OTP requested |
Portal login |
otp |
8.3 Template Variables
All templates have access to:
{{ tenant.name }}
{{ tenant.logo_url }}
{{ debtor.billing_title }}
{{ debtor.debtor_code }}
{{ transaction.transaction_number }}
{{ transaction.total_amount }}
{{ transaction.due_date }}
{{ transaction.payment_link }}
{{ payment.amount }}
{{ payment.payment_date }}
{{ payment.payment_method }}
9. Webhook Support
ARM exposes both inbound and outbound webhooks.
9.1 Inbound Webhooks
| Source |
Event |
Endpoint |
| ERP |
Customer updated |
/webhooks/erp/customer-updated |
| ERP |
Payment received |
/webhooks/erp/payment-received |
| Payment Gateway |
Transaction result |
/webhooks/gateway/transaction-result |
| SIS |
Enrollment change |
/webhooks/sis/enrollment-change |
9.2 Outbound Webhooks (configurable per tenant)
| Event |
Payload |
invoice.created |
Transaction DTO |
payment.received |
Payment DTO |
payment.failed |
RPS DTO with failure details |
debtor.updated |
Debtor DTO |
9.3 Webhook Security
- HMAC-SHA256 signature in
X-ARM-Signature header
- Timestamp validation (reject > 5 min old)
- Retry with exponential backoff (3 attempts, 1s → 4s → 16s)
- Dead letter queue for failed deliveries
10. Appendix: Integration Checklist per New Client
When onboarding a new client/tenant: