# Wave Accounting

> Read and write a Wave business's books: customers, products and services, the chart of accounts, sales taxes, and invoices from draft through approval, payment and deletion.

App · Accounting & Finance · 20 actions. Web page: https://docs.lodol.com/docs/integrations/wave

## Actions

### Approve invoice

Approve a draft invoice, which makes it final and records it in the books. An invoice has to be approved before a payment can be recorded against it. This cannot be undone.

**Inputs**

- Invoice ID (`invoice_id`, text, required): The invoice's Wave ID. 'List invoices' returns these in 'invoice_ids', and 'Create invoice' reports the one it made as 'invoice_id'.

**Outputs**

- `approved` (true/false): Always true
- `invoice` (object)
- `invoice_id` (text): The invoice's Wave ID
- `status` (text): The status after approval

**Example output**

```json
{
  "approved": true,
  "invoice": {
    "amountDue": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "amountPaid": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    },
    "currency": {
      "code": "USD",
      "exponent": 2,
      "name": "US dollar",
      "symbol": "$"
    },
    "customer": {
      "email": "billing@acme.example.com",
      "id": "Q3VzdG9tZXI6NTY3OA==",
      "name": "Acme Supplies"
    },
    "dueDate": "2026-10-01",
    "exchangeRate": "1",
    "id": "SW52b2ljZTo3Nzc3",
    "invoiceDate": "2026-09-01",
    "invoiceNumber": "17",
    "items": [
      {
        "account": {
          "id": "QWNjb3VudDoxMDAx",
          "name": "Sales"
        },
        "description": "Billable consulting time",
        "id": "SW52b2ljZUl0ZW06MQ==",
        "product": {
          "id": "UHJvZHVjdDo0MzIx",
          "name": "Consulting hour"
        },
        "quantity": "1",
        "subtotal": {
          "currency": {
            "code": "USD",
            "exponent": 2,
            "name": "US dollar",
            "symbol": "$"
          },
          "minorUnitValue": "12000",
          "value": "120.00"
        },
        "taxes": [],
        "total": {
          "currency": {
            "code": "USD",
            "exponent": 2,
            "name": "US dollar",
            "symbol": "$"
          },
          "minorUnitValue": "12000",
          "value": "120.00"
        },
        "unitPrice": "120.00"
      }
    ],
    "status": "SAVED",
    "subtotal": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "taxTotal": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    },
    "title": "Invoice",
    "total": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "viewUrl": "https://invoice.waveapps.com/example"
  },
  "invoice_id": "SW52b2ljZTo3Nzc3",
  "status": "SAVED"
}
```

### Archive product

Archive a product or service so it stops being offered on new invoices. Wave has no product delete: a product that has ever been invoiced is part of the books, so archiving is the only removal there is.

**Inputs**

- Product ID (`product_id`, text, required): The product or service's Wave ID. 'List products' returns these in 'product_ids'.

**Outputs**

- `archived` (true/false): Always true
- `product` (object)
- `product_id` (text): The product's Wave ID

**Example output**

```json
{
  "archived": true,
  "product": {
    "defaultSalesTaxes": [],
    "description": "Billable consulting time",
    "id": "UHJvZHVjdDo0MzIx",
    "incomeAccount": {
      "id": "QWNjb3VudDoxMDAx",
      "name": "Sales",
      "subtype": {
        "value": "INCOME"
      }
    },
    "isArchived": true,
    "isBought": false,
    "isSold": true,
    "name": "Consulting hour",
    "unitPrice": "120.00"
  },
  "product_id": "UHJvZHVjdDo0MzIx"
}
```

### Create customer

Add a customer to a business. Only the name is required; everything else - contact details, billing address, currency - can be filled in later with 'Update customer'.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Name (`name`, text, required): The customer's name, or their business name. This is what appears on an invoice.
- Contact first name (`first_name`, text): First name of the person to contact at the customer.
- Contact last name (`last_name`, text): Last name of the person to contact at the customer.
- Email (`email`, text): Where invoices are sent. Wave does not require it, and does not enforce that it is unique.
- Phone (`phone`, text): The customer's telephone number.
- Mobile (`mobile`, text): The contact's mobile number.
- Website (`website`, text): The customer's website address.
- Currency (`currency`, text): The currency to use. Leave empty to use the business's own currency, which is what almost every workflow wants.
- Account number (`display_id`, text): Your own reference for this customer. Wave shows it as the customer's account number.
- Internal notes (`internal_notes`, text): Notes kept on the customer record. Never shown to the customer.
- Address line 1 (`address_line1`, text): Street address, PO box, or company name.
- Address line 2 (`address_line2`, text): Apartment, suite, unit, or building.
- City (`city`, text): City, district, suburb, town, or village.
- Country (`country_code`, text): The customer's country. Pick one first to load its states/provinces below, if it has any.
- State / province (`province_code`, text): The customer's state, province, or region. Wave only recognises the values it lists for the country picked above - most countries have none, in which case this stays empty. Pick a country first.
- Postal code (`postal_code`, text): ZIP or postal code.

**Outputs**

- `created` (true/false): Always true
- `customer` (object)
- `customer_id` (text): The new customer's Wave ID

**Example output**

```json
{
  "created": true,
  "customer": {
    "currency": {
      "code": "USD",
      "exponent": 2,
      "name": "US dollar",
      "symbol": "$"
    },
    "email": "billing@acme.example.com",
    "id": "Q3VzdG9tZXI6NTY3OA==",
    "isArchived": false,
    "name": "Acme Supplies",
    "outstandingAmount": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "overdueAmount": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    }
  },
  "customer_id": "Q3VzdG9tZXI6NTY3OA=="
}
```

### Create invoice

Create an invoice for a customer. A draft can still be edited in Wave and is not in the books yet; approving it makes it final. Every line item needs a product - use 'List products' or 'Create product' to get one.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Customer ID (`customer_id`, text, required): The customer's Wave ID. 'List customers' returns these in 'customer_ids', and every create/update step reports the one it touched as 'customer_id'.
- Line items (`items`, list, required): The lines on the invoice, as a list of objects. Each needs "product_id"; "quantity", "unit_price", "description" and "sales_tax_ids" are optional and fall back to the product's own. For example: [{"product_id": "UHJvZHVjdDo0MzIx", "quantity": 2}].
- Create as (`status`, text): Whether the invoice starts as an editable draft or is approved straight away. Approval cannot be undone - an approved invoice is deleted rather than returned to draft. One of: `DRAFT` (Draft - editable, and not yet in the books), `SAVED` (Approved - final, and recorded in the books). Default: `DRAFT`.
- Invoice date (`invoice_date`, date): When the invoice is issued. Defaults to today.
- Due date (`due_date`, date): When payment is due. Leave empty to apply the business's own payment terms to the invoice date.
- Invoice number (`invoice_number`, text): Leave empty to let Wave take the next number after the highest one it has.
- PO number (`po_number`, text): The customer's purchase or sales order number.
- Title (`title`, text): The heading at the top of the document. Leave empty for the business's default.
- Subheading (`subhead`, text): The line under the title. Leave empty for none.
- Memo (`memo`, text): Notes shown to the customer on the invoice.
- Footer (`footer`, text): Text along the bottom of the invoice.
- Currency (`currency`, text): The currency to use. Leave empty to use the business's own currency, which is what almost every workflow wants.

**Outputs**

- `created` (true/false): Always true
- `invoice` (object)
- `invoice_id` (text): The new invoice's Wave ID
- `status` (text): The status it was created in

**Example output**

```json
{
  "created": true,
  "invoice": {
    "amountDue": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "amountPaid": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    },
    "currency": {
      "code": "USD",
      "exponent": 2,
      "name": "US dollar",
      "symbol": "$"
    },
    "customer": {
      "email": "billing@acme.example.com",
      "id": "Q3VzdG9tZXI6NTY3OA==",
      "name": "Acme Supplies"
    },
    "dueDate": "2026-10-01",
    "exchangeRate": "1",
    "id": "SW52b2ljZTo3Nzc3",
    "invoiceDate": "2026-09-01",
    "invoiceNumber": "17",
    "items": [
      {
        "account": {
          "id": "QWNjb3VudDoxMDAx",
          "name": "Sales"
        },
        "description": "Billable consulting time",
        "id": "SW52b2ljZUl0ZW06MQ==",
        "product": {
          "id": "UHJvZHVjdDo0MzIx",
          "name": "Consulting hour"
        },
        "quantity": "1",
        "subtotal": {
          "currency": {
            "code": "USD",
            "exponent": 2,
            "name": "US dollar",
            "symbol": "$"
          },
          "minorUnitValue": "12000",
          "value": "120.00"
        },
        "taxes": [],
        "total": {
          "currency": {
            "code": "USD",
            "exponent": 2,
            "name": "US dollar",
            "symbol": "$"
          },
          "minorUnitValue": "12000",
          "value": "120.00"
        },
        "unitPrice": "120.00"
      }
    ],
    "status": "DRAFT",
    "subtotal": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "taxTotal": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    },
    "title": "Invoice",
    "total": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "viewUrl": "https://invoice.waveapps.com/example"
  },
  "invoice_id": "SW52b2ljZTo3Nzc3",
  "status": "DRAFT"
}
```

### Create product

Add a product or service to a business. Attach an income account to make it sellable - Wave will not put a product with no income account on an invoice.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Name (`name`, text, required): What the product or service is called.
- Unit price (`unit_price`, number, required): Price for one unit, in the ordinary currency amount - 12.50, not 1250.
- Description (`description`, text): What appears under the name on an invoice line. Leave empty for none.
- Income account (`income_account_id`, text): Which income account the sales of this product post to. Attaching one is what makes a product sellable - Wave will not put a product with no income account on an invoice. Wave accepts only accounts whose subtype is INCOME, DISCOUNTS, OTHER_INCOME; each option's subtype is shown in square brackets.
- Expense account (`expense_account_id`, text): Which expense account purchases of this product post to, which is what lets it go on a bill. Wave accepts only accounts whose subtype is EXPENSE, COST_OF_GOODS_SOLD, PAYMENT_PROCESSING_FEES, PAYROLL_EXPENSES; each option's subtype is shown in square brackets.
- Default sales taxes (`sales_tax_ids`, list): Sales taxes applied to this product by default whenever it goes on an invoice. Leave empty for none.

**Outputs**

- `created` (true/false): Always true
- `product` (object)
- `product_id` (text): The new product's Wave ID

**Example output**

```json
{
  "created": true,
  "product": {
    "defaultSalesTaxes": [],
    "description": "Billable consulting time",
    "id": "UHJvZHVjdDo0MzIx",
    "incomeAccount": {
      "id": "QWNjb3VudDoxMDAx",
      "name": "Sales",
      "subtype": {
        "value": "INCOME"
      }
    },
    "isArchived": false,
    "isBought": false,
    "isSold": true,
    "name": "Consulting hour",
    "unitPrice": "120.00"
  },
  "product_id": "UHJvZHVjdDo0MzIx"
}
```

### Delete customer

Delete a customer. Wave refuses while any invoice or payment still points at them, so delete those first - a customer who has traded is part of the books.

**Inputs**

- Customer ID (`customer_id`, text, required): The customer's Wave ID. 'List customers' returns these in 'customer_ids', and every create/update step reports the one it touched as 'customer_id'.

**Outputs**

- `customer_id` (text): The customer that was deleted
- `deleted` (true/false): Always true

**Example output**

```json
{
  "customer_id": "Q3VzdG9tZXI6NTY3OA==",
  "deleted": true
}
```

### Delete invoice

Delete an invoice. Wave refuses while payments are still recorded against it, so remove those first - 'Get invoice' lists them in 'payment_ids'.

**Inputs**

- Invoice ID (`invoice_id`, text, required): The invoice's Wave ID. 'List invoices' returns these in 'invoice_ids', and 'Create invoice' reports the one it made as 'invoice_id'.

**Outputs**

- `deleted` (true/false): Always true
- `invoice_id` (text): The invoice that was deleted

**Example output**

```json
{
  "deleted": true,
  "invoice_id": "SW52b2ljZTo3Nzc3"
}
```

### Delete invoice payment

Remove a recorded payment from an invoice, putting the amount back on what is owed. 'Get invoice' lists an invoice's payment IDs in 'payment_ids'.

**Inputs**

- Payment ID (`payment_id`, text, required): The payment's Wave ID. 'Get invoice' returns these in 'payment_ids', and 'Record invoice payment' reports the one it made as 'payment_id'.

**Outputs**

- `deleted` (true/false): Always true
- `payment_id` (text): The payment that was deleted

**Example output**

```json
{
  "deleted": true,
  "payment_id": "SW52b2ljZVBheW1lbnQ6MjI="
}
```

### Get business

Read one business - its currency, address, timezone, and whether Wave's email sending is enabled for it.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.

**Outputs**

- `business` (object)
- `business_id` (text): The business's Wave ID

**Example output**

```json
{
  "business": {
    "currency": {
      "code": "USD",
      "exponent": 2,
      "name": "US dollar",
      "symbol": "$"
    },
    "emailSendEnabled": true,
    "id": "QnVzaW5lc3M6MTIzNA==",
    "isArchived": false,
    "isPersonal": false,
    "name": "Northwind Consulting",
    "organizationalType": "SOLE_PROPRIETORSHIP",
    "timezone": "America/Toronto"
  },
  "business_id": "QnVzaW5lc3M6MTIzNA=="
}
```

### Get customer

Read one customer, including how much they currently owe and how much of that is overdue.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Customer ID (`customer_id`, text, required): The customer's Wave ID. 'List customers' returns these in 'customer_ids', and every create/update step reports the one it touched as 'customer_id'.

**Outputs**

- `customer` (object)
- `customer_id` (text): The customer's Wave ID

**Example output**

```json
{
  "customer": {
    "currency": {
      "code": "USD",
      "exponent": 2,
      "name": "US dollar",
      "symbol": "$"
    },
    "email": "billing@acme.example.com",
    "id": "Q3VzdG9tZXI6NTY3OA==",
    "isArchived": false,
    "name": "Acme Supplies",
    "outstandingAmount": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "overdueAmount": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    }
  },
  "customer_id": "Q3VzdG9tZXI6NTY3OA=="
}
```

### Get invoice

Read one invoice with its line items, taxes, totals and every payment recorded against it. The payment IDs come back in 'payment_ids', which is what 'Delete invoice payment' takes.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Invoice ID (`invoice_id`, text, required): The invoice's Wave ID. 'List invoices' returns these in 'invoice_ids', and 'Create invoice' reports the one it made as 'invoice_id'.

**Outputs**

- `invoice` (object)
- `invoice_id` (text): The invoice's Wave ID
- `payment_ids` (list): IDs of the payments recorded against it
- `status` (text): The invoice's current status

**Example output**

```json
{
  "invoice": {
    "amountDue": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "amountPaid": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    },
    "currency": {
      "code": "USD",
      "exponent": 2,
      "name": "US dollar",
      "symbol": "$"
    },
    "customer": {
      "email": "billing@acme.example.com",
      "id": "Q3VzdG9tZXI6NTY3OA==",
      "name": "Acme Supplies"
    },
    "dueDate": "2026-10-01",
    "exchangeRate": "1",
    "id": "SW52b2ljZTo3Nzc3",
    "invoiceDate": "2026-09-01",
    "invoiceNumber": "17",
    "items": [
      {
        "account": {
          "id": "QWNjb3VudDoxMDAx",
          "name": "Sales"
        },
        "description": "Billable consulting time",
        "id": "SW52b2ljZUl0ZW06MQ==",
        "product": {
          "id": "UHJvZHVjdDo0MzIx",
          "name": "Consulting hour"
        },
        "quantity": "1",
        "subtotal": {
          "currency": {
            "code": "USD",
            "exponent": 2,
            "name": "US dollar",
            "symbol": "$"
          },
          "minorUnitValue": "12000",
          "value": "120.00"
        },
        "taxes": [],
        "total": {
          "currency": {
            "code": "USD",
            "exponent": 2,
            "name": "US dollar",
            "symbol": "$"
          },
          "minorUnitValue": "12000",
          "value": "120.00"
        },
        "unitPrice": "120.00"
      }
    ],
    "payments": [
      {
        "account": {
          "currency": {
            "code": "USD",
            "exponent": 2,
            "name": "US dollar",
            "symbol": "$"
          },
          "id": "QWNjb3VudDo5OTk5",
          "name": "Cash on Hand"
        },
        "amount": "120.00",
        "customer": {
          "id": "Q3VzdG9tZXI6NTY3OA==",
          "name": "Acme Supplies"
        },
        "exchangeRate": "1",
        "id": "SW52b2ljZVBheW1lbnQ6MjI=",
        "paymentDate": "2026-09-05",
        "paymentMethod": "CASH"
      }
    ],
    "status": "SAVED",
    "subtotal": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "taxTotal": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    },
    "title": "Invoice",
    "total": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "viewUrl": "https://invoice.waveapps.com/example"
  },
  "invoice_id": "SW52b2ljZTo3Nzc3",
  "payment_ids": [
    "SW52b2ljZVBheW1lbnQ6MjI="
  ],
  "status": "SAVED"
}
```

### List accounts

Read a business's chart of accounts, optionally narrowed by type or subtype. This is where the account IDs the other actions need come from - an income account for a product, and a cash-or-bank account to record a payment into.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Account types (`types`, list): Only accounts of these types. Leave empty for all five. One or more of: `ASSET`, `LIABILITY`, `EQUITY`, `INCOME`, `EXPENSE`.
- Account subtypes (`subtypes`, list): Only accounts of these subtypes. 'Cash and bank' is what 'Record invoice payment' needs; 'Income' is what a sellable product needs. Leave empty for all. One or more of: `CASH_AND_BANK` (Cash and bank), `CREDIT_CARD` (Credit card), `INCOME`, `OTHER_INCOME` (Other income), `DISCOUNTS`, `EXPENSE`, `COST_OF_GOODS_SOLD` (Cost of goods sold), `PAYMENT_PROCESSING_FEES` (Payment processing fees), `PAYROLL_EXPENSES` (Payroll expenses), `RECEIVABLE` (Accounts receivable), and 7 more.
- Archived (`archived`, text): Whether to include archived records. Wave keeps archived records for the history they carry, so 'Only active' is what a workflow normally wants. One of: `false` (Only active), `true` (Only archived), `any` (Both). Default: `false`.
- Page (`page`, number): Which page of results to read, counting from 1. Feed 'next_page' from a previous run back in here to read the next one. From 1 to 100000. Default: `1`.
- Results per page (`page_size`, number): How many results one page holds, 1-200. Defaults to 25. From 1 to 200. Default: `25`.

**Outputs**

- `account_ids` (list): Just the IDs, for chaining into a later step
- `accounts` (list): The accounts on this page
- `business_id` (text): The business these came from
- `count` (number): How many are on this page
- `has_more` (true/false): Whether a page follows
- `next_page` (number): The 'page' that reads the next page, or empty at the end
- `page` (number): Which page this is
- `total_count` (number): How many records match in total
- `total_pages` (number): How many pages there are

**Example output**

```json
{
  "account_ids": [
    "QWNjb3VudDo5OTk5"
  ],
  "accounts": [
    {
      "balance": "1450.00",
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "id": "QWNjb3VudDo5OTk5",
      "isArchived": false,
      "name": "Cash on Hand",
      "normalBalanceType": "DEBIT",
      "subtype": {
        "name": "Cash and Bank",
        "value": "CASH_AND_BANK"
      },
      "type": {
        "name": "Asset",
        "normalBalanceType": "DEBIT",
        "value": "ASSET"
      }
    }
  ],
  "business_id": "QnVzaW5lc3M6MTIzNA==",
  "count": 1,
  "has_more": false,
  "next_page": null,
  "page": 1,
  "total_count": 1,
  "total_pages": 1
}
```

### List businesses

List every business in the connected Wave account. Returns each one's Wave ID, which is the value every other action's 'Business' field takes.

**Inputs**

- Page (`page`, number): Which page of results to read, counting from 1. Feed 'next_page' from a previous run back in here to read the next one. From 1 to 100000. Default: `1`.
- Results per page (`page_size`, number): How many results one page holds, 1-200. Defaults to 25. From 1 to 200. Default: `25`.
- Archived (`archived`, text): Whether to include archived records. Wave keeps archived records for the history they carry, so 'Only active' is what a workflow normally wants. One of: `false` (Only active), `true` (Only archived), `any` (Both). Default: `false`.

**Outputs**

- `business_id` (text): The business these came from
- `business_ids` (list): Just the IDs, for chaining into a later step
- `businesses` (list): The businesses on this page
- `count` (number): How many are on this page
- `has_more` (true/false): Whether a page follows
- `next_page` (number): The 'page' that reads the next page, or empty at the end
- `page` (number): Which page this is
- `total_count` (number): How many records match in total
- `total_pages` (number): How many pages there are

**Example output**

```json
{
  "business_ids": [
    "QnVzaW5lc3M6MTIzNA=="
  ],
  "businesses": [
    {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "emailSendEnabled": true,
      "id": "QnVzaW5lc3M6MTIzNA==",
      "isArchived": false,
      "isPersonal": false,
      "name": "Northwind Consulting",
      "organizationalType": "SOLE_PROPRIETORSHIP",
      "timezone": "America/Toronto"
    }
  ],
  "count": 1,
  "has_more": false,
  "next_page": null,
  "page": 1,
  "total_count": 1,
  "total_pages": 1
}
```

### List customers

List a business's customers, optionally narrowed to one email address or to a window of when they were last changed. Returns each one's outstanding and overdue amounts alongside their contact details.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Email (`email`, text): Only customers with this exact email address. Leave empty for all of them.
- Sort by (`sort`, text): How to order the results. One of: `NAME_ASC` (Name, A to Z), `NAME_DESC` (Name, Z to A), `CREATED_AT_DESC` (Created, newest first), `CREATED_AT_ASC` (Created, oldest first), `MODIFIED_AT_DESC` (Modified, newest first), `MODIFIED_AT_ASC` (Modified, oldest first). Default: `NAME_ASC`.
- Modified after (`modified_after`, date and time): Only records changed after this moment. Leave empty for all.
- Modified before (`modified_before`, date and time): Only records changed before this moment. Leave empty for all.
- Page (`page`, number): Which page of results to read, counting from 1. Feed 'next_page' from a previous run back in here to read the next one. From 1 to 100000. Default: `1`.
- Results per page (`page_size`, number): How many results one page holds, 1-200. Defaults to 25. From 1 to 200. Default: `25`.

**Outputs**

- `business_id` (text): The business these came from
- `count` (number): How many are on this page
- `customer_ids` (list): Just the IDs, for chaining into a later step
- `customers` (list): The customers on this page
- `has_more` (true/false): Whether a page follows
- `next_page` (number): The 'page' that reads the next page, or empty at the end
- `page` (number): Which page this is
- `total_count` (number): How many records match in total
- `total_pages` (number): How many pages there are

**Example output**

```json
{
  "business_id": "QnVzaW5lc3M6MTIzNA==",
  "count": 1,
  "customer_ids": [
    "Q3VzdG9tZXI6NTY3OA=="
  ],
  "customers": [
    {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "email": "billing@acme.example.com",
      "id": "Q3VzdG9tZXI6NTY3OA==",
      "isArchived": false,
      "name": "Acme Supplies",
      "outstandingAmount": {
        "currency": {
          "code": "USD",
          "exponent": 2,
          "name": "US dollar",
          "symbol": "$"
        },
        "minorUnitValue": "12000",
        "value": "120.00"
      },
      "overdueAmount": {
        "currency": {
          "code": "USD",
          "exponent": 2,
          "name": "US dollar",
          "symbol": "$"
        },
        "minorUnitValue": "0",
        "value": "0.00"
      }
    }
  ],
  "has_more": false,
  "next_page": null,
  "page": 1,
  "total_count": 1,
  "total_pages": 1
}
```

### List invoices

List a business's invoices, narrowed by status, customer, date range or invoice number. Recorded payments are not included - Wave only populates those when a single invoice is asked for, so use 'Get invoice' for those.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Status (`status`, text): Only invoices in this state. Leave empty for every state. One of: `DRAFT`, `SAVED` (Saved (approved, not yet sent)), `SENT`, `VIEWED` (Viewed by the customer), `UNPAID`, `PARTIAL` (Partially paid), `PAID`, `OVERDUE`, `OVERPAID`.
- Customer ID (`customer_id`, text): Only invoices for this customer. Leave empty for all of them. 'List customers' returns these in 'customer_ids'.
- Invoice dated on or after (`invoice_date_start`, date): Earliest invoice date to include.
- Invoice dated on or before (`invoice_date_end`, date): Latest invoice date to include.
- Invoice number contains (`invoice_number`, text): Matches on containment, not equality: '12' also finds 112, 120 and 121. Check the results rather than assuming one.
- Sort by (`sort`, text): How to order the results. One of: `INVOICE_DATE_DESC` (Invoice date, newest first), `INVOICE_DATE_ASC` (Invoice date, oldest first), `DUE_AT_ASC` (Due date, soonest first), `DUE_AT_DESC` (Due date, latest first), `CREATED_AT_DESC` (Created, newest first), `CREATED_AT_ASC` (Created, oldest first), `MODIFIED_AT_DESC` (Modified, newest first), `INVOICE_NUMBER_ASC` (Invoice number, ascending), `INVOICE_NUMBER_DESC` (Invoice number, descending), `AMOUNT_DUE_DESC` (Amount due, largest first), and 7 more. Default: `INVOICE_DATE_DESC`.
- Page (`page`, number): Which page of results to read, counting from 1. Feed 'next_page' from a previous run back in here to read the next one. From 1 to 100000. Default: `1`.
- Results per page (`page_size`, number): How many results one page holds, 1-200. Defaults to 25. From 1 to 200. Default: `25`.

**Outputs**

- `business_id` (text): The business these came from
- `count` (number): How many are on this page
- `has_more` (true/false): Whether a page follows
- `invoice_ids` (list): Just the IDs, for chaining into a later step
- `invoices` (list): The invoices on this page
- `next_page` (number): The 'page' that reads the next page, or empty at the end
- `page` (number): Which page this is
- `total_count` (number): How many records match in total
- `total_pages` (number): How many pages there are

**Example output**

```json
{
  "business_id": "QnVzaW5lc3M6MTIzNA==",
  "count": 1,
  "has_more": false,
  "invoice_ids": [
    "SW52b2ljZTo3Nzc3"
  ],
  "invoices": [
    {
      "amountDue": {
        "currency": {
          "code": "USD",
          "exponent": 2,
          "name": "US dollar",
          "symbol": "$"
        },
        "minorUnitValue": "12000",
        "value": "120.00"
      },
      "amountPaid": {
        "currency": {
          "code": "USD",
          "exponent": 2,
          "name": "US dollar",
          "symbol": "$"
        },
        "minorUnitValue": "0",
        "value": "0.00"
      },
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "customer": {
        "email": "billing@acme.example.com",
        "id": "Q3VzdG9tZXI6NTY3OA==",
        "name": "Acme Supplies"
      },
      "dueDate": "2026-10-01",
      "exchangeRate": "1",
      "id": "SW52b2ljZTo3Nzc3",
      "invoiceDate": "2026-09-01",
      "invoiceNumber": "17",
      "items": [
        {
          "account": {
            "id": "QWNjb3VudDoxMDAx",
            "name": "Sales"
          },
          "description": "Billable consulting time",
          "id": "SW52b2ljZUl0ZW06MQ==",
          "product": {
            "id": "UHJvZHVjdDo0MzIx",
            "name": "Consulting hour"
          },
          "quantity": "1",
          "subtotal": {
            "currency": {
              "code": "USD",
              "exponent": 2,
              "name": "US dollar",
              "symbol": "$"
            },
            "minorUnitValue": "12000",
            "value": "120.00"
          },
          "taxes": [],
          "total": {
            "currency": {
              "code": "USD",
              "exponent": 2,
              "name": "US dollar",
              "symbol": "$"
            },
            "minorUnitValue": "12000",
            "value": "120.00"
          },
          "unitPrice": "120.00"
        }
      ],
      "status": "SAVED",
      "subtotal": {
        "currency": {
          "code": "USD",
          "exponent": 2,
          "name": "US dollar",
          "symbol": "$"
        },
        "minorUnitValue": "12000",
        "value": "120.00"
      },
      "taxTotal": {
        "currency": {
          "code": "USD",
          "exponent": 2,
          "name": "US dollar",
          "symbol": "$"
        },
        "minorUnitValue": "0",
        "value": "0.00"
      },
      "title": "Invoice",
      "total": {
        "currency": {
          "code": "USD",
          "exponent": 2,
          "name": "US dollar",
          "symbol": "$"
        },
        "minorUnitValue": "12000",
        "value": "120.00"
      },
      "viewUrl": "https://invoice.waveapps.com/example"
    }
  ],
  "next_page": null,
  "page": 1,
  "total_count": 1,
  "total_pages": 1
}
```

### List products

List a business's products and services, optionally narrowed to the ones it sells or the ones it buys. Returns each one's unit price and the accounts it posts to.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Sold by the business (`is_sold`, text): Only products the business sells (the ones that can go on an invoice), only the ones it does not, or either. One of: `any` (Either), `true` (Yes), `false` (No). Default: `any`.
- Bought by the business (`is_bought`, text): Only products the business buys (the ones that can go on a bill), only the ones it does not, or either. One of: `any` (Either), `true` (Yes), `false` (No). Default: `any`.
- Sort by (`sort`, text): How to order the results. One of: `NAME_ASC` (Name, A to Z), `NAME_DESC` (Name, Z to A), `CREATED_AT_DESC` (Created, newest first), `CREATED_AT_ASC` (Created, oldest first), `MODIFIED_AT_DESC` (Modified, newest first), `MODIFIED_AT_ASC` (Modified, oldest first). Default: `NAME_ASC`.
- Archived (`archived`, text): Whether to include archived records. Wave keeps archived records for the history they carry, so 'Only active' is what a workflow normally wants. One of: `false` (Only active), `true` (Only archived), `any` (Both). Default: `false`.
- Page (`page`, number): Which page of results to read, counting from 1. Feed 'next_page' from a previous run back in here to read the next one. From 1 to 100000. Default: `1`.
- Results per page (`page_size`, number): How many results one page holds, 1-200. Defaults to 25. From 1 to 200. Default: `25`.

**Outputs**

- `business_id` (text): The business these came from
- `count` (number): How many are on this page
- `has_more` (true/false): Whether a page follows
- `next_page` (number): The 'page' that reads the next page, or empty at the end
- `page` (number): Which page this is
- `product_ids` (list): Just the IDs, for chaining into a later step
- `products` (list): The products on this page
- `total_count` (number): How many records match in total
- `total_pages` (number): How many pages there are

**Example output**

```json
{
  "business_id": "QnVzaW5lc3M6MTIzNA==",
  "count": 1,
  "has_more": false,
  "next_page": null,
  "page": 1,
  "product_ids": [
    "UHJvZHVjdDo0MzIx"
  ],
  "products": [
    {
      "defaultSalesTaxes": [],
      "description": "Billable consulting time",
      "id": "UHJvZHVjdDo0MzIx",
      "incomeAccount": {
        "id": "QWNjb3VudDoxMDAx",
        "name": "Sales",
        "subtype": {
          "value": "INCOME"
        }
      },
      "isArchived": false,
      "isBought": false,
      "isSold": true,
      "name": "Consulting hour",
      "unitPrice": "120.00"
    }
  ],
  "total_count": 1,
  "total_pages": 1
}
```

### List sales taxes

List a business's sales taxes with the rate in force today and the dated history behind it. Rates come back as decimals - 0.13 means 13%.

**Inputs**

- Business (`business_id`, text, required): Which set of books to work in. Pick from the list; the value sent is the business's Wave ID. 'List businesses' returns these in 'business_ids'.
- Archived (`archived`, text): Whether to include archived records. Wave keeps archived records for the history they carry, so 'Only active' is what a workflow normally wants. One of: `false` (Only active), `true` (Only archived), `any` (Both). Default: `false`.
- Modified after (`modified_after`, date and time): Only records changed after this moment. Leave empty for all.
- Modified before (`modified_before`, date and time): Only records changed before this moment. Leave empty for all.
- Page (`page`, number): Which page of results to read, counting from 1. Feed 'next_page' from a previous run back in here to read the next one. From 1 to 100000. Default: `1`.
- Results per page (`page_size`, number): How many results one page holds, 1-200. Defaults to 25. From 1 to 200. Default: `25`.

**Outputs**

- `business_id` (text): The business these came from
- `count` (number): How many are on this page
- `has_more` (true/false): Whether a page follows
- `next_page` (number): The 'page' that reads the next page, or empty at the end
- `page` (number): Which page this is
- `sales_tax_ids` (list): Just the IDs, for chaining into a later step
- `sales_taxes` (list): The sales taxes on this page
- `total_count` (number): How many records match in total
- `total_pages` (number): How many pages there are

**Example output**

```json
{
  "business_id": "QnVzaW5lc3M6MTIzNA==",
  "count": 1,
  "has_more": false,
  "next_page": null,
  "page": 1,
  "sales_tax_ids": [
    "U2FsZXNUYXg6MTE="
  ],
  "sales_taxes": [
    {
      "abbreviation": "HST",
      "id": "U2FsZXNUYXg6MTE=",
      "isArchived": false,
      "isCompound": false,
      "isRecoverable": true,
      "name": "HST",
      "rate": "0.13"
    }
  ],
  "total_count": 1,
  "total_pages": 1
}
```

### Record invoice payment

Record a payment against an approved invoice. The payment lands in the account you choose, which is normally a cash-or-bank one - 'List accounts' filtered to 'Cash and bank' finds it.

**Inputs**

- Invoice ID (`invoice_id`, text, required): The invoice's Wave ID. 'List invoices' returns these in 'invoice_ids', and 'Create invoice' reports the one it made as 'invoice_id'.
- Deposit into (`payment_account_id`, text, required): Which account the money lands in - normally a cash-or-bank account. Each option's subtype is shown in square brackets and the business it belongs to after the dash.
- Amount (`amount`, number, required): How much was paid, in the ordinary currency amount - 120.50, not 12050. Less than the total records a partial payment.
- Payment date (`payment_date`, date, required): The date the payment was actually made.
- Payment method (`payment_method`, text): How the customer paid. One of: `CASH`, `CHEQUE`, `BANK_TRANSFER` (Bank transfer), `CREDIT_CARD` (Credit card), `PAYPAL`, `OTHER`, `UNSPECIFIED`. Default: `OTHER`.
- Memo (`memo`, text): A note kept with the payment.
- Exchange rate (`exchange_rate`, number): Only matters when the invoice and the deposit account are in different currencies. Leave empty for 1. Default: `1`.

**Outputs**

- `invoice_id` (text): The invoice it was recorded against
- `payment` (object)
- `payment_id` (text): The new payment's Wave ID
- `recorded` (true/false): Always true

**Example output**

```json
{
  "invoice_id": "SW52b2ljZTo3Nzc3",
  "payment": {
    "account": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "id": "QWNjb3VudDo5OTk5",
      "name": "Cash on Hand"
    },
    "amount": "120.00",
    "customer": {
      "id": "Q3VzdG9tZXI6NTY3OA==",
      "name": "Acme Supplies"
    },
    "exchangeRate": "1",
    "id": "SW52b2ljZVBheW1lbnQ6MjI=",
    "paymentDate": "2026-09-05",
    "paymentMethod": "CASH"
  },
  "payment_id": "SW52b2ljZVBheW1lbnQ6MjI=",
  "recorded": true
}
```

### Update customer

Change an existing customer. Only the fields you fill in are sent - anything left empty keeps the value it already has, rather than being cleared.

**Inputs**

- Customer ID (`customer_id`, text, required): The customer's Wave ID. 'List customers' returns these in 'customer_ids', and every create/update step reports the one it touched as 'customer_id'.
- Name (`name`, text): The customer's name, or their business name. This is what appears on an invoice. Leave empty to keep the current name.
- Contact first name (`first_name`, text): First name of the person to contact at the customer.
- Contact last name (`last_name`, text): Last name of the person to contact at the customer.
- Email (`email`, text): Where invoices are sent. Wave does not require it, and does not enforce that it is unique.
- Phone (`phone`, text): The customer's telephone number.
- Mobile (`mobile`, text): The contact's mobile number.
- Website (`website`, text): The customer's website address.
- Currency (`currency`, text): The currency to use. Leave empty to use the business's own currency, which is what almost every workflow wants.
- Account number (`display_id`, text): Your own reference for this customer. Wave shows it as the customer's account number.
- Internal notes (`internal_notes`, text): Notes kept on the customer record. Never shown to the customer.
- Address line 1 (`address_line1`, text): Street address, PO box, or company name.
- Address line 2 (`address_line2`, text): Apartment, suite, unit, or building.
- City (`city`, text): City, district, suburb, town, or village.
- Country (`country_code`, text): The customer's country. Pick one first to load its states/provinces below, if it has any.
- State / province (`province_code`, text): The customer's state, province, or region. Wave only recognises the values it lists for the country picked above - most countries have none, in which case this stays empty. Pick a country first.
- Postal code (`postal_code`, text): ZIP or postal code.

**Outputs**

- `customer` (object)
- `customer_id` (text): The customer's Wave ID
- `updated` (true/false): Always true

**Example output**

```json
{
  "customer": {
    "currency": {
      "code": "USD",
      "exponent": 2,
      "name": "US dollar",
      "symbol": "$"
    },
    "email": "billing@acme.example.com",
    "id": "Q3VzdG9tZXI6NTY3OA==",
    "isArchived": false,
    "name": "Acme Supplies",
    "outstandingAmount": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "12000",
      "value": "120.00"
    },
    "overdueAmount": {
      "currency": {
        "code": "USD",
        "exponent": 2,
        "name": "US dollar",
        "symbol": "$"
      },
      "minorUnitValue": "0",
      "value": "0.00"
    }
  },
  "customer_id": "Q3VzdG9tZXI6NTY3OA==",
  "updated": true
}
```

### Update product

Change an existing product or service. Only the fields you fill in are sent - anything left empty keeps the value it has.

**Inputs**

- Product ID (`product_id`, text, required): The product or service's Wave ID. 'List products' returns these in 'product_ids'.
- Name (`name`, text): What the product is called. Leave empty to keep the current name.
- Unit price (`unit_price`, number): Price for one unit, in the ordinary currency amount. Leave empty to keep the current price.
- Description (`description`, text): What appears under the name on an invoice line. Leave empty to keep the current description.
- Income account (`income_account_id`, text): Which income account the sales of this product post to. Attaching one is what makes a product sellable - Wave will not put a product with no income account on an invoice. Wave accepts only accounts whose subtype is INCOME, DISCOUNTS, OTHER_INCOME; each option's subtype is shown in square brackets.
- Expense account (`expense_account_id`, text): Which expense account purchases of this product post to, which is what lets it go on a bill. Wave accepts only accounts whose subtype is EXPENSE, COST_OF_GOODS_SOLD, PAYMENT_PROCESSING_FEES, PAYROLL_EXPENSES; each option's subtype is shown in square brackets.
- Default sales taxes (`sales_tax_ids`, list): Sales taxes applied to this product by default whenever it goes on an invoice. Leave empty for none.

**Outputs**

- `product` (object)
- `product_id` (text): The product's Wave ID
- `updated` (true/false): Always true

**Example output**

```json
{
  "product": {
    "defaultSalesTaxes": [],
    "description": "Billable consulting time",
    "id": "UHJvZHVjdDo0MzIx",
    "incomeAccount": {
      "id": "QWNjb3VudDoxMDAx",
      "name": "Sales",
      "subtype": {
        "value": "INCOME"
      }
    },
    "isArchived": false,
    "isBought": false,
    "isSold": true,
    "name": "Consulting hour",
    "unitPrice": "120.00"
  },
  "product_id": "UHJvZHVjdDo0MzIx",
  "updated": true
}
```
