Invoices
Invoices are at the heart of the services provided by Profifact, be it through the user interface or the Profifact service. After creating a customer, a client can create invoices for that customer. This article describes the life cycle of an invoice and how clients can use the Profifact service to create, retrieve, update and delete invoices.
Index
Introduction
The core service provided by Profifact is the creation of invoices. It is no coincidence that
the /invoices resource has the most extensive functionality of all
the resources that are provided. Clients can retrieve previously created invoices in multiple
formats, create invoices and update and delete concept invoices.
Profifact assigns statuses to invoices to indicate how far invoices have progressed through the
invoice life cycle:
- CONCEPT
- Indicates that an invoice is a concept that has not been made definitive yet. Invoices with status CONCEPT do not have an invoice number and can be modified or deleted by the client. Once a concept invoice is marked definitive, it is assigned an invoice number and its status is set to UNSETTLED.
- UNSETTLED
- Indicates that an invoice is definitive and is awaiting payment by the customer. Invoices with status UNSETTLED cannot be modified or deleted. Depending on whether payment is received, unsettled invoices progress to either status PAID or UNCOLLECTIBLE.
- PAID
- Indicates that an invoice has been settled by the customer. This is a final status that is assigned automatically once the total debt represented by an invoice is exactly the amount paid by the customer. If additional (and possibly negative) payments are added to the invoice status is reset to UNSETTLED.
- UNCOLLECTIBLE
- Indicates that the debt represented by the invoice is unsettled but that payment is not likely to occur. This is a final status that must be assigned explicitly, usually after extensive efforts to collect the debt. If payment is received after all, the status of an invoice may be reset to UNSETTLED from which it may progress to PAID.
A new invoice starts with status CONCEPT. It has one or more invoice lines and the client is free to change any of its the lines and properties. The client may even delete the invoice without any consequences. A concept invoice can be based on an offer or be a reversal of a previously created invoice (called the parent invoice). A concept invoice progresses to status UNSETTLED when the client decides to send the invoice to the customer. From that moment on the invoice cannot be modified or deleted anymore. If an error is discovered in an unsettled invoice, a reversal invoice can be created to (partially) reverse the claims made by the original invoice. Payments can be added to an unsettled invoice, ultimately causing the invoice to progress to status PAID. To remind a customer of the obligation to settle the debt represented by an invoice one or more reminders can be created for the unsettled invoice. If, despite all efforts, a customer is unwilling or unable to settle a debt, the associated invoice may be set to status UNCOLLECTIBLE. This usually happens when a customer goes bankrupt and indicates that no further efforts will be made to collect the debt.
Once an invoice has reached status UNSETTLED it is not allowed to change, not even if the address of the client or the customer changes. In practice client addresses, customer addresses and even invoice templates change over time. To ensure that an invoice is not affected by such changes invoices do not directly reference a client or a customer. Instead they reference a client address and a customer address. If a new address is entered for a particular client or customer all non-concept invoices keep referring to the original (archived) address. Only concept invoices are updated to reference the new address. The same is true for invoice templates.
Starting with API version 1.5.0, text-only invoice lines are supported and each line has a type attribute that indicates the type of the line:
- REGULAR
- A regular invoice line that represents a good or service with an amount, a price and a VAT rate.
- TEXT
- A text-only invoice line that is rendered without amount, price an VAT rate. For consistency with regular invoice lines, the line amount and price are always zero and the line VAT rate is always null.
Retrieving multiple invoices
Clients can retrieve multiple invoices by sending an HTTP GET request to /invoices. Invoices can be retrieved as a set of invoice objects or as a set of summarized invoice records. The former is useful when the client wants invoice objects exactly as returned when retrieving a single invoice. The latter is more useful if the results are to be displayed in a table.Authentication is required and only invoices owned by the client are returned. If no limit is specified, the maximum number of items returned is 100. If a client has more than 100 invoices, multiple requests are needed to retrieve all items.
Request
HTTP GET requests to /invoices may include any of the following GET parameters:- order
- A comma separated set of field names specifying the sort order of the matching items. A minus sign preceeding a field name indicates descending sort order.
- offset
- The offset of the first item to return from the collection of matching items.
- limit
- The maximum number of items to return.
- summary
- Specifies whether to return summaries or objects. Valid values are 0 to indicate invoice objects must be returned (i.e. no summarized information) and 1 to indicate that the server should return summarized invoice information. 0 is the default value and yields the same results as not specifying the summary parameter at all.
- customerId
- A unique ID of the customer whose invoices to return. If specified, only invoices of a particular customer are returned. All three ID forms defined in the support section on retrieving a customer are supported.
- status
- A commma separated array of invoices statuses, as defined in the introduction, indicating the statuses of the invoices to include in the results. If specified the results are filtered by invoice status such that only invoices are included whose statuses are in the array of invoice statuses indicated by the value this parameter. The empty string is not a valid value for this parameter, because it would always cause an empty result set.
Examples
// Retrieve the first 100 invoice objects ordered by ID (both are equivalent):
GET /invoices?summary=0&limit=100&order=id HTTP/1.1
GET /invoices HTTP/1.1
// Retrieve invoice objects 20 through 29 (if available) ordered by number:
GET /invoices?order=number&offset=20&limit=10 HTTP/1.1
// Retrieve invoice objects sorted by price type, status and id (descending):
GET /invoices?order=priceType,status,-id HTTP/1.1
// Retrieve summaries of the first 100 invoices ordered by invoice ID:
GET /invoices?summary=1&order=id HTTP/1.1
// Retrieve the first 100 invoice objects for a customer by ID (both are equivalent):
GET /invoices?customerId=989732 HTTP/1.1
GET /invoices?customerId=id:989732 HTTP/1.1
// Retrieve the first 100 invoice objects for a customer by address ID:
GET /invoices?customerId=addressId:5941 HTTP/1.1
// Retrieve the first 100 invoice objects for a customer by external ID:
GET /invoices?customerId=externalId:JQ88P003 HTTP/1.1
// Retrieve the first 100 concept invoice objects:
GET /invoices?status=CONCEPT HTTP/1.1
// Retrieve summaries of the first 100 unsettled and uncollectible invoices:
GET /invoices?summary=1&status=UNSETTLED,UNCOLLECTIBLE HTTP/1.1
Response
The Profifact server may send any of the status codes defined in response status codes in response to an incoming request. For a valid request HTTP status 200 OK is returned and the response body contains a data structure with the members defined in the tables below. See the section on data types for an explanation of property data types.
If the summary parameter is not specified or has value 0 the following fields are returned:
Name | Type | Description |
---|---|---|
count | int | Specifies the number of items returned. |
total | int | Specifies the total number of matching items. |
offset | int | Specifies the offset of the first returned item in the collection of all matching items. |
items | array | The possibly empty array of the invoice objects selected for being returned based on the request. For each object the server returns exactly the properties defined by the Retrieving an invoice response. |
Otherwise, if the summary parameter is specified and has value 1 the following fields are returned:
Name | Type | Description |
---|---|---|
count | int | Specifies the number of items returned. |
total | int | Specifies the total number of matching items. |
offset | int | Specifies the offset of the first returned item in the collection of all matching items. |
items | array | The possibly empty array of the invoice summary records selected for being returned based on the request. |
id | int | The unique ID of the invoice assigned by Profifact. |
customerAddressId | int | The unique ID of the version of the address of the customer associated with the invoice. Customer addresses may change over time, but an invoice always keeps a reference to the version of the address that was assigned to it when it was created. The only time the customer address ID of an invoice changes is when the client modifies the address of the customer while the invoice has status CONCEPT. The reference held by the invoice is then updated to the new version of the customer address. |
parentId | int? | The unique ID of the invoice of which the invoice is a reversal. If the invoice is not a reversal the value is null. |
offerId | int? | The unique ID of the offer on which the invoice is based. If the invoice is not based on an offer the value is null. |
number | int? | The number assigned to the invoice or null if the invoice has status CONCEPT. Invoice numbers start with the year in which they were created. The year in the invoice number is always the same as the year in the date of the invoice. The last four digits of the invoice number are the index of the invoice in that year. |
date | date | The date of the invoice. |
status | string | The status of the invoice as defined in the introduction. |
paymentPeriod | int | The payment period of the invoice in days. Valid values are in the range from 0 to 999. |
customerName | string | The name of the customer of the invoice. |
totalInclusive | decimal | The total amount represented by the invoice inclusing VAT. |
totalPaid | decimal | The total amount represented by all payments added to the invoice. |
reminderCount | int | The number of reminders that have been created for the invoice. |
Retrieving an invoice
Clients can retrieve a single invoice by sending an HTTP GET request to /invoices/RESOURCE_ID where RESOURCE_ID is the unique identifier of the requested invoice.Request
Invoices can be retrieved in two formats, JSON and PDF. Which of the two is returned for a particular request depends on the value of the Accept request header. If the first acceptable media type specified in the Accept header is application/json, the server returns a JSON representation of the invoice. If the first acceptable media type is application/pdf, the server returns a rendered PDF representation of the invoice.Currently, no additional GET parameters are supported for requests to /invoices/RESOURCE_ID.
Examples
// Retrieve the JSON reprsentation of an invoice by its unique ID:
GET /invoices/23479 HTTP/1.1
Accept: application/json
// Retrieve a PDF representation of the same invoice:
GET /invoices/23479 HTTP/1.1
Accept: application/pdf
Response
The Profifact server may send any of the status codes defined in response status codes in response to an incoming request. For a valid request HTTP status 200 OK is returned and the response body contains the data requested by the client. Requesting a PDF representation causes the service to return binary PDF data that can be stored as a PDF file. Requesting a JSON representation causes the service to return an invoice object whose members are shown in the table below. See the section on data types for an explanation of property data types.
Name | Type | Description |
---|---|---|
id | int | The unique ID of the invoice assigned by Profifact. |
parentId | int? | The unique ID of the invoice of which the invoice is a reversal. If the invoice is not a reversal the value is null. |
offerId | int? | The unique ID of the offer on which the invoice is based. If the invoice is not based on an offer the value is null. |
clientAddressId | int | The unique ID of the version of the client's address associated with the invoice. Client addresses may change over time, but an invoice always keeps a reference to the version of the address that was assigned to it when it was created. The only time the client address ID of an invoice changes is when the client modifies its own address while the invoice has status CONCEPT. The reference held by the invoice is then updated to the new version of the client's address. |
customerAddressId | int | The unique ID of the version of the address of the customer associated with the invoice. Customer addresses may change over time, but an invoice always keeps a reference to the version of the address that was assigned to it when it was created. The only time the customer address ID of an invoice changes is when the client modifies the address of the customer while the invoice has status CONCEPT. The reference held by the invoice is then updated to the new version of the customer address. |
templateId | int | The unique ID of the version of the template associated with the invoice. Invoice templates may change over time, but an invoice always keeps a reference to the version of the template that was assigned to it when the invoice was created. The only time the template ID of an invoice changes is when the client modifies the template while the invoice has status CONCEPT. The reference held by the invoice is then updated to the new version of the template. |
number | int? | The number assigned to the invoice or null if the invoice has status CONCEPT. Invoice numbers start with the year in which they were created. The year in the invoice number is always the same as the year in the date of the invoice. The last four digits of the invoice number are the index of the invoice in that year. |
date | date | The date of the invoice. |
status | string | The status of the invoice as defined in the introduction. |
priceType | string | Indicates whether the prices in the lines of the invoice include VAT. Valid values are INCLUSIVE and EXCLUSIVE. |
paymentPeriod | int | The payment period of the invoice in days. Valid values are in the range from 0 to 999. |
reference | string | The reference of the invoice as specified by the client. |
comments | string | The comments of the invoice as specified by the client. |
lines | array | The array invoice lines that are part of the invoice. An invoice has at least one invoice line. Invoice lines do not have IDs, because they do not exist as seperate entities outside the scope of invoices. Invoice lines are returned in the order in which they appear on the invoice. |
amount | decimal | The amount of the product or service represented by the invoice line. |
price | decimal | The price of the product or service represented by the invoice line. |
description | string | A description of the product or service represented by the invoice line. |
vatRateId | int | The unique ID of the VAT rate that applies to the product or service represented by the invoice line. |
payments | array | The array of payments added to the invoice. An invoice has zero or more payments. Invoices with status CONCEPT cannot have payments. |
id | int | The unique ID of the payment. |
date | date | The date of the payment. |
type | string | The type of the invoice line as defined in the introduction. |
amount | decimal | The amount paid. |
method | string | The payment method used. Valid values are UNSPECIFIED, BANK, CASH, PIN, CREDITCARD, DIRECTDEBIT and PRIVATE. |
reminders | string | The array of reminders created for the invoice. Zero or more reminders can be created for an invoice. Reminders cannot be created for invoices with status CONCEPT. |
id | int | The unique ID of the reminder. |
date | date | The date of the reminder. |
type | string | The type of the reminder indicating its severity. Valid values from mild to severy are INFORMAL, FORMAL and DEFAULT. |
number | int | The number assigned to the reminder by Profifact. Reminder numbers start with the year in which they were created. The year in the reminder number is always the same as the year in the date of the reminder. The last four digits of the reminder number are the index of the reminder in that year. |
index | int | The index of the reminder in the set of reminders created for the invoice. |
amountUnpaid | decimal | The part of total amount expressed by the invoice that has not been paid yet. The value of this property is negative if the customer has overpaid (i.e. the client owes a part of the paid amount to the client). |
Creating an invoice
A new invoice can be created by sending an HTTP POST request to /invoices. The request body must contain values for at least the mandatory invoice properties encoded in the content type indicated by the client through the Content-Type header. Currently only JSON encoded data is supported.Request
HTTP POST requests to /invoices are validated before an invoice is created. Valid requests must provide valid values for the mandatory fields listed in the table below. If specified, values for optional fields must be valid as well. See the section on data types for an explanation of property data types.
Name | Type | Valid values | Description |
---|---|---|---|
parentId | int? | The unique ID of the invoice for which the new invoice is a reversal or null if the invoice is not a reversal (i.e. it is a regular invoice). | |
offerId | int? | The unique ID of the offer on which the new invoice is based or null if the invoice is not based on an offer. | |
customerAddressId | int | The unique ID of the latest version of the customer address of the new invoice. As explained in the introduction, invoices keep references to customers through customer addresses. Only a non-archived customer address can be assigned to a new invoice. Use the /customers resource to obtain the unique ID of the latest address of a customer. | |
templateId | int? | The unique ID of a non-archived version of the template to assign to the new invoice. Use the /templates resource to obtain a template ID. If this property is missing or if its value is null, the unique ID of the client's default invoice template is assigned to the new invoice. | |
date | date | The date of the new invoice. | |
status | string | CONCEPT, UNSETTLED | The status of the new invoice as defined in the introduction. If a new invoice is created with status CONCEPT, it can be modified and deleted in subsequent requests or using the Profifact UI. Before it is assigned an invoice number it must explicitly be set to status UNSETTLED. If a new invoice is created with status UNSETTLED then it is immediately assigned an invoice number. It cannot be modified or deleted. |
priceType | string | INCLUSIVE, EXCLUSIVE | Indicates whether the prices in the lines of the new invoice include VAT. |
paymentPeriod | int? | 0 - 999 | The payment period of the new invoice in days. If this property is missing, or if its value is null the default payment period for the customer identified by the customerAddressId property is used. If that customer does not have a custom payment period then the default payment period of the client is used (see settings). |
reference | string? | ^.{0,255}$ | The reference for the new invoice. A reference usually is a project identifier or a cost center identifier provided by the customer. |
comments | string? | ^.{0,4096}$ | The client's comments associated with the new invoice. |
lines | array | The array invoice lines that are part of the new invoice. An invoice has at least one invoice line. Invoice lines are added to the new invoice in the order in which they appear in the request. Each of the invoice lines must provide values for the amount, price, description and vatRateId properties. | |
amount | decimal | The amount of the product or service represented by the invoice line. | |
price | decimal | The price of the product or service represented by the invoice line. | |
description | string | ^.{1,4096}$ | A description of the product or service represented by the invoice line. |
vatRateId | int | The unique ID of the VAT rate that applies to the product or service represented by the invoice line. VAT rate identifiers can be found using the /vatrates resource. VAT rates are currently mandatory, but null may in the future cause the default VAT rate of the client to be used (see settings). |
Examples
// A minimal example for creating a new concept invoice:
POST /invoices HTTP/1.1
{
"customerAddressId":1,
"templateId":4,
"date":"2016-01-01",
"status":"CONCEPT",
"priceType":"EXCLUSIVE",
"lines":[{"amount":1,"price":100,"description":"Some description","vatRateId":6}]
}
// A more extensive example for creating an unsettled invoice based on an offer:
POST /invoices HTTP/1.1
{
"customerAddressId":1,
"offerId":5588,
"templateId":4,
"date":"2016-01-01",
"status":"UNSETTLED",
"paymentPeriod":90,
"priceType":"INCLUSIVE",
"reference":"PQ7937-A",
"comments":"2% discount if settled within 8 days after invoice date",
"lines":
[
{"amount":2.73,"price":100,"description":"Meters of product","vatRateId":2}
{"amount":17.50,"price":35.0,"description":"Work hours","vatRateId":6}
]
}
Response
The Profifact server may send any of the status codes defined in response status codes in response to an incoming request. For a valid request HTTP status 201 Created is returned and the response body contains exactly the same information as the Retrieving an invoice response.Updating an invoice
The update method of the Profifact service supports updating of existing concept invoices. Requests to update invoices with statuses other than CONCEPT are denied. The unique ID of the invoice to be updated must be specified as the RESOURCE_ID in HTTP PUT requests to /invoices/RESOURCE_ID.When updating an invoice only the changes have to be specified. E.g. to update only the status property of a concept invoice to UNSETTLED, the request data needs only provide the status property with its new value (see below for examples). The lines of an invoice are considered a single property. Changing one invoice line requires that all lines are posted as the new value of the lines property.
Setting the value of a property to null is interpreted by the service as a request to assign null to the property and not as a request in which the value of that property must not be changed. The latter can be accomplished by not specifying the property at all.
Request
To update an existing concept invoice send an HTTP PUT request to /invoices/RESOURCE_ID where RESOURCE_ID is the unique ID of the invoice to be updated. All the properties defined in the section on creating an invoice may be present in the request data. The same validation rules apply.Examples
// Changing the status of an invoice from CONCEPT to UNSETTLED:
PUT /invoices/972371 HTTP/1.1
{ "status": "UNSETTLED" }
// Changing the price type and payment period of an invoice:
PUT /invoices/972371 HTTP/1.1
{ "priceType": "INCLUSIVE", "paymentPeriod": 60 }
// The following are not identical. The first request sets the value of the offerId property
// to null. The second request leaves the value of the offerId property untouched:
PUT /invoices/972371 HTTP/1.1
{ "date": "2016-02-28", "offerId": null }
PUT /invoices/972371 HTTP/1.1
{ "date": "2016-02-28" }
// Changing one of the lines of an invoice (compare with the examples for creating an invoice):
PUT /invoices/972371 HTTP/1.1
{
"lines":
[
{"amount":2.73,"price":100,"description":"Meters of product","vatRateId":2}
{"amount":17.50,"price":135.0,"description":"Work hours","vatRateId":6}
]
}
// Changing an invoice to become a completely different invoice and setting its status to SETTLED:
POST /invoices HTTP/1.1
{
"customerAddressId":834,
"parentId":2382,
"templateId":88,
"date":"2016-03-17",
"status":"UNSETTLED",
"paymentPeriod":30,
"priceType":"EXCLUSIVE",
"reference":null,
"comments":"Final invoice for subscription 789388",
"lines":[{"amount":1.0,"price":99.0,"description":"Monthly subscription fee","vatRateId":6}]
}
Response
The Profifact server may send any of the status codes defined in response status codes in response to an incoming request. For a valid request HTTP status 200 OK is returned and the response body contains exactly the same information as the Retrieving an invoice response.Deleting an invoice
Invoices with status CONCEPT can be deleted by the client. Requests to delete invoices with any of the other statuses are denied.Request
To delete an invoice, send an HTTP DELETE request to /invoices/RESOURCE_ID where RESOURCE_ID is the unique ID of the invoice to delete.Examples
// Delete an invoice:
DELETE /invoices/972371 HTTP/1.1