id and an object field naming its type. Formats are described in Requests and responses.
Money fields are decimal strings with four decimal places. Timestamps are ISO 8601 in UTC. Calendar dates are
YYYY-MM-DD in the subscription’s timezone.Organisation
The organisation the API key belongs to. Retrieve it.{
"id": "7c3e9a1b-5d20-4f68-a4b7-8e6d2c0f9a99",
"object": "organisation",
"name": "Northwind Software",
"timezone": "Australia/Sydney",
"default_currency": "AUD",
"setup_mode": false,
"can_create_xero_contacts": true
}
| Field | Type | Description |
|---|---|---|
id | string | The organisation’s id. |
name | string | The organisation’s name. |
timezone | string | The organisation’s timezone. Dates you send are read in this timezone. |
default_currency | string or null | The default currency code, such as AUD. |
setup_mode | boolean | true while Setup Mode is on. No invoices are raised in Xero. |
can_create_xero_contacts | boolean | Whether an owner or admin has allowed the API to create Xero contacts. |
Customer
A customer, synced from a Xero contact. Endpoints.{
"id": "3b9f1c1e-6a52-4c0e-9d7e-1f6f2f0b7a11",
"object": "customer",
"code": "ACME-001",
"name": "Acme Pty Ltd",
"company_name": "Acme Pty Ltd",
"first_name": null,
"last_name": null,
"email": "accounts@acme.example",
"status": "active",
"xero_contact_id": "d5f2a8c1-6b73-4e09-8a1d-4c7e9b3f0a12",
"created": "2026-08-14T02:31:08.000Z"
}
| Field | Type | Description |
|---|---|---|
id | string | The Saasybill customer id. |
code | string or null | Your own reference for the customer. Unique in the organisation. It is the contact number in Xero. |
name | string | The display name: the company name, or the person’s name. |
company_name | string or null | The company name. |
first_name | string or null | The contact’s first name. |
last_name | string or null | The contact’s last name. |
email | string or null | The customer’s email address. |
status | string | active or inactive. |
xero_contact_id | string or null | The id of the contact in Xero. |
created | timestamp | When the customer was added to Saasybill. |
A customer with no code can’t be found by
customer_code. Give the customer a code before your integration needs to look them up.Plan
A pricing plan. Endpoints. For how each type prices, see Plans explained.{
"id": "b6c1e0a4-2f7d-4a61-8f0c-5d3e9a7b2c44",
"object": "plan",
"code": "TEAM-MONTHLY",
"name": "Team",
"type": "per_unit",
"interval": { "unit": "month", "count": 1 },
"currency": "AUD",
"price": "12.0000",
"minimum_units": 5,
"free_units": 0,
"unit_labels": { "singular": "seat", "plural": "seats" },
"allows_price_override": false,
"status": "active",
"tiers": [],
"created": "2026-06-02T23:10:44.000Z"
}
| Field | Type | Description |
|---|---|---|
id | string | The plan id. |
code | string | The plan’s code. Unique in the organisation. |
name | string | The plan’s name. |
type | string | flat_fee, per_unit, tiered, volume or stairstep. |
interval | object | The billing period: unit is day, week, month or year, and count is how many of them. |
currency | string | The plan’s currency code. |
price | string | The flat fee, or the per-unit price. On tiered, volume and stairstep plans, read the prices in tiers. |
minimum_units | integer | The fewest units a subscription can have. |
free_units | integer | Units included at no charge. |
unit_labels | object | The singular and plural names of a unit, such as seat and seats. Either can be null. |
allows_price_override | boolean | true when a flat fee subscription can set its own flat_fee_price. |
status | string | draft, active, inactive or legacy. Only active and draft plans can be sold. |
tiers | array | The price bands, ordered by from_units. Empty on flat fee and per unit plans. |
created | timestamp | When the plan was created. |
Plan types
| Type | How it prices |
|---|---|
flat_fee | One price per period, whatever the units. Takes no units. |
per_unit | A price multiplied by the units, less any free units. |
tiered | Each band of units is priced at its own rate, and the bands add up. |
volume | The band the total falls in sets one rate for every unit. |
stairstep | The band the total falls in sets one price for the whole quantity. |
Tier
| Field | Type | Description |
|---|---|---|
from_units | integer | The first unit in the band. |
to_units | integer or null | The last unit in the band. null for the top band, which has no limit. |
price | string | The band’s price. |
Charge
A one-off fee that can be added to a new subscription. It bills once and doesn’t recur. Endpoints.{
"id": "e2a7d5c8-91b3-4d16-a0f4-7c8b6e5d3a22",
"object": "charge",
"code": "ONBOARDING",
"name": "Onboarding",
"description": "One-off setup and training",
"currency": "AUD",
"price": "450.0000",
"allows_price_override": false,
"status": "active",
"created": "2026-06-02T23:14:09.000Z"
}
| Field | Type | Description |
|---|---|---|
id | string | The charge id. Charges are sent on a subscription by id. |
code | string | The charge’s code. |
name | string | The charge’s name. |
description | string or null | A description shown on the invoice line. |
currency | string | The charge’s currency. It must match the plan’s. |
price | string | The charge’s price. |
allows_price_override | boolean | true when a subscription can set its own price for this charge. |
status | string | draft, active, inactive or legacy. |
created | timestamp | When the charge was created. |
Subscription
A customer’s subscription to a plan. Endpoints. For the lifecycle, see Subscriptions explained.{
"id": "9d4e2b7a-13c5-4f8e-b6a0-2e1d7c9f5b33",
"object": "subscription",
"customer": "3b9f1c1e-6a52-4c0e-9d7e-1f6f2f0b7a11",
"customer_code": "ACME-001",
"plan": "b6c1e0a4-2f7d-4a61-8f0c-5d3e9a7b2c44",
"status": "active",
"currency": "AUD",
"interval": { "unit": "month", "count": 1 },
"timezone": "Australia/Sydney",
"start_date": "2026-09-30",
"renewal_date": "2026-10-30",
"end_date": null,
"units": 10,
"minimum_units": 5,
"discount_percent": "10.00",
"cancel_at_period_end": false,
"end_after_cycles": null,
"label": "Acme – Team plan",
"invoice_reference": "PO-4471",
"renewal_value": "108.0000",
"created": "2026-09-30T04:12:00.000Z"
}
| Field | Type | Description |
|---|---|---|
id | string | The subscription id. |
customer | string | The customer’s id. |
customer_code | string or null | The customer’s code. |
plan | string | The plan’s id. |
status | string | pending, active, complete or ended. See below. |
currency | string | The subscription’s currency. |
interval | object | The billing period, copied from the plan. |
timezone | string | The subscription’s timezone. Its dates are in this timezone. |
start_date | date | When the subscription starts. |
renewal_date | date or null | When it next renews. |
end_date | date or null | When it ends, if it is set to end. |
units | integer | The current number of units. 0 on flat fee plans. |
minimum_units | integer | The minimum set on this subscription. 0 means the plan’s minimum applies. A subscription can raise its plan’s minimum, never lower it. |
discount_percent | string | The discount, from "0.00" to "100.00". |
cancel_at_period_end | boolean | true when the subscription is set to end at its renewal date. |
end_after_cycles | integer or null | The number of billing cycles before it ends. null for an ongoing subscription. |
label | string or null | A label for you. |
invoice_reference | string or null | The reference printed on each invoice, such as a purchase order number. |
renewal_value | string | What the next renewal will bill, after discount. |
created | timestamp | When the subscription was created. |
Subscription status
| Status | Meaning |
|---|---|
| pending | Created with a future start date. The first invoice has been created. |
| active | Live and billing. Renews automatically. |
| complete | Reached its scheduled end. |
| ended | Stopped by request. Can be restored before its renewal date. |
A subscription set to end at period end stays
active with cancel_at_period_end: true until its end date.Invoice
An invoice raised in Xero. Endpoints. Invoices are read-only in the API.{
"id": "5f8a3c9d-7e21-4b04-9c6d-0a2b4e8f1d55",
"object": "invoice",
"customer": "3b9f1c1e-6a52-4c0e-9d7e-1f6f2f0b7a11",
"subscription": "9d4e2b7a-13c5-4f8e-b6a0-2e1d7c9f5b33",
"number": "INV-0042",
"reference": "PO-4471",
"status": "awaiting_approval",
"currency": "AUD",
"invoice_date": "2026-09-29T14:00:00.000Z",
"due_date": "2026-10-29T13:00:00.000Z",
"subtotal": "558.0000",
"total": "613.8000",
"credit_note_amount": "0.0000",
"amount_paid": null,
"sent": false,
"xero": {
"sync_status": "synced",
"invoice_id": "f0e9d8c7-b6a5-4f43-9210-fedcba987654",
"sync_error": null
},
"lines": [
{
"id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c77",
"type": "subscription",
"name": "Team",
"description": "Team – 10 seats",
"units": 10,
"amount": "120.0000",
"discount_amount": "12.0000",
"charge_amount": "108.0000",
"effective_date": "2026-09-29T14:00:00.000Z"
}
],
"created": "2026-09-30T04:12:01.000Z"
}
| Field | Type | Description |
|---|---|---|
id | string | The Saasybill invoice id. |
customer | string | The customer’s id. |
subscription | string or null | The subscription that raised it. |
number | string or null | Xero’s invoice number, once the invoice is in Xero. |
reference | string or null | The invoice reference. |
status | string | The invoice’s status. See below. |
currency | string | The invoice’s currency. |
invoice_date | timestamp | The invoice date. |
due_date | timestamp or null | The due date. |
subtotal | string | The total excluding tax. |
total | string | The total including tax, as Xero returns it. |
credit_note_amount | string | Credit applied to the invoice. |
amount_paid | string or null | The amount paid so far. |
sent | boolean | Whether the invoice has been sent to the customer. |
xero | object | Whether the invoice is in Xero. See below. |
lines | array | The invoice’s line items. |
created | timestamp | When the invoice was created in Saasybill. |
Invoice status
| Status | Meaning |
|---|---|
draft | Created, not yet approved in Xero. |
awaiting_approval | Ready to be approved in Xero. |
approved | Approved and awaiting payment. |
paid | Fully paid. |
voided | Voided in Xero. |
deleted | Deleted in Xero. |
scheduled | Held for a later date. |
not_in_external | Not in Xero. Check xero.sync_status. |
Xero sync
| Field | Description |
|---|---|
xero.sync_status | synced the invoice is in Xero. pending it hasn’t reached Xero yet. failed Xero refused it. |
xero.invoice_id | The invoice’s id in Xero. null until it is there. |
xero.sync_error | Why Xero refused it. null unless sync_status is failed. |
Invoice line
| Field | Type | Description |
|---|---|---|
id | string | The line’s id. |
type | string or null | subscription, addon or charge. |
name | string or null | The item’s name. |
description | string or null | The line’s description. |
units | integer or null | The units billed. null where the line has none, such as a charge. |
amount | string | The amount before discount. |
discount_amount | string | The discount taken off. |
charge_amount | string | What is billed: amount less discount_amount. |
effective_date | timestamp or null | When the line takes effect. |
On a subscription created through the API, a charge takes the subscription’s discount only when you set
apply_discount to true on that charge.