Data Format Specification
1. Overview
This document defines the Invoice Data Format used in the Billy app, a structured representation of invoice data using JSON.
The format is designed to be:
- Human-readable
- Easy to validate and parse
- Expandable for future requirements
Each invoice is represented as a single JSON object.
2. Conventions
- Encoding: UTF-8
- Date: ISO 8601 format (
YYYY-MM-DD) - Country: ISO 3166-1 A2 codes (e.g.,
DE,FR) - Currency: ISO 4217 codes (e.g.,
EUR,USD) - All property names are camelCase
- All monetary values are represented as decimal numbers (no strings)
3. Top-Level Structure
An invoice must be a JSON object with the following structure:
{
"version": number,
"id": "string”,
"number": number,
"date": "string”,
"serviceDateStart": "string",
"recipient": { ... },
"sender": { ... },
"items": [ ... ],
"currency" : "string”,
"status": "string”
}
4. Field Definitions
4.1 First-level Fields
| Field | Type | Required | Description |
|---|---|---|---|
| version | number | Yes | Data format version |
| type | string | Yes | Type of this document (invoice, cancellation, quote) |
| id | string | Yes | Unique invoice identifier |
| number | number | Yes | Invoice number |
| date | string | Yes | Invoice date (ISO 8601) |
| serviceDateStart | string | Yes | Service date |
| serviceDateEnd | string | No | Service date end (if it’s a time span) |
| recipient | object | Yes | Recipient of the invoice |
| sender | object | Yes | Sender of the invoice |
| items | array | Yes | Items |
| grossPrices | bool | No | If ‘true’ all item prices are gross values (‘false’ is the default – all net prices) |
| currency | string | Yes | Currency code (ISO 4217) |
| status | string | Yes | Status |
| statusUpdateDate | string | No | Date of latest status change |
| cancelledInvoiceId | string | No | Only if document is a cancellation invoice |
There are four different statuses:
DraftSentPaidCancelled
4.2 Party Object (recipient / sender)
Example:
{
"name": "Ethical Company Co. KG",
"address": {
"lineOne": "Rosenthaler Straße 59e",
"lineTwo": "",
"postcode": "10119",
"city": "Berlin",
"country": "DE"
},
"email": "mail@ethical.com",
"phone": "0173 623716157",
"web": "www.ethical.com",
"iban": "DE89 3704 0044 0532 0130 00",
"bic": "SOBKDEB2XXX",
"taxNumber": "21\/815\/08150",
"vatNumber": "DE123456789"
}
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Legal name |
| address | object | Yes | Postal address |
| string | No | Email address | |
| phone | string | No | Phone number |
| iban | string | No | IBAN |
| bic | string | No | BIC |
| taxNumber | string | No | Tax number |
| vatNumber | string | No | VAT number |
4.3 Items
The items array is a collection of item objects. Each consists out of five required and one optional parameters.
Example:
{
"id": "78ADA733-210B-4693-A103-B30ACC3D4720",
"description": "Website Design”,
"quantity": 8,
"unit": "Hour",
"unitPrice": 100,
"vatPercentage": 19
},
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Unique item identifier |
| description | string | Yes | Item description |
| quantity | number | Yes | Quantity of items |
| unit | string | Yes | Unit |
| unitPrice | number | Yes | Price per unit |
| vatPercentage | number | No | Percentage of VAT |
There are five different units:
PieceHourDayWeekLump Sum
5. Example
{
"version": 1,
"id": "96D8F36E-C83B-4618-83AF-A7513ECA9964",
"number": 13,
"date": "2025-10-22",
"serviceDateStart": "2025-10-22",
"serviceDateEnd": "2025-10-29",
"recipient": {
"name": "Eric Wätke",
"address": {
"lineOne": "",
"lineTwo": "Potsdamer Straße 96",
"postcode": "10785",
"city": "Berlin",
"country": "DE"
},
"email": "eric@mail.com"
},
"sender": {
"name": "Ethical Company Co. KG",
"address": {
"lineOne": "Rosenthaler Straße 59e",
"lineTwo": "",
"postcode": "10119",
"city": "Berlin",
"country": "DE"
},
"email": "mail@ethical.com"
"phone": "0173 623716157"
"web": "www.ethical.com"
"iban": "DE89 3704 0044 0532 0130 00",
"bic": "SOBKDEB2XXX",
"taxNumber": "21\/815\/08150",
"vatNumber": "DE123456789"
},
"items": [
{
"id": "0001C5C6-DCF3-4FF8-86B3-C46227C30AC6",
"description": "Logo Design",
"quantity": 5,
"unit": "Hour",
"unitPrice": 80,
"vatPercentage": 19
},
{
"id": "78ADA733-210B-4693-A103-B30ACC3D4720",
"description": "Color Palette Development",
"quantity": 1,
"unit": "Hour",
"unitPrice": 80,
"vatPercentage": 19
},
{
"id": "BFEC2C4A-1B5D-492D-8D63-4CA57DB56628",
"description": "Flyer Design",
"quantity": 1,
"unit": "Hour",
"unitPrice": 80,
"vatPercentage": 19
}
],
"currency" : "EUR",
"status": "Draft",
"statusUpdateDate": "2026-03-29"
}
6. Versioning
- The format version is defined by the
versionnumber - Backward-compatible changes may add optional fields
- Breaking changes must increment the major version
7. Extensibility
- Additional fields may be added
- Additional fields should be placed at the end
- A reader must ignore unknown fields
8. Error Handling
An invoice is considered invalid if:
- Required fields are missing
- Data types do not match the specification