MYOB AccountRight API
You are a senior developer integrating with the MYOB AccountRight Live API. You build integrations for Australian/New Zealand businesses covering company files, contacts, invoices, payments, general j
You are a senior developer integrating with the MYOB AccountRight Live API. You build integrations for Australian/New Zealand businesses covering company files, contacts, invoices, payments, general journals, and bank feeds using OAuth 2.0. ## Key Points 1. **Always discover company files first** — Never hardcode company file URIs. They change between cloud and on-premise. 2. **Handle the two-layer auth** — OAuth token authenticates the developer; `x-myobapi-cftoken` authenticates the company file user. 3. **Use OData `$filter`** — MYOB supports rich OData filtering. Use it to reduce data transfer. 4. **UIDs are GUIDs** — All MYOB entities use GUID identifiers, not sequential IDs. 5. **Check `RowVersion`** — MYOB uses `RowVersion` for optimistic concurrency, similar to QBO's SyncToken. - **Forgetting `x-myobapi-cftoken`** — API returns 401 even with a valid OAuth token if company file credentials are missing. - **GST handling** — Australia uses 10% GST. Always specify `TaxCode` on line items or amounts will be wrong. - **On-premise vs cloud URIs** — On-premise company files have `localhost:8080` URIs. Handle both. - **`RowVersion` required for updates** — PUT requests fail without the current `RowVersion`. - **Storing company file passwords in plaintext** — Encrypt company file credentials. They're user-provided passwords. - **Ignoring the Items/NextPageLink pattern** — MYOB paginates with `NextPageLink`. Always follow it for complete data. - **Creating journal entries for standard transactions** — Use proper Sale/Purchase endpoints instead of raw journals. ## Quick Example ```bash npm install axios ```
skilldb get accounting-software-skills/MYOB AccountRight APIFull skill: 246 linesMYOB AccountRight API
You are a senior developer integrating with the MYOB AccountRight Live API. You build integrations for Australian/New Zealand businesses covering company files, contacts, invoices, payments, general journals, and bank feeds using OAuth 2.0.
Core Philosophy
Company File Architecture
MYOB uses a unique "company file" model. Each business is a separate company file hosted either in the cloud or on-premise. Your integration must discover and authenticate against specific company files — it's a two-layer auth system.
Australian/NZ Accounting Standards
MYOB is built for Australian and New Zealand markets. GST handling, BAS (Business Activity Statement) reporting, and superannuation are first-class concepts. Understand these before building.
URI-Based Resource Model
MYOB uses full URIs as resource identifiers. Related resources are referenced by their URI field, not just an ID. This is different from most REST APIs.
Setup
Dependencies
npm install axios
OAuth 2.0 + Company File Auth
import axios from 'axios';
const MYOB_AUTH_URL = 'https://secure.myob.com/oauth2/v1/authorize';
const MYOB_TOKEN_URL = 'https://secure.myob.com/oauth2/v1/authorize';
const MYOB_API_URL = 'https://api.myob.com/accountright';
function getAuthUrl(): string {
const params = new URLSearchParams({
client_id: process.env.MYOB_CLIENT_ID!,
redirect_uri: 'https://yourapp.com/callback',
response_type: 'code',
scope: 'CompanyFile',
});
return `${MYOB_AUTH_URL}?${params}`;
}
async function exchangeCode(code: string) {
const response = await axios.post(MYOB_TOKEN_URL, new URLSearchParams({
client_id: process.env.MYOB_CLIENT_ID!,
client_secret: process.env.MYOB_CLIENT_SECRET!,
grant_type: 'authorization_code',
code,
redirect_uri: 'https://yourapp.com/callback',
}));
return response.data;
}
// Company file auth requires additional credentials
function getCompanyFileHeaders(accessToken: string, cfUsername: string, cfPassword: string) {
const cfAuth = Buffer.from(`${cfUsername}:${cfPassword}`).toString('base64');
return {
Authorization: `Bearer ${accessToken}`,
'x-myobapi-cftoken': cfAuth,
'x-myobapi-key': process.env.MYOB_CLIENT_ID!,
'x-myobapi-version': 'v2',
};
}
Discovering Company Files
async function listCompanyFiles(accessToken: string) {
const response = await axios.get(MYOB_API_URL, {
headers: {
Authorization: `Bearer ${accessToken}`,
'x-myobapi-key': process.env.MYOB_CLIENT_ID!,
},
});
return response.data; // Array of company file objects with Uri, Name, etc.
}
Key Techniques
1. Managing Contacts
async function createCustomer(cfUri: string, headers: Record<string, string>) {
const response = await axios.post(
`${cfUri}/Contact/Customer`,
{
CompanyName: 'Acme Pty Ltd',
FirstName: 'John',
LastName: 'Smith',
IsActive: true,
Addresses: [
{
Location: 1,
Street: '123 Collins Street',
City: 'Melbourne',
State: 'VIC',
PostCode: '3000',
Country: 'Australia',
},
],
SellingDetails: {
SaleLayout: 'Service',
InvoiceDelivery: 'Print',
TaxCode: { UID: 'gst-tax-uid' },
FreightTaxCode: { UID: 'gst-free-uid' },
Credit: { Limit: 10000.00 },
Terms: { PaymentIsDue: 'DayOfMonthAfterEOM', BalanceDueDay: 30 },
},
},
{ headers }
);
return response.data;
}
async function listCustomers(cfUri: string, headers: Record<string, string>) {
const response = await axios.get(
`${cfUri}/Contact/Customer?$filter=IsActive eq true&$top=100&$skip=0`,
{ headers }
);
return response.data.Items;
}
2. Creating Invoices
async function createServiceInvoice(cfUri: string, headers: Record<string, string>) {
const response = await axios.post(
`${cfUri}/Sale/Invoice/Service`,
{
Number: 'INV-00042',
Date: '2026-03-25',
Customer: { UID: 'customer-uid' },
IsTaxInclusive: false,
Lines: [
{
Type: 'Transaction',
Description: 'Consulting services — March 2026',
Account: { UID: 'revenue-account-uid' },
TaxCode: { UID: 'gst-uid' },
Total: 3000.00,
},
],
Terms: { PaymentIsDue: 'DayOfMonthAfterEOM', BalanceDueDay: 30 },
Comment: 'Thank you for your business',
},
{ headers }
);
return response.data;
}
3. Recording Payments
async function recordCustomerPayment(cfUri: string, headers: Record<string, string>) {
const response = await axios.post(
`${cfUri}/Sale/CustomerPayment`,
{
PayFrom: 'Account',
Account: { UID: 'bank-account-uid' },
Customer: { UID: 'customer-uid' },
Date: '2026-03-25',
AmountReceived: 3300.00, // GST inclusive
Invoices: [
{
UID: 'invoice-uid',
AmountApplied: 3300.00,
},
],
Memo: 'Payment received — INV-00042',
},
{ headers }
);
return response.data;
}
4. General Journal Entries
async function createJournalEntry(cfUri: string, headers: Record<string, string>) {
const response = await axios.post(
`${cfUri}/GeneralLedger/GeneralJournal`,
{
DateOccurred: '2026-03-31',
Memo: 'Month-end accrual — unbilled revenue',
Lines: [
{
Account: { UID: 'accrued-revenue-uid' },
TaxCode: { UID: 'nt-uid' },
Amount: 5000.00,
IsCredit: false, // Debit
Memo: 'Accrued revenue — Project Alpha',
},
{
Account: { UID: 'revenue-uid' },
TaxCode: { UID: 'nt-uid' },
Amount: 5000.00,
IsCredit: true, // Credit
Memo: 'Accrued revenue — Project Alpha',
},
],
},
{ headers }
);
return response.data;
}
5. OData Filtering
// MYOB supports OData query syntax
async function queryInvoices(cfUri: string, headers: Record<string, string>) {
const filter = encodeURIComponent(
"Date ge datetime'2026-01-01' and Date le datetime'2026-03-31' and BalanceDueAmount gt 0"
);
const response = await axios.get(
`${cfUri}/Sale/Invoice/Service?$filter=${filter}&$orderby=Date desc&$top=50`,
{ headers }
);
return response.data.Items;
}
Best Practices
- Always discover company files first — Never hardcode company file URIs. They change between cloud and on-premise.
- Handle the two-layer auth — OAuth token authenticates the developer;
x-myobapi-cftokenauthenticates the company file user. - Use OData
$filter— MYOB supports rich OData filtering. Use it to reduce data transfer. - UIDs are GUIDs — All MYOB entities use GUID identifiers, not sequential IDs.
- Check
RowVersion— MYOB usesRowVersionfor optimistic concurrency, similar to QBO's SyncToken.
Common Pitfalls
- Forgetting
x-myobapi-cftoken— API returns 401 even with a valid OAuth token if company file credentials are missing. - GST handling — Australia uses 10% GST. Always specify
TaxCodeon line items or amounts will be wrong. - On-premise vs cloud URIs — On-premise company files have
localhost:8080URIs. Handle both. RowVersionrequired for updates — PUT requests fail without the currentRowVersion.
Anti-Patterns
- Storing company file passwords in plaintext — Encrypt company file credentials. They're user-provided passwords.
- Ignoring the Items/NextPageLink pattern — MYOB paginates with
NextPageLink. Always follow it for complete data. - Creating journal entries for standard transactions — Use proper Sale/Purchase endpoints instead of raw journals.
- Not validating TaxCode UIDs — Query
/GeneralLedger/TaxCodeto get valid tax codes for the company file.
Install this skill directly: skilldb add accounting-software-skills
Related Skills
FreeAgent API v2
You are a senior developer integrating with the FreeAgent API v2. You build integrations for UK freelancers and small businesses covering contacts, invoices, expenses, bank transactions, timeslips, an
FreshBooks API v3
You are a senior developer integrating with the FreshBooks API v3. You build integrations for client management, invoicing, expense tracking, time entries, and payments using OAuth 2.0 and FreshBooks'
KashFlow API
You are a senior developer integrating with the KashFlow API. You build integrations for UK small businesses covering customers, invoices, receipts, payments, bank accounts, and VAT returns using Kash
Odoo Accounting XML-RPC / JSON-RPC API
You are a senior developer integrating with Odoo Accounting via its XML-RPC and JSON-RPC APIs. You build integrations for partners, invoices, payments, journal entries, reconciliation, and chart of ac
QuickBooks Online REST API v3
You are a senior developer integrating with the Intuit QuickBooks Online REST API v3. You build robust accounting integrations that create invoices, sync payments, manage customers/vendors, pull finan
Sage Business Cloud Accounting API
You are a senior developer integrating with the Sage Business Cloud Accounting API. You build integrations for contacts, invoices, payments, ledger accounts, and banking using Sage's RESTful API with