Creating an Invoice | Moloni ON API
Moloni ONGuidesAPI ReferenceExplorer
Guides

Creating an Invoice

This guide walks you through creating an invoice using the invoiceCreate mutation. Before calling it, you'll need a few pieces of information: a customer, a product and a document set.

Prerequisites

To create an invoice you need:

  1. A customer ID: the customer you're billing
  2. A product ID: the item(s) being invoiced
  3. A document set ID: the numbering series for the invoice

If you don't already have these IDs, you can fetch them with the queries shown below.

Fetching a document set

A document set is a numbering series for documents. Each company has one or more document sets, and each set can be associated with multiple document types (e.g. a single set may handle both invoices and receipts). Use documentSetsForDocument to get the sets that are configured for invoices in your company:

query {
  documentSetsForDocument(companyId: 1, documentTypeId: 1) {
    errors { field msg }
    data {
      documentSetId
      name
      isDefault
    }
  }
}

Document types are system-defined and fixed; use the documentTypes query to look up the ID for invoices.

Pick the documentSetId from the appropriate series.

Fetching a customer

query {
  customers(companyId: 1, options: {
    search: { field: ALL, value: "Acme" }
    pagination: { page: 1, qty: 5 }
  }) {
    data {
      customerId
      name
      vat
    }
  }
}

Fetching a product

query {
  products(companyId: 1, options: {
    search: { field: ALL, value: "Chair" }
    pagination: { page: 1, qty: 5 }
  }) {
    data {
      productId
      name
      reference
      price
    }
  }
}

Required fields

The InvoiceInsert input has these required fields:

FieldTypeDescription
documentSetIdInt!The document set (numbering series) to use
customerIdInt!The customer being billed
dateDateTime!Invoice date
expirationDateDate!Payment due date
products[DocumentProductInput!]!Line items (at least one)

Each line item in the products array requires at minimum:

FieldTypeDescription
productIdInt!The product ID
qtyFloat!Quantity
orderingInt!Position of the line (starting from 1)

See DocumentProductInput for all available fields.

Creating a simple invoice

This example creates a finalized invoice for 2 units of a product:

mutation {
  invoiceCreate(
    companyId: 1
    data: {
      documentSetId: 4
      customerId: 42
      date: "2025-03-20T10:00:00.000Z"
      expirationDate: "2025-04-20"
      status: 1
      products: [
        {
          productId: 88
          qty: 2
          ordering: 1
        }
      ]
    }
  ) {
    errors { field msg }
    data {
      documentId
      number
      date
      expirationDate
      totalValue
      grossValue
      taxesValue
      status
    }
  }
}

Response:

{
  "data": {
    "invoiceCreate": {
      "errors": [],
      "data": {
        "documentId": 1234,
        "number": 56,
        "date": "2025-03-20T10:00:00.000Z",
        "expirationDate": "2025-04-20",
        "totalValue": 99.98,
        "grossValue": 81.28,
        "taxesValue": 18.70,
        "status": 1
      }
    }
  }
}

An empty errors array means the invoice was created successfully. The response includes the generated documentId and sequential number.

Draft vs finalized

The status field controls whether the invoice is a draft or finalized:

StatusMeaning
0Draft: can be edited or deleted
1Finalized: locked, assigned a sequential number, reported to tax authorities (if applicable)

To create a draft, set status: 0 (or omit it):

mutation {
  invoiceCreate(
    companyId: 1
    data: {
      documentSetId: 4
      customerId: 42
      date: "2025-03-20T10:00:00.000Z"
      expirationDate: "2025-04-20"
      status: 0
      products: [
        {
          productId: 88
          qty: 2
          ordering: 1
        }
      ]
    }
  ) {
    errors { field msg }
    data {
      documentId
      number
      status
    }
  }
}

Handling errors

Always check the errors array before using data. If validation fails, the API returns one or more errors indicating which field caused the problem:

{
  "data": {
    "invoiceCreate": {
      "errors": [
        {
          "field": "customerId",
          "msg": "The customer provided does not exist for this company"
        }
      ],
      "data": null
    }
  }
}

Common validation errors include:

  • Invalid or missing documentSetId
  • Customer not found for the given company
  • Product not found
  • Missing required fields (date, expirationDate)
  • Invalid date formats

See the Error Handling guide for the full error model and best practices.

Optional fields

Beyond the required fields, InvoiceInsert supports a variety of optional fields:

FieldTypeDescription
notesStringFree-text notes on the invoice
yourReferenceStringCustomer's reference (e.g. PO number)
ourReferenceStringInternal reference number
globalDiscountFloatDiscount percentage applied to the whole invoice (0–100)
salespersonIdIntAssign a salesperson
alternateAddressIdIntUse an alternate delivery address for the customer
currencyExchangeIdIntForeign currency exchange rate

See the full list in the InvoiceInsert reference page.

Overriding line item details

Each product line can override catalog defaults:

products: [
  {
    productId: 88
    qty: 5
    ordering: 1
    price: 39.99
    discount: 10
  }
]
FieldDescription
priceOverride the catalog price
discountLine-level discount percentage (0–100)
summaryOverride the product description
warehouseIdDeduct stock from a specific warehouse
exemptionReasonTax exemption reason for this line

See DocumentProductInput for all options.

Next steps