> ## Documentation Index
> Fetch the complete documentation index at: https://docs.saasybill.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Objects

> Every object the API returns, field by field

Every object has an `id` and an `object` field naming its type. Formats are described in [Requests and responses](/api-reference/requests-and-responses#data-formats).

<Info>
  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.
</Info>

***

## Organisation

The organisation the API key belongs to. [Retrieve it](/api-reference/organisation/retrieve-the-organisation).

```json theme={null}
{
  "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,
  "livemode": 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](/settings/account) 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. |
| `livemode` | boolean | `false` when the key belongs to a [sandbox](/api-reference/testing), `true` for a live organisation. Every webhook event carries the same value. |

***

## Customer

A customer, synced from a Xero contact. [Endpoints](/api-reference/customers/list-customers).

```json theme={null}
{
  "id": "3b9f1c1e-6a52-4c0e-9d7e-1f6f2f0b7a11",
  "object": "customer",
  "code": "ACME-001",
  "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 or null | The contact's name in Xero. Xero requires one, so it is `null` only for a customer imported without it. |
| `first_name` | string or null | The contact person's first name, in Xero. |
| `last_name` | string or null | The contact person's last name, in Xero. |
| `email` | string or null | The customer's email address. |
| `status` | string | <Badge color="green">active</Badge> or <Badge color="red">inactive</Badge>. |
| `xero_contact_id` | string or null | The id of the contact in Xero. |
| `created` | timestamp | When the customer was added to Saasybill. |

<Note>
  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.
</Note>

***

## Plan

A pricing plan. [Endpoints](/api-reference/plans/list-plans). For how each type prices, see [Plans explained](/core/plans).

```json theme={null}
{
  "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": [],
  "meters": [],
  "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`, `stairstep` or `no_base_fee`. |
| `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`. `0.0000` on a `no_base_fee` plan. |
| `minimum_units` | integer | The fewest units a subscription can have. This is about the recurring fee's units, not a [meter](#plan-meter)'s minimum. |
| `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. |
| `meters` | array | The [meters](#plan-meter) the plan bills for beside its recurring fee, each priced on its own. Empty for a plan that bills no usage. |
| `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. |
| `no_base_fee` | No recurring fee. The plan bills only its `meters`, in arrears. It has no units and its `price` is `0.0000`. |

### 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. |

### Plan meter

A meter a plan bills for, and how. A plan can bill any number of meters. Usage is billed in arrears, when the subscription's period ends. See [Usage-based billing](/api-reference/guides/usage-based-billing).

```json theme={null}
{
  "meter": "c4d8e2f6-7a19-4b30-95e1-3f6a8b0d2c55",
  "meter_code": "api_calls",
  "name": "API Calls",
  "unit_labels": { "singular": "call", "plural": "calls" },
  "pricing_model": "per_unit",
  "price": "0.0200",
  "included_units": 10000,
  "minimum_units": 0,
  "tiers": []
}
```

| Field | Type | Description |
| - | - | - |
| `meter` | string | The Saasybill meter id. |
| `meter_code` | string | The meter's ID as shown in Saasybill, such as `api_calls`. It is what [`POST /v1/usage_events`](/api-reference/usage/report-usage) takes. |
| `name` | string | The meter's name. |
| `unit_labels` | object | What one unit of this meter is called: `singular` and `plural`. Either can be `null`. |
| `pricing_model` | string | `per_unit`, `tiered`, `volume` or `stairstep`. These price as the [plan types](#plan-types) of the same name do. |
| `price` | string or null | The rate per unit. Only for `per_unit`. `null` when the meter prices from `tiers`. |
| `included_units` | integer or null | Units included before charging starts. Only for `per_unit`. `null` for the others, where a free first band does the same job. |
| `minimum_units` | integer | The least a period bills for this meter. A period bills the larger of what was reported and this, before the pricing. `0` means none. A subscription can raise it for itself. |
| `tiers` | array | The meter's price bands, as for a plan's [tiers](#tier). Empty for `per_unit`. Rates can have up to four decimal places. |

***

## Charge

A one-off fee that can be added to a new subscription. It bills once and doesn't recur. [Endpoints](/api-reference/charges/list-charges).

```json theme={null}
{
  "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](/api-reference/subscriptions/list-subscriptions). For the lifecycle, see [Subscriptions explained](/core/subscriptions).

```json theme={null}
{
  "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",
  "usage_value": "0.0000",
  "usage_value_annual": "0.0000",
  "minimum_usage_value": "0.0000",
  "meters": [],
  "cpi_enabled": false,
  "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 plans with no units: flat fee and `no_base_fee`. |
| `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 period is certain to bill, after discount: the plan at its current units, the add-ons, and the minimum units of each meter the plan bills. Usage above the meter minimums is not included. See `usage_value`. |
| `usage_value` | string | The average, over the last three closed usage periods, of what each billed for usage above the meter minimums, after discount. An estimate at the plan's current meter prices. It is never part of `renewal_value`. `0.0000` until a usage period has closed, and for a plan that bills no meter. |
| `usage_value_annual` | string | `usage_value` times the number of periods in a year. |
| `minimum_usage_value` | string | The part of `renewal_value` that is the meter minimums, after discount. `0.0000` for a plan that bills no meter. |
| `meters` | array | The meters the plan bills, with the minimum each is billed at. See below. |
| `cpi_enabled` | boolean | `true` when the price rises with CPI at each renewal. On a plan that bills meters, the meter rates rise too. See [CPI price increases](/api-reference/guides/create-a-subscription#cpi-price-increases). |
| `created` | timestamp | When the subscription was created. |

### Subscription meter

One entry in a subscription's `meters`, for each meter its plan bills.

| Field | Type | Description |
| - | - | - |
| `meter` | string | The Saasybill meter id. |
| `meter_code` | string | The meter's ID as shown in Saasybill. |
| `name` | string | The meter's name. |
| `minimum_units` | integer | The minimum in force: this subscription's own where it raised one, never below the plan's. |
| `plan_minimum_units` | integer | The plan's minimum for the meter. |

### Subscription status

| Status | Meaning |
| - | - |
| <Badge color="blue">pending</Badge> | Created with a future start date. The first invoice has been created. |
| <Badge color="green">active</Badge> | Live and billing. Renews automatically. |
| <Badge>complete</Badge> | Reached its scheduled end. |
| <Badge color="red">ended</Badge> | Stopped by request. Can be [restored](/api-reference/guides/end-and-restore) before its renewal date. |

<Note>
  A subscription set to end at period end stays `active` with `cancel_at_period_end: true` until its end date.
</Note>

***

## Invoice

An invoice raised in Xero. [Endpoints](/api-reference/invoices/list-invoices). Invoices are read-only in the API.

```json theme={null}
{
  "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",
      "revenue_type": "new_subscription",
      "meter": null,
      "usage_quantity": null,
      "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. |
| `not_in_external` | Not in Xero. Check `xero.sync_status`. |

### Xero sync

| Field | Description |
| - | - |
| `xero.sync_status` | <Badge color="green">synced</Badge> the invoice is in Xero. <Badge color="yellow">pending</Badge> it hasn't reached Xero yet. <Badge color="red">failed</Badge> 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`, `charge` or `usage`. A `usage` line bills metered usage: one line per meter per billing period. |
| `revenue_type` | string or null | The revenue bucket the line falls in: `new_subscription`, `expansion`, `renewal` or `usage`. Metered usage is `usage`, never `renewal`. `null` where it wasn't recorded. |
| `meter` | string or null | The Saasybill meter id a `usage` line bills. `null` on every other line. |
| `usage_quantity` | string or null | The quantity a `usage` line was priced for, after the meter's minimum. `units` is this rounded up. `null` on every other line. |
| `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. On a `usage` line, `usage_quantity` rounded up. |
| `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. |

<Info>
  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.
</Info>

***

## Usage event batch

What [`POST /v1/usage_events`](/api-reference/usage/report-usage) returns: how each event in the request fared. See [Usage-based billing](/api-reference/guides/usage-based-billing).

```json theme={null}
{
  "object": "usage_event_batch",
  "created": 1,
  "duplicates": 1,
  "rejected": 1,
  "results": [
    { "event_id": "evt_20261012_0001", "status": "created" },
    { "event_id": "evt_20261012_0002", "status": "duplicate" },
    {
      "event_id": "evt_20261012_0004",
      "status": "rejected",
      "error": {
        "code": "meter_not_on_plan",
        "message": "This subscription's plan does not bill for this meter."
      }
    }
  ]
}
```

| Field | Type | Description |
| - | - | - |
| `created` | integer | Events stored by this request. |
| `duplicates` | integer | Events already stored with the same details, counted once. |
| `rejected` | integer | Events not stored. Resend them once fixed. |
| `results` | array | One entry per event, in the order they were sent. |

### Usage event result

| Field | Type | Description |
| - | - | - |
| `event_id` | string | The `event_id` you sent. |
| `status` | string | <Badge color="green">created</Badge>, <Badge>duplicate</Badge> or <Badge color="red">rejected</Badge>. |
| `error` | object | Present only when `status` is `rejected`. `code` is stable, so branch on it and never on `message`. See [rejection codes](/api-reference/guides/usage-based-billing#rejection-codes). |

***

## Credit note

A credit note raised in Xero, such as when a volume plan's units cross into a cheaper tier or a reduction in units is credited. [Endpoints](/api-reference/credit-notes/list-credit-notes). Credit notes are read-only in the API.

```json theme={null}
{
  "id": "c2d7e1a4-8b36-4d19-a5f0-7e3b9c1d2f66",
  "object": "credit_note",
  "customer": "3b9f1c1e-6a52-4c0e-9d7e-1f6f2f0b7a11",
  "subscription": "9d4e2b7a-13c5-4f8e-b6a0-2e1d7c9f5b33",
  "number": "CN-0007",
  "reference": null,
  "status": "approved",
  "currency": "AUD",
  "credit_note_date": "2026-09-29T14:00:00.000Z",
  "subtotal": "60.0000",
  "total": "66.0000",
  "remaining_credit": "0.0000",
  "allocation_status": "applied",
  "sent": false,
  "xero": {
    "sync_status": "synced",
    "credit_note_id": "a1b2c3d4-e5f6-4789-8abc-def012345678",
    "sync_error": null
  },
  "lines": [
    {
      "id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e99",
      "name": "Team",
      "description": "Team – reduction from 12 to 10 seats",
      "amount": "60.0000",
      "effective_date": "2026-09-29T14:00:00.000Z"
    }
  ],
  "allocations": [
    {
      "id": "3d4e5f6a-7b8c-4d9e-8f10-2b3c4d5e6faa",
      "invoice": "5f8a3c9d-7e21-4b04-9c6d-0a2b4e8f1d55",
      "amount": "66.0000",
      "date": "2026-10-29T14:00:00.000Z",
      "status": "active",
      "xero_sync_status": "synced"
    }
  ],
  "created": "2026-09-29T14:00:05.000Z"
}
```

| Field | Type | Description |
| - | - | - |
| `id` | string | The Saasybill credit note id. |
| `customer` | string | The customer's id. |
| `subscription` | string or null | The subscription it relates to. |
| `number` | string or null | Xero's credit note number, once the credit note is in Xero. |
| `reference` | string or null | The credit note reference. |
| `status` | string | The credit note's status. It uses the same values as the [invoice status](#invoice-status). |
| `currency` | string | The credit note's currency. |
| `credit_note_date` | timestamp or null | The credit note date. |
| `subtotal` | string | The total excluding tax. |
| `total` | string | The total including tax, as Xero returns it. |
| `remaining_credit` | string | What is left to apply to invoices. |
| `allocation_status` | string or null | How much of the credit has been applied. See below. |
| `sent` | boolean | Whether the credit note has been sent to the customer. |
| `xero` | object | Whether the credit note is in Xero. It has the same shape as the invoice's [Xero sync](#xero-sync), with `credit_note_id` in place of `invoice_id`. |
| `lines` | array | The credit note's line items. |
| `allocations` | array | Where the credit has been applied. |
| `created` | timestamp | When the credit note was created in Saasybill. |

### Allocation status

| Status | Meaning |
| - | - |
| `applied` | All of the credit has been applied to invoices. |
| `partial` | Some of the credit has been applied. |
| `unapplied` | None of the credit has been applied. |
| `error` | Applying the credit hit an error. Check each allocation's `xero_sync_status`. |

### Credit note line

| Field | Type | Description |
| - | - | - |
| `id` | string | The line's id. |
| `name` | string or null | The item's name. |
| `description` | string or null | The line's description. |
| `amount` | string | The amount credited, excluding tax. |
| `effective_date` | timestamp or null | When the line takes effect. |

### Allocation

| Field | Type | Description |
| - | - | - |
| `id` | string | The allocation's id. |
| `invoice` | string | The id of the invoice the credit was applied to. |
| `amount` | string | The amount applied. |
| `date` | timestamp | When it was applied. |
| `status` | string | `active`, or `reverted` if the allocation was undone. |
| `xero_sync_status` | string | `synced`, `pending` or `failed`. |

<Info>
  A reverted allocation no longer counts towards `remaining_credit`.
</Info>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.