Invoicing
Less than to read
Invoicing, both sales and purchase, is the hot spot of Accounting. Chances are you will need to read them or create them.
Sales vs. Purchase Invoices
You can create invoices for sales and purchases using the API. Both share many attributes, you just have to use
different types of objects. For instance, in a purchase invoice, the contact you’ll be using will have the
contact_type_id
VENDOR
, while for a sales invoice, you’ll be using a CUSTOMER
. The other difference are the ledger
accounts being used on the invoice items. For purchase invoices, the ledger accounts will have to be from the EXPENSE
ledger account group, for sales invoices from the INCOME
ledger account group.
Creating an Invoice
An invoice references many other objects: A contact, a ledger account per invoice item, one or more tax rates and maybe a product or a service. Some of those objects have already been created or are present by default, some of them you have to create before you can build the invoice.
Create Or Find A Contact
First, you’ll need a contact the invoice gets assigned to. To create one, send a POST request to the contacts
endpoint:
POST /contacts
Content-Type: application/json
{
"contact": {
"contact_type_ids": ["CUSTOMER"],
"name": "Great Example Inc",
"main_address": {
"address_type_id": "ACCOUNTS",
"address_line_1": "Some Where",
"city": "LA",
"region": "US-CA",
"postal_code": "90210",
"country_group_id": "US"
}
}
}
This creates a very simple customer contact account. To create a vendor account, use VENDOR
in the contact_type_ids
array. Please note that you cannot assign more than one contact_type_id
.
The beginning of the server response will look like this:
{
"id": "14d93840783b11e8990a122c8428e4b2",
"displayed_as": "Great Example Inc",
"$path": "/contacts/14d93840783b11e8990a122c8428e4b2",
"created_at": "2018-06-25T05:46:18Z",
"updated_at": "2018-06-25T05:46:18Z",
"links": [
{
"href": "https://accounting.na.sageone.com/contacts/customers/3887951",
"rel": "alternate",
"type": "text/html"
}
],
"contact_types": [
{
"id": "CUSTOMER",
"displayed_as": "Customer",
"$path": "/contact_types/CUSTOMER"
}
],
"name": "Great Example Inc"
}
You will need the id
from the response. It makes sense to store that ID in your system so that you do not have to look
it up via the API each time you need it.
To lookup an existing customer, you can use the following query:
GET /contacts?contact_type_id=CUSTOMER&search=Great%20Example%20Inc
This will search for Great Example Inc
with the user’s customers. To search for a vendor, use VENDOR
as
contact_type_id
. You can also search for an email address by adding &email=person%40greatexample.inc
. The result
will contain all matching contacts in the items
array. Choose the appropriate one (or let the user choose) and
memorize the ID for using it in the invoice.
Find A Ledger Account For Each Invoice Item
For each invoice item, you (or the user) have to select an appropriate ledger account. For sales, there is a
default_sales_ledger_account
attribute on the contact, which you might want to use. Alternatively, you can use an API
request to get a list of suitable accounts for sales invoices:
GET /ledger_accounts?visible_in=sales&items_per_page=200
This will return a list like this:
{
"$total": 7,
"$page": 1,
"$next": null,
"$back": null,
"$itemsPerPage": 200,
"$items": [
{
"id": "4195173e75db11e8990a122c8428e4b2",
"displayed_as": "Professional Fees (4000)",
"$path": "/ledger_accounts/4195173e75db11e8990a122c8428e4b2"
},
{
"id": "4195196a75db11e8990a122c8428e4b2",
"displayed_as": "Sales of Materials (4050)",
"$path": "/ledger_accounts/4195196a75db11e8990a122c8428e4b2"
},
{
"id": "41951b8675db11e8990a122c8428e4b2",
"displayed_as": "Interest Income (4100)",
"$path": "/ledger_accounts/41951b8675db11e8990a122c8428e4b2"
},
{
"id": "41951dae75db11e8990a122c8428e4b2",
"displayed_as": "Finance Charge Income (4200)",
"$path": "/ledger_accounts/41951dae75db11e8990a122c8428e4b2"
},
{
"id": "41951fc875db11e8990a122c8428e4b2",
"displayed_as": "Other Income (4300)",
"$path": "/ledger_accounts/41951fc875db11e8990a122c8428e4b2"
},
{
"id": "419521fd75db11e8990a122c8428e4b2",
"displayed_as": "Uncategorized Income (4400)",
"$path": "/ledger_accounts/419521fd75db11e8990a122c8428e4b2"
},
{
"id": "4195240d75db11e8990a122c8428e4b2",
"displayed_as": "Sales/Fees Discounts (4900)",
"$path": "/ledger_accounts/4195240d75db11e8990a122c8428e4b2"
}
]
}
Please cache this kind of data. The ledger accounts for a user may change, but they’re not expected to change often. It doesn’t make much sense to query for ledger accounts every minute.
For getting a list of suitable ledger accounts on purchase invoices, use the following query:
GET /ledger_accounts?visible_in=expenses&items_per_page=200
This will return all expense ledger accounts. On vendor contacts, there is also a default_purchase_ledger_account
attribute.
Find A Tax Rate For Each Item
Now that you have contact and ledger account IDs, you will need to find a tax rate for each invoice item. For sales
invoices, you might be able to use the default_sales_tax_rate
attribute from the contact, but this is not set on each
contact.
The following API request will list available tax rates for the user:
GET /tax_rates?attributes=name,percentage&items_per_page=200
The attributes=name,percentage
will make sure that the name and the percentage are included in the collection
response. By default, only id
, displayed_as
and $path
are present in collection responses. items_per_page
allows
you to get up to 200 items per request. By default, the API returns 20 items per request.
For some countries, there are region specific tax rates. You can filter for them using the address_region_id
query
param:
GET /tax_rates?attributes=name,percentage&address_region_id=CA-QC
For a list of available tax regions, use
GET /address_regions?items_per_page=200
As with the ledger accounts, it is advisable to cache the results. In any case, you need to memorize the tax rate id and percentage for each invoice item.
Optional: Find Or Create A Product Or Service For Each Item
In Accounting, users can create products and services. Those objects have a name, a price and reference ledger accounts and tax rates. In sales invoices, products and services should be used when applicable so that the user can track the sales on his products and services. In purchase invoices, products can be referenced. This allows users to see their products’ profits and it also helps keeping track of their inventory.
There are API requests to list existing products
GET /products?active=true
and services
GET /services?active=true
When creating a product, you will need a ledger account ID that is used for sales and one that is used when purchasing
the product. See above for obtaining those. You can also add prices to the product, for this, you will need product
sales price type ids. To get those, use GET /product_sales_price_types
. For convenience, you can set a tax rate
that is used when selling the product.
Then, you can create the product:
POST /products
Content-Type: application/json
{
"product": {
"description": "An example product",
"item_code": "PRODUCT-01",
"sales_ledger_account_id": "4195196a75db11e8990a122c8428e4b2",
"sales_tax_rate_id": "584793ca75db11e8990a122c8428e4b2",
"purchase_ledger_account_id": "4194d2b875db11e8990a122c8428e4b2",
"sales_prices": [
{
"product_sales_price_type_id": "41a77be375db11e8990a122c8428e4b2",
"price": "9.99",
"price_includes_tax": true
}
]
}
}
When creating a service, you need a ledger account and a description. Optionally, you can add sales prices and a tax
rate. For the prices, you need to get service rate type ids from GET /service_rate_type_ids
. You can add different
prices for each service rate type ID on a service.
POST /services
Content-Type: application/json
{
"service": {
"description": "An example service",
"item_code": "SERVICE-01",
"sales_ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"sales_tax_rate_id": "584793ca75db11e8990a122c8428e4b2",
"sales_prices": [
{
"service_rate_type_id": "41ab074075db11e8990a122c8428e4b2",
"rate": "19.99",
"price_includes_tax": false
}
]
}
}
Build The Invoice
Now, you have all the objects that are required for creating the invoice via the API and we can start building the JSON body that will be used.
There are three required attributes: The contact_id
, the invoice’s date
and the invoice_lines
.
For the contact_id
, see above to learn how to get one. Make sure to use a contact with a contact_type_id
of
CUSTOMER
for sales invoices and VENDOR
for purchase invoices.
The date
is the date on the invoice. This can be the current date, but this is not required — you can also create an
invoice for the previous year (but not before the financial_settings.accounts_start_date
of the business).
The invoice_lines
attribute is an array of invoice line objects, which we will describe now:
Building An Invoice Line
An entry in the invoice_lines
array has the following required attributes:
description
: A string that describes the itemledger_account_id
: An ID that identifies the ledger account for this itemquantity
unit_price
tax_rate_id
: The tax rate used for this invoice line-
tax_amount
: The tax amount (not for tax rates ‘zero’, ‘no tax’, and ‘exempt’; not allowed for Spanish businesses) Your application has to calculate the tax amount (if there is no other source, ie. on purchase invoices) and send in a value. If optional and omitted, the tax amount will be set to zero. To calculate the tax amount, you will need thepercentage
value of the tax rate for the line item. The formula then istax_amount = net_amount * tax_percentage / 100
Ensure you round the result to two decimal places. This is the only precision supported by Accounting.
Attention: Floating point representations in JSON can be tricky. Please send decimal values as strings!
The following attributes are optional (there are even more, but let’s concentrate on the most important ones):
product_id
: An ID that identifies the product that has been sold or purchasedservice_id
: The ID that identifies the service that has been sold (only on sales invoices)net_amount
: The net amounttotal_amount
: The total amount for the invoice linediscount_amount
: The discount amount for the invoice line
Let’s have a look at some examples:
A minimal invoice item:
{
"description": "A Minimal Invoice Item",
"ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"quantity": "1",
"unit_price": "0.99",
"tax_rate_id": "584793ca75db11e8990a122c8428e4b2"
}
An invoice item that contains pre-calculated values for tax amount and discount:
{
"description": "An Invoice Item With Pre-Calculated Tax",
"ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"quantity": "1",
"unit_price": "110.00",
"tax_rate_id": "584793ca75db11e8990a122c8428e4b2",
"discount_amount": "10.00",
"tax_amount": "9.95"
}
An invoice item that references a service:
{
"description": "An Invoice Item For A Service",
"ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"quantity": "1",
"unit_price": "19.99",
"tax_rate_id": "584793ca75db11e8990a122c8428e4b2",
"service_id": "086b655f785411e8990a122c8428e4b2"
}
And finally one that references a product:
{
"description": "An Invoice Item For A Product",
"ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"quantity": "1",
"unit_price": "9.99",
"tax_rate_id": "584793ca75db11e8990a122c8428e4b2",
"product_id": "a083714f784c11e8990a122c8428e4b2"
}
You have to build such on object for each item on the invoice. Once you have that array, you can add optional attributes to your invoice.
Adding Optional Attributes To The Invoice
Optional attributes can be used to add more data to the invoice and to deviate from defaults that would be used without them. Let’s concentrate on the most important ones:
invoice_number
: Especially important for purchase invoices, where the vendor will have included a number on his invoice. Can be used for sales invoices as well, but be careful, as Accounting tries to auto-number all the invoices it created. The next invoice number created will be the last one’s plus 1 by default. If you send in your own value which differs from that, this might result in a gap between invoice numbers, which should be avoided, as the numbering must be consistent. You can check the next invoice number to be used by fetchingGET /invoice_settings
in thenext_invoice_number
attribute.due_date
: A specific due date for this invoice. If not set on sales invoices, defaults todate
pluscontact.credit_days
, or, if this is not present, the business’ default number of credit days.reference
: A random string that you can use to reference any other, even external entity, for instance a quote.supplier_reference
: This attribute, which is only available on purchase invoices, is a string that takes any reference the supplier provided, so that the user can find the invoice easily.notes
: A string that is kept internally, only visible to the Accounting user(s).terms_and_conditions
: A string that may be printed on the invoice.currency_id
: This is used for the multi-currency feature, which will be covered in another guide in the future. Stay tuned!
Adding Shipping Costs (Only On Sales)
There are some attributes you can use on the sales invoice object to add shipping costs:
shipping_net_amount
: The net amount paid for shippingshipping_tax_rate_id
: The tax rate IDshipping_tax_amount
: The tax amount. Will be calculated when omitted.
For purchase invoices, please add a separate invoice line for shipping costs.
Creating Draft Or Pro Forma Invoices
You can create draft and pro forma sales invoices using the status_id
attribute. Those invoices are handled like
normal invoices, but they do not affect the accounts, ie., no transaction gets created when those invoices are saved. To
create a draft invoice, set status
to DRAFT
, for pro forma invoices, use PRO_FORMA
.
Send The POST Request
Now that we’ve built the request body, we can send it to the API:
POST /sales_invoices
Content-Type: application/json
{
"sales_invoice": {
"contact_id": "14d93840783b11e8990a122c8428e4b2",
"date": "2018-06-24",
"invoice_lines": [
{
"description": "A Minimal Invoice Item",
"ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"quantity": "1",
"unit_price": "0.99",
"tax_rate_id": "584793ca75db11e8990a122c8428e4b2"
},
{
"description": "An Invoice Item With Pre-Calculated Tax",
"ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"quantity": "1",
"unit_price": "110.00",
"tax_rate_id": "584793ca75db11e8990a122c8428e4b2",
"discount_amount": "10.00",
"tax_amount": "9.95"
},
{
"description": "An Invoice Item For A Service",
"ledger_account_id": "4195173e75db11e8990a122c8428e4b2",
"quantity": "1",
"unit_price": "19.99",
"tax_rate_id": "584793ca75db11e8990a122c8428e4b2",
"service_id": "086b655f785411e8990a122c8428e4b2"
}
]
}
}
The server will respond with a 201 Created
status code on success. The response body will contain a full
representation of the created invoice object.
Side Effects Of An Invoice Creation
When creating an invoice that is not a draft or pro forma, a transaction will be created that updates the balances of
all the ledger accounts referenced in the invoice lines. The transaction will be against a holding account, as each
newly created invoice is unpaid. If you want to record a payment against an invoice, you will have to create an
additional contact_payment
object.
Depending on the business’ accounting type and tax scheme, tax entries will be created as soon as the invoice is created or as soon as there’s a payment on it.
Understanding Invoice Representations
For understanding the API representation of an invoice, let’s have a look at a draft invoice that has been created in the Web UI. Here you can see how the elements in the UI map to attributes in the JSON representation.
When using GET /sales_invoices/{id}
, a very long response is returned. Don’t be afraid, we’ll explain the
important parts bit by bit. Let’s begin with the first part:
"id": "e5aff2cd745011e8863412a7e3287944",
"displayed_as": "SI-DRAFT",
"$path": "/sales_invoices/e5aff2cd745011e8863412a7e3287944",
"transaction": null,
"transaction_type": {
"id": "SALES_INVOICE",
"displayed_as": "Sales Invoice",
"$path": "/transaction_types/SALES_INVOICE"
},
"created_at": "2018-06-20T06:12:23Z",
"updated_at": "2018-06-20T06:12:23Z",
"links": [
{
"href": "https://accounting.na.sageone.com/invoicing/sales_invoices/e5aff2cd745011e8863412a7e3287944",
"rel": "alternate",
"type": "text/html"
}
],
"tax_calculation_method": null,
"invoice_number": "SI-DRAFT",
id
, displayed_as
and $path
are attributes that are common to most endpoints in the Accounting API. displayed_as
will always contain a representation of the object that is suitable for displaying to an end user.
transaction
is null
here, because the invoice has been created as draft.
transaction_type
references the type of the transaction that would have been created if the invoice wasn’t draft.
created_at
and updated_at
are very common throughout the API as well.
links
is an array of relevant links for this object. In this case, there is a link to the invoice’s representation in
the Accounting web UI.
tax_calculation_method
is not applicable for this invoice, so it is set to null
. Possible values are invoice
,
cash
and retailer
.
The invoice_number
contains the string DRAFT
, this would be replaced by the next free invoice number when converting
to a real invoice.
The Contact
Let’s continue with the next few lines:
"contact_name": "A Really nice customer Inc",
"contact_reference": null,
"contact": {
"id": "3a1d5799745011e8863412a7e3287944",
"displayed_as": "A Really nice customer Inc",
"$path": "/contacts/3a1d5799745011e8863412a7e3287944"
},
The contact to which the invoice is assigned to is not only referenced by its id
, also, the contact’s name is copied
over to the invoice. This is important as a contact’s name can change, but it must not change on any issued invoice.
When displaying the contact of an existing invoice, always prefer to display the attributes directly on the invoice for
that reason.
Invoice Dates And Reference
"date": "2018-06-20",
"due_date": "2018-07-20",
"reference": "AB-123",
The date
is not the creation date of the invoice, but the date when the invoice is issued at. It is printed on the
invoice and is the date that is used on the transaction. The due_date
informs the customer about the date when they
should have paid the invoice and reference
is a string the user can assign to the invoice to help them identify it.
Address
"main_address_free_form": "Some Where\nOver The Rainbow CA 90210",
"main_address": {
"id": "e5ba36cb745011e8863412a7e3287944",
"displayed_as": "Some Where\nOver The Rainbow CA 90210",
"$path": "/contacts/e5ba36cb745011e8863412a7e3287944",
"address_type": {
"id": "SALES",
"displayed_as": "Sales",
"$path": "/address_types/SALES"
},
"address_line_1": "Some Where",
"address_line_2": "",
"city": "Over The Rainbow",
"region": "CA",
"postal_code": "90210",
"country": {
"id": "US",
"displayed_as": "United States (US)",
"$path": "/countries/US"
},
"country_group": {
"id": "US",
"displayed_as": "US",
"$path": "/country_groups/US"
}
},
Like the contact_name
, its main address gets copied over to the invoice in the main_address_free_form
attribute. The
complete representation of the main_address
is also included in the invoice. The same is true for the delivery
address, so we’ll skip that section and go to:
Notes And Terms
"notes": "Comments are internal, only you see them",
"terms_and_conditions": "Terms and Conditions will be printed on the invoice PDF.",
notes
and terms_and_conditions
are attributes directly visible to the user, with the latter being printed on the
invoice, while the former is internal.
Shipping Amounts
"shipping_net_amount": "0.0",
"shipping_tax_rate": {
"id": "95670c34738211e8863412a7e3287944",
"displayed_as": "No Tax",
"$path": "/tax_rates/95670c34738211e8863412a7e3287944"
},
"shipping_tax_amount": "0.0",
"shipping_tax_breakdown": [
],
"shipping_total_amount": "0.0",
These attributes describe the shipping net, tax and total amounts and the tax rate used to calculate the tax amount. They are only available on sales invoices.
Totals
"net_amount": "294.0",
"tax_amount": "27.2",
"total_amount": "321.2",
"total_quantity": "10.0",
"total_discount_amount": "6.0",
You’ll get the totals for the complete invoice in net_amount
, tax_amount
and total_amount
.
Payments And Allocations
"payments_allocations_total_amount": "0.0",
"payments_allocations_total_discount": "0.0",
"total_paid": "0.0",
"outstanding_amount": "0.0",
These attributes show you how much money has been paid or allocated for this invoice. As it is a draft invoice, there cannot be any payments, so all of them are zero here.
Multi-Currency
"currency": {
"id": "USD",
"displayed_as": "US Dollar (USD)",
"$path": "/currencies/USD"
},
"exchange_rate": "1.0",
"inverse_exchange_rate": "1.0",
"base_currency_shipping_net_amount": "0.0",
"base_currency_shipping_tax_amount": "0.0",
"base_currency_shipping_tax_breakdown": [
],
"base_currency_shipping_total_amount": "0.0",
"base_currency_total_discount_amount": "6.0",
"base_currency_net_amount": "294.0",
"base_currency_tax_amount": "27.2",
"base_currency_total_amount": "321.2",
"base_currency_outstanding_amount": "0.0",
Above attributes are relevant when using the multi-currency feature, which will be covered in a future guide.
Status
"status": {
"id": "DRAFT",
"displayed_as": "Draft",
"$path": "/artefact_statuses/DRAFT"
},
"sent": false,
"void_reason": null,
The status
attribute describes the state of the invoice. See below in the section “Change The State Of An Invoice” for
details on this.
The sent
attribute is just a marker if the invoice has been sent to the customer, so it is only relevant for sales
documents.
The void_reason
is only present when the status
id
is VOID
. It is a user provided string that describes the
reason why the invoice has been voided.
Invoice Lines
And then, there are the invoice_lines
. Let’s have a look at one of them, step after step:
{
"id": "e5c61f6b745011e8863412a7e3287944",
"displayed_as": "The first invoice item",
"description": "The first invoice item",
Each invoice line has its own ID, this allows updating any line without having to care for the lines order.
"product": null,
"service": null,
If the line has been associated with a product or service, this would be referenced here.
"ledger_account": {
"id": "95c4353c738211e8863412a7e3287944",
"displayed_as": "Professional Fees (4000)",
"$path": "/ledger_accounts/95c4353c738211e8863412a7e3287944"
},
The ledger account which is used for the invoice line. When the invoice is taken into account, there is a transaction with a ledger entry against this account.
"trade_of_asset": false,
"quantity": "1.0",
"unit_price": "10.0",
"net_amount": "9.0",
Of those attributes, the Boolean trade_of_asset
needs some explanation. When this is set to true
, the item is meant
for resale. This is important for flat tax rates in some countries.
"tax_rate": {
"id": "adac0c97738211e8863412a7e3287944",
"displayed_as": "Beverly Hills, CA 9.25%",
"$path": "/tax_rates/adac0c97738211e8863412a7e3287944"
},
"tax_amount": "0.83",
"tax_breakdown": [
{
"tax_rate": {
"id": "adac0c97738211e8863412a7e3287944",
"displayed_as": "Beverly Hills, CA 9.25%",
"$path": "/tax_rates/adac0c97738211e8863412a7e3287944"
},
"percentage": "9.25",
"amount": "0.83"
}
],
"total_amount": "9.83",
"base_currency_unit_price": "10.0",
"unit_price_includes_tax": false,
These attributes provide information about the tax amount and how it has been calculated.
"base_currency_net_amount": "9.0",
"base_currency_tax_amount": "0.83",
"base_currency_tax_breakdown": [
{
"tax_rate": {
"id": "adac0c97738211e8863412a7e3287944",
"displayed_as": "Beverly Hills, CA 9.25%",
"$path": "/tax_rates/adac0c97738211e8863412a7e3287944"
},
"percentage": "9.25",
"amount": "0.83"
}
],
"base_currency_total_amount": "9.83",
This is relevant for the multi-currency feature, which will be covered in a future guide.
"eu_goods_services_type": null,
"discount_amount": "1.0",
"base_currency_discount_amount": "1.0",
"discount_percentage": "10.0",
"eu_sales_description": null
},
As you can see, the first invoice line has been created using a discount percentage of 10%, which is an amount of 1.0.
Tax Analysis
After the invoice_lines
, there are a couple of other attributes:
"tax_analysis": [
{
"tax_rate": {
"id": "adac0c97738211e8863412a7e3287944",
"displayed_as": "Beverly Hills, CA 9.25%",
"$path": "/tax_rates/adac0c97738211e8863412a7e3287944"
},
"net_amount": "294.0",
"tax_amount": "27.2",
"total_amount": "321.2",
"goods_amount": "0.0",
"service_amount": "0.0"
}
],
Other Attributes
There are some more attributes, but those were the most important ones.
Changing The State Of An Invoice
Each invoice can have one of at the moment eight statuses. You can get a full list of them by requesting
GET /artefact_statutes
. Here is a list of the present statuses and their meanings:
Status | Meaning |
---|---|
UNPAID |
The invoice is taken into account, but no payments or allocations have been recorded. |
PART_PAID |
The invoice is taken into account, there are payments or allocations, but there is an outstanding amount on the invoice. |
PAID |
The invoice is taken into account and has been fully paid. |
VOID |
The invoice has been cancelled. |
DRAFT |
The invoice is not taken into account. There cannot be any payments or allocations on it. |
DISPUTED |
The invoice has been marked as disputed. This status is only available on purchases. |
DECLINED |
The artefact has been marked as declined. It is only available on sales quotes. |
PRO_FORMA |
The invoice is not taken into account. There cannot be any payments or allocations on it. |
Directly after creation, invoices can only be UNPAID
, DRAFT
or PRO_FORMA
. The following sections describe how the
status can be changed via the API.
From Draft Or Pro Forma To Unpaid
To change the status from DRAFT
or PRO_FORMA
to unpaid, you have to send a POST
request to the invoice’s path plus
/release
. You do not have to send a POST body. For example, for a sales invoice:
POST /sales_invoices/{id}/release
This will return a full representation of the invoice and change its status ID to UNPAID
.
From Unpaid To Part Paid Or Paid
You cannot change the status of an invoice to PART_PAID
or PAID
by updating the invoice itself. Instead, you’ll have
to create either a contact_payment
or a contact_allocation
object. For the former, please see the
Payments Concept guide for details. A contact allocation can
be used to allocate one or more invoices against one or more credit notes/payments on account:
POST /contact_allocations
Content-Type: application/json
{
"contact_allocation": {
"contact_id": "14d93840783b11e8990a122c8428e4b2",
"allocated_artefacts": [
{
"artefact_id": "c2bab86f786f11e8990a122c8428e4b2",
"amount": "100.0"
},
{
"artefact_id": "108973dc787311e8990a122c8428e4b2",
"amount": "-100.0"
}
],
"transaction_type_id": "CUSTOMER_ALLOCATION"
}
}
The contact_id
includes the vendor’s or customer’s ID, the transaction_type_id
needs to be CUSTOMER_ALLOCATION
for
allocating sales artefacts and VENDOR_ALLOCATION
for purchase artefacts. The allocated_artefacts
attribute is an
array with objects referencing credit notes, unallocated payments and invoices. The sum of the amounts must to be zero -
you always remove credit and add debit here. In other words: For a customer allocation, the amount on the credit note is
negative and the amount on the invoice is positive. For a vendor allocation, it is the other way round: The credit note
gets a positive value, the invoice a negative.
You can create payments or allocations until the invoice is fully paid.
From Unpaid To Void (Sales Invoices)
Cancelling a sales invoice is done by a DELETE
request against the invoice’s $path
:
DELETE /sales_invoices/{id}
Content-Type: application/json
{
"void_reason": "Invoice was created by accident"
}
Please note that you have to submit a body with the DELETE
request. The body must include a single param:
void_reason
. This is a random string that describes why the invoice has been voided.
Cancelling an invoice also voids the transaction that has been created for the invoice, ie., the balances of the ledger accounts are updated with that operation.
From Part Paid Or Paid To Void
You cannot directly void any invoice that has payments or allocations. Instead, you have to delete all the payments and
allocations first. The invoice’s status will change to UNPAID
, which will allow you to void the invoice as described
above.
This may seem a bit complicated, but if you could void an invoice without removing the payments, the accounts would get incorrect balances and this must not happen in accounting.
From Any State To Disputed
This is currently not possible using the API. Sorry for that.
Deleting Invoices (Purchases)
Purchase invoices without payments or allocations can be deleted without passing a void_reason
:
DELETE /purchase_invoices/{id}
This will return a 204 No Content
response. The transaction that was created together with the invoice will be voided
automatically.
Other Document Types
Invoicing is not just about invoices. For instance, when an Accounting user gets or issues a refund, a credit note can be created to represent that. The following document types are available in Accounting. The endpoints for them use the same data representations as the invoice endpoints, so using them is very similar.
Credit Notes
Credit notes can be created for sales and purchases. They represent refunds received or issued. To get all existing
purchase credit notes, you can use GET /purchase_credit_notes
. The sales credit notes are available at
GET /sales_credit_notes
.
Credit notes affect the balances of the involved ledger accounts, ie., when a credit note is created, a transaction is created as well.
Quotes And Estimates
Quotes and estimate documents can be created for sales. They do not affect the balances of the ledger accounts, after all, they are about business opportunities, no liabilities exist. Those are the endpoints for these two document types:
GET /sales_quotes
GET /sales_estimates
The only differences between them are the name and their invoice settings.
Corrective Invoices
This document type is only available for Spanish Accounting users!
In Spain, there are corrective invoices, ie., invoices, that correct previous ones. In the Accounting API, you can use
the GET /sales_corrective_invoices
and GET /purchase_corrective_invoices
endpoints for these documents. When
creating a corrective invoice, you are required to pass two additional attributes:
original_invoice_number
: The number of the invoice that is being correctedoriginal_invoice_date
: The date of the invoice that is being corrected
If the original invoice is also present in Accounting, you should pass its id
as original_invoice_id
attribute.
POST /purchase_corrective_invoices
Content-Type: application/json
{
"purchase_corrective_invoice": {
"contact_id": "15605f5bd05b413d9bc714f9abe7dc5a",
"date": "2018-07-01",
"due_date": "2018-07-31",
"reference": "OP 1337",
"vendor_reference": "INV 123",
"original_artefact_id": "d4847e1df3bb4d408dd3182034109723",
"invoice_lines": [
{
"product_id": "2c5b896609864999a664f4fe3a36b5b9",
"description": "Line 1",
"ledger_account_id": "718c18bb70884da186678e4e5c0e464c",
"quantity": 2,
"unit_price": 55,
"discount_amount": 10,
"tax_rate_id": "ES_STANDARD"
},
{
"product_id": "39d93f60e87b4301a346ab435f507010",
"description": "Line 2",
"ledger_account_id": "718c18bb70884da186678e4e5c0e464c",
"quantity": 2,
"unit_price": 55,
"discount_amount": 10,
"tax_rate_id": "ES_LOWER_1"
}]
}
}
Corrective invoices update the balances of the ledger accounts, when they are created, a transaction is created as well.
Fetching The PDF Representation Of A Sales Document
For all sales documents, Accounting creates a PDF file. To fetch this PDF, set the Accept:
HTTP header to
application/pdf
:
GET /sales_invoices/{id}
Accept: application/pdf
This will return the PDF file in the response body.