Custom Payments

Personas in this Story: Default, Client1, Client2.

System starts with an empty list of invoices:

Response: HTTP 200, application/json (Hide)
GET /invoices

Response:

1
[]

But we have a couple of currencies defined:

Response: HTTP 200, application/json (Hide)
GET /currencies

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
[
    {
        "id": 3,
        "class": "Currency",
        "url_path": "\/currencies\/3",
        "name": "British Pound",
        "updated_on": null,
        "code": "GBP",
        "is_default": false,
        "decimal_spaces": 2,
        "decimal_rounding": 0
    },
    {
        "id": 1,
        "class": "Currency",
        "url_path": "\/currencies\/1",
        "name": "Euro",
        "updated_on": null,
        "code": "EUR",
        "is_default": false,
        "decimal_spaces": 2,
        "decimal_rounding": 0
    },
    {
        "id": 4,
        "class": "Currency",
        "url_path": "\/currencies\/4",
        "name": "Japanese Yen",
        "updated_on": null,
        "code": "JPY",
        "is_default": false,
        "decimal_spaces": 2,
        "decimal_rounding": 0
    },
    {
        "id": 2,
        "class": "Currency",
        "url_path": "\/currencies\/2",
        "name": "US Dollar",
        "updated_on": null,
        "code": "USD",
        "is_default": true,
        "decimal_spaces": 2,
        "decimal_rounding": 0
    }
]

As well as a default tax rate:

Response: HTTP 200, application/json (Hide)
GET /tax-rates

Response:

1
2
3
4
5
6
7
8
9
10
[
    {
        "id": 1,
        "class": "TaxRate",
        "url_path": "\/tax-rates\/1",
        "name": "VAT",
        "percentage": 17.5,
        "is_default": false
    }
]

For the purpose of this test, we have a client company with two members:

Response: HTTP 200, application/json (Hide)
GET /companies/2

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
    "single": {
        "id": 2,
        "class": "Company",
        "url_path": "\/companies\/2",
        "name": "Client Company GmbH",
        "members": [
            2,
            3
        ],
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "is_archived": false,
        "created_on": 1430164820,
        "created_by_id": 1,
        "updated_on": 1430164820,
        "updated_by_id": 1,
        "address": "Street Name 12\nCity",
        "phone": null,
        "homepage_url": null,
        "tax_id": null,
        "currency_id": 1,
        "is_owner": false,
        "has_note": false
    },
    "hourly_rates": {
        "1": 100
    },
    "active_projects_count": 0
}

Lets create an invoice:

Response: HTTP 200, application/json (Hide)
POST /invoices

Payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
    "company_id": 2,
    "number": "1\/2014",
    "items": [
        {
            "description": "First item",
            "quantity": 100,
            "unit_cost": 25
        },
        {
            "description": "Second item",
            "quantity": 250,
            "unit_cost": 13,
            "first_tax_rate_id": 1
        },
        {
            "description": "Third item",
            "quantity": 15,
            "unit_cost": 25
        }
    ],
    "private_note": "Client will not be able to see this"
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
{
    "single": {
        "id": 1,
        "class": "Invoice",
        "url_path": "\/invoices\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "company_id": 2,
        "company_name": "Client Company GmbH",
        "company_address": "Street Name 12\nCity",
        "note": null,
        "currency_id": 1,
        "language_id": 0,
        "discount_rate": 0,
        "subtotal": 6125,
        "subtotal_without_discount": 6125,
        "discount": 0,
        "tax": 568.75,
        "rounding_difference": 0,
        "rounded_total": 6693.75,
        "total": 6693.75,
        "paid_amount": 0,
        "balance_due": 6693.75,
        "recipients": null,
        "email_from": null,
        "email_subject": null,
        "email_body": null,
        "second_tax_is_enabled": false,
        "second_tax_is_compound": false,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164822,
        "based_on_type": null,
        "based_on_id": null,
        "number": "1\/2014",
        "project_id": 0,
        "purchase_order_number": null,
        "issued_on": 1430164822,
        "due_on": 1430164822,
        "allow_payments": 1,
        "closed_on": null,
        "sent_on": null,
        "hash": "zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR",
        "status": "issued",
        "public_url": "http:\/\/feather.dev\/s\/invoice?hash=zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR&number=1%2F2014",
        "is_credit_invoice": false
    },
    "reminders": [],
    "items": [
        {
            "id": 1,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "First item",
            "quantity": 100,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 2500,
            "subtotal_without_discount": 2500,
            "discount": 0,
            "total": 2500,
            "position": 1,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 2,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/2",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Second item",
            "quantity": 250,
            "unit_cost": 13,
            "first_tax_rate_id": 1,
            "first_tax_value": 568.75,
            "first_tax_name": "VAT",
            "first_tax_rate": 17.5,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 3250,
            "subtotal_without_discount": 3250,
            "discount": 0,
            "total": 3818.75,
            "position": 2,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 3,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/3",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Third item",
            "quantity": 15,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 375,
            "subtotal_without_discount": 375,
            "discount": 0,
            "total": 375,
            "position": 3,
            "time_record_ids": [],
            "expense_ids": []
        }
    ],
    "time_records": [],
    "expenses": [],
    "payments": []
}

There are no payments made for this invoice. We can double check:

Response: HTTP 200, application/json (Hide)
GET /payments

Response:

1
[]

By adding 6693.75 we will mark this invoice as paid:

Response: HTTP 200, application/json (Hide)
POST /payments

Payload:

1
2
3
4
5
6
{
    "parent_type": "Invoice",
    "parent_id": 1,
    "amount": 6693.75,
    "comment": "Paid in full"
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
    "single": {
        "id": 1,
        "class": "Payment",
        "url_path": "\/payments\/1",
        "parent_type": "Invoice",
        "parent_id": 1,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164822,
        "amount": 6693.75,
        "status": "paid",
        "paid_on": 1430164822,
        "currency_id": 1,
        "method": "custom",
        "comment": "Paid in full",
        "additional_properties": []
    }
}

Lets check if payment was properly recorded and that invoice status has been changed:

Response: HTTP 200, application/json (Hide)
GET /invoices/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
{
    "single": {
        "id": 1,
        "class": "Invoice",
        "url_path": "\/invoices\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "company_id": 2,
        "company_name": "Client Company GmbH",
        "company_address": "Street Name 12\nCity",
        "note": null,
        "currency_id": 1,
        "language_id": 0,
        "discount_rate": 0,
        "subtotal": 6125,
        "subtotal_without_discount": 6125,
        "discount": 0,
        "tax": 568.75,
        "rounding_difference": 0,
        "rounded_total": 6693.75,
        "total": 6693.75,
        "paid_amount": 6693.75,
        "balance_due": 0,
        "recipients": null,
        "email_from": null,
        "email_subject": null,
        "email_body": null,
        "second_tax_is_enabled": false,
        "second_tax_is_compound": false,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164822,
        "based_on_type": null,
        "based_on_id": null,
        "number": "1\/2014",
        "project_id": 0,
        "purchase_order_number": null,
        "issued_on": 1430092800,
        "due_on": 1430092800,
        "allow_payments": 1,
        "closed_on": 1430092800,
        "sent_on": null,
        "hash": "zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR",
        "status": "paid",
        "public_url": "http:\/\/feather.dev\/s\/invoice?hash=zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR&number=1%2F2014",
        "is_credit_invoice": false
    },
    "reminders": [],
    "items": [
        {
            "id": 1,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "First item",
            "quantity": 100,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 2500,
            "subtotal_without_discount": 2500,
            "discount": 0,
            "total": 2500,
            "position": 1,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 2,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/2",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Second item",
            "quantity": 250,
            "unit_cost": 13,
            "first_tax_rate_id": 1,
            "first_tax_value": 568.75,
            "first_tax_name": "VAT",
            "first_tax_rate": 17.5,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 3250,
            "subtotal_without_discount": 3250,
            "discount": 0,
            "total": 3818.75,
            "position": 2,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 3,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/3",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Third item",
            "quantity": 15,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 375,
            "subtotal_without_discount": 375,
            "discount": 0,
            "total": 375,
            "position": 3,
            "time_record_ids": [],
            "expense_ids": []
        }
    ],
    "time_records": [],
    "expenses": [],
    "payments": [
        {
            "id": 1,
            "class": "Payment",
            "url_path": "\/payments\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "created_on": 1430164822,
            "created_by_id": 1,
            "updated_on": 1430164822,
            "amount": 6693.75,
            "status": "paid",
            "paid_on": 1430092800,
            "currency_id": 1,
            "method": "custom",
            "comment": "Paid in full",
            "additional_properties": []
        }
    ]
}

On a side note, invoice that is marked as paid will no longer be available in /invoices list, but moved to archive:

Response: HTTP 200, application/json (Hide)
GET /invoices

Response:

1
[]
Response: HTTP 200, application/json (Hide)
GET /invoices/archive

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
[
    {
        "id": 1,
        "class": "Invoice",
        "url_path": "\/invoices\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "company_id": 2,
        "company_name": "Client Company GmbH",
        "company_address": "Street Name 12\nCity",
        "note": null,
        "currency_id": 1,
        "language_id": 0,
        "discount_rate": 0,
        "subtotal": 6125,
        "subtotal_without_discount": 6125,
        "discount": 0,
        "tax": 568.75,
        "rounding_difference": 0,
        "rounded_total": 6693.75,
        "total": 6693.75,
        "paid_amount": 6693.75,
        "balance_due": 0,
        "recipients": null,
        "email_from": null,
        "email_subject": null,
        "email_body": null,
        "second_tax_is_enabled": false,
        "second_tax_is_compound": false,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164822,
        "based_on_type": null,
        "based_on_id": null,
        "number": "1\/2014",
        "project_id": 0,
        "purchase_order_number": null,
        "issued_on": 1430092800,
        "due_on": 1430092800,
        "allow_payments": 1,
        "closed_on": 1430092800,
        "sent_on": null,
        "hash": "zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR",
        "status": "paid",
        "public_url": "http:\/\/feather.dev\/s\/invoice?hash=zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR&number=1%2F2014",
        "is_credit_invoice": false
    }
]

If we update the payment, so it is not the full amount:

Response: HTTP 200, application/json (Hide)
PUT /payments/1

Payload:

1
2
3
{
    "amount": 3693.75
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
    "single": {
        "id": 1,
        "class": "Payment",
        "url_path": "\/payments\/1",
        "parent_type": "Invoice",
        "parent_id": 1,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164823,
        "amount": 3693.75,
        "status": "paid",
        "paid_on": 1430092800,
        "currency_id": 1,
        "method": "custom",
        "comment": "Paid in full",
        "additional_properties": []
    }
}

invoice should pick up the change:

Response: HTTP 200, application/json (Hide)
GET /invoices/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
{
    "single": {
        "id": 1,
        "class": "Invoice",
        "url_path": "\/invoices\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "company_id": 2,
        "company_name": "Client Company GmbH",
        "company_address": "Street Name 12\nCity",
        "note": null,
        "currency_id": 1,
        "language_id": 0,
        "discount_rate": 0,
        "subtotal": 6125,
        "subtotal_without_discount": 6125,
        "discount": 0,
        "tax": 568.75,
        "rounding_difference": 0,
        "rounded_total": 6693.75,
        "total": 6693.75,
        "paid_amount": 3693.75,
        "balance_due": 3000,
        "recipients": null,
        "email_from": null,
        "email_subject": null,
        "email_body": null,
        "second_tax_is_enabled": false,
        "second_tax_is_compound": false,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164823,
        "based_on_type": null,
        "based_on_id": null,
        "number": "1\/2014",
        "project_id": 0,
        "purchase_order_number": null,
        "issued_on": 1430092800,
        "due_on": 1430092800,
        "allow_payments": 1,
        "closed_on": null,
        "sent_on": null,
        "hash": "zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR",
        "status": "issued",
        "public_url": "http:\/\/feather.dev\/s\/invoice?hash=zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR&number=1%2F2014",
        "is_credit_invoice": false
    },
    "reminders": [],
    "items": [
        {
            "id": 1,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "First item",
            "quantity": 100,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 2500,
            "subtotal_without_discount": 2500,
            "discount": 0,
            "total": 2500,
            "position": 1,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 2,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/2",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Second item",
            "quantity": 250,
            "unit_cost": 13,
            "first_tax_rate_id": 1,
            "first_tax_value": 568.75,
            "first_tax_name": "VAT",
            "first_tax_rate": 17.5,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 3250,
            "subtotal_without_discount": 3250,
            "discount": 0,
            "total": 3818.75,
            "position": 2,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 3,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/3",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Third item",
            "quantity": 15,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 375,
            "subtotal_without_discount": 375,
            "discount": 0,
            "total": 375,
            "position": 3,
            "time_record_ids": [],
            "expense_ids": []
        }
    ],
    "time_records": [],
    "expenses": [],
    "payments": [
        {
            "id": 1,
            "class": "Payment",
            "url_path": "\/payments\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "created_on": 1430164822,
            "created_by_id": 1,
            "updated_on": 1430164823,
            "amount": 3693.75,
            "status": "paid",
            "paid_on": 1430092800,
            "currency_id": 1,
            "method": "custom",
            "comment": "Paid in full",
            "additional_properties": []
        }
    ]
}

Finally, when we drop the payment:

Response: HTTP 200, application/json (Hide)
DELETE /payments/1

Response:

1
null

invoice should be updated accordingly:

Response: HTTP 200, application/json (Hide)
GET /invoices/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
{
    "single": {
        "id": 1,
        "class": "Invoice",
        "url_path": "\/invoices\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "company_id": 2,
        "company_name": "Client Company GmbH",
        "company_address": "Street Name 12\nCity",
        "note": null,
        "currency_id": 1,
        "language_id": 0,
        "discount_rate": 0,
        "subtotal": 6125,
        "subtotal_without_discount": 6125,
        "discount": 0,
        "tax": 568.75,
        "rounding_difference": 0,
        "rounded_total": 6693.75,
        "total": 6693.75,
        "paid_amount": 0,
        "balance_due": 6693.75,
        "recipients": null,
        "email_from": null,
        "email_subject": null,
        "email_body": null,
        "second_tax_is_enabled": false,
        "second_tax_is_compound": false,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164823,
        "based_on_type": null,
        "based_on_id": null,
        "number": "1\/2014",
        "project_id": 0,
        "purchase_order_number": null,
        "issued_on": 1430092800,
        "due_on": 1430092800,
        "allow_payments": 1,
        "closed_on": null,
        "sent_on": null,
        "hash": "zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR",
        "status": "issued",
        "public_url": "http:\/\/feather.dev\/s\/invoice?hash=zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR&number=1%2F2014",
        "is_credit_invoice": false
    },
    "reminders": [],
    "items": [
        {
            "id": 1,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "First item",
            "quantity": 100,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 2500,
            "subtotal_without_discount": 2500,
            "discount": 0,
            "total": 2500,
            "position": 1,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 2,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/2",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Second item",
            "quantity": 250,
            "unit_cost": 13,
            "first_tax_rate_id": 1,
            "first_tax_value": 568.75,
            "first_tax_name": "VAT",
            "first_tax_rate": 17.5,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 3250,
            "subtotal_without_discount": 3250,
            "discount": 0,
            "total": 3818.75,
            "position": 2,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 3,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/3",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Third item",
            "quantity": 15,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 375,
            "subtotal_without_discount": 375,
            "discount": 0,
            "total": 375,
            "position": 3,
            "time_record_ids": [],
            "expense_ids": []
        }
    ],
    "time_records": [],
    "expenses": [],
    "payments": []
}

Finally, lets test if payments are dropped when invoice is deleted. Lets start by adding two payments:

Response: HTTP 200, application/json (Hide)
POST /payments

Payload:

1
2
3
4
5
{
    "parent_type": "Invoice",
    "parent_id": 1,
    "amount": 3693.75
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
    "single": {
        "id": 2,
        "class": "Payment",
        "url_path": "\/payments\/2",
        "parent_type": "Invoice",
        "parent_id": 1,
        "created_on": 1430164823,
        "created_by_id": 1,
        "updated_on": 1430164823,
        "amount": 3693.75,
        "status": "paid",
        "paid_on": 1430164823,
        "currency_id": 1,
        "method": "custom",
        "comment": null,
        "additional_properties": []
    }
}
Sleeping for 1 seconds
Response: HTTP 200, application/json (Hide)
POST /payments

Payload:

1
2
3
4
5
{
    "parent_type": "Invoice",
    "parent_id": 1,
    "amount": 3000
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
    "single": {
        "id": 3,
        "class": "Payment",
        "url_path": "\/payments\/3",
        "parent_type": "Invoice",
        "parent_id": 1,
        "created_on": 1430164824,
        "created_by_id": 1,
        "updated_on": 1430164824,
        "amount": 3000,
        "status": "paid",
        "paid_on": 1430164824,
        "currency_id": 1,
        "method": "custom",
        "comment": null,
        "additional_properties": []
    }
}

With these two payments, we should of paid the invoice in full:

Response: HTTP 200, application/json (Hide)
GET /invoices/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
{
    "single": {
        "id": 1,
        "class": "Invoice",
        "url_path": "\/invoices\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "company_id": 2,
        "company_name": "Client Company GmbH",
        "company_address": "Street Name 12\nCity",
        "note": null,
        "currency_id": 1,
        "language_id": 0,
        "discount_rate": 0,
        "subtotal": 6125,
        "subtotal_without_discount": 6125,
        "discount": 0,
        "tax": 568.75,
        "rounding_difference": 0,
        "rounded_total": 6693.75,
        "total": 6693.75,
        "paid_amount": 6693.75,
        "balance_due": 0,
        "recipients": null,
        "email_from": null,
        "email_subject": null,
        "email_body": null,
        "second_tax_is_enabled": false,
        "second_tax_is_compound": false,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164824,
        "based_on_type": null,
        "based_on_id": null,
        "number": "1\/2014",
        "project_id": 0,
        "purchase_order_number": null,
        "issued_on": 1430092800,
        "due_on": 1430092800,
        "allow_payments": 1,
        "closed_on": 1430092800,
        "sent_on": null,
        "hash": "zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR",
        "status": "paid",
        "public_url": "http:\/\/feather.dev\/s\/invoice?hash=zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR&number=1%2F2014",
        "is_credit_invoice": false
    },
    "reminders": [],
    "items": [
        {
            "id": 1,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "First item",
            "quantity": 100,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 2500,
            "subtotal_without_discount": 2500,
            "discount": 0,
            "total": 2500,
            "position": 1,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 2,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/2",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Second item",
            "quantity": 250,
            "unit_cost": 13,
            "first_tax_rate_id": 1,
            "first_tax_value": 568.75,
            "first_tax_name": "VAT",
            "first_tax_rate": 17.5,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 3250,
            "subtotal_without_discount": 3250,
            "discount": 0,
            "total": 3818.75,
            "position": 2,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 3,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/3",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Third item",
            "quantity": 15,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 375,
            "subtotal_without_discount": 375,
            "discount": 0,
            "total": 375,
            "position": 3,
            "time_record_ids": [],
            "expense_ids": []
        }
    ],
    "time_records": [],
    "expenses": [],
    "payments": [
        {
            "id": 2,
            "class": "Payment",
            "url_path": "\/payments\/2",
            "parent_type": "Invoice",
            "parent_id": 1,
            "created_on": 1430164823,
            "created_by_id": 1,
            "updated_on": 1430164823,
            "amount": 3693.75,
            "status": "paid",
            "paid_on": 1430092800,
            "currency_id": 1,
            "method": "custom",
            "comment": null,
            "additional_properties": []
        },
        {
            "id": 3,
            "class": "Payment",
            "url_path": "\/payments\/3",
            "parent_type": "Invoice",
            "parent_id": 1,
            "created_on": 1430164824,
            "created_by_id": 1,
            "updated_on": 1430164824,
            "amount": 3000,
            "status": "paid",
            "paid_on": 1430092800,
            "currency_id": 1,
            "method": "custom",
            "comment": null,
            "additional_properties": []
        }
    ]
}

Payments should return both payments:

Response: HTTP 200, application/json (Hide)
GET /payments

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[
    {
        "id": 3,
        "class": "Payment",
        "url_path": "\/payments\/3",
        "parent_type": "Invoice",
        "parent_id": 1,
        "created_on": 1430164824,
        "created_by_id": 1,
        "updated_on": 1430164824,
        "amount": 3000,
        "status": "paid",
        "paid_on": 1430164824,
        "currency_id": 1,
        "method": "custom",
        "comment": null,
        "additional_properties": []
    },
    {
        "id": 2,
        "class": "Payment",
        "url_path": "\/payments\/2",
        "parent_type": "Invoice",
        "parent_id": 1,
        "created_on": 1430164823,
        "created_by_id": 1,
        "updated_on": 1430164823,
        "amount": 3693.75,
        "status": "paid",
        "paid_on": 1430164823,
        "currency_id": 1,
        "method": "custom",
        "comment": null,
        "additional_properties": []
    }
]

Now, lets cancel the invoice:

Response: HTTP 200, application/json (Hide)
PUT /invoices/1/cancel

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
{
    "single": {
        "id": 1,
        "class": "Invoice",
        "url_path": "\/invoices\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "company_id": 2,
        "company_name": "Client Company GmbH",
        "company_address": "Street Name 12\nCity",
        "note": null,
        "currency_id": 1,
        "language_id": 0,
        "discount_rate": 0,
        "subtotal": 6125,
        "subtotal_without_discount": 6125,
        "discount": 0,
        "tax": 568.75,
        "rounding_difference": 0,
        "rounded_total": 6693.75,
        "total": 6693.75,
        "paid_amount": 0,
        "balance_due": 6693.75,
        "recipients": null,
        "email_from": null,
        "email_subject": null,
        "email_body": null,
        "second_tax_is_enabled": false,
        "second_tax_is_compound": false,
        "created_on": 1430164822,
        "created_by_id": 1,
        "updated_on": 1430164825,
        "based_on_type": null,
        "based_on_id": null,
        "number": "1\/2014",
        "project_id": 0,
        "purchase_order_number": null,
        "issued_on": 1430092800,
        "due_on": 1430092800,
        "allow_payments": 1,
        "closed_on": 1430164825,
        "sent_on": null,
        "hash": "zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR",
        "status": "canceled",
        "public_url": "http:\/\/feather.dev\/s\/invoice?hash=zYQkMbqnKTzscVFheXxFuR9btICqO2zcPenrgDFR&number=1%2F2014",
        "is_credit_invoice": false
    },
    "reminders": [],
    "items": [
        {
            "id": 1,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/1",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "First item",
            "quantity": 100,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 2500,
            "subtotal_without_discount": 2500,
            "discount": 0,
            "total": 2500,
            "position": 1,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 2,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/2",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Second item",
            "quantity": 250,
            "unit_cost": 13,
            "first_tax_rate_id": 1,
            "first_tax_value": 568.75,
            "first_tax_name": "VAT",
            "first_tax_rate": 17.5,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 3250,
            "subtotal_without_discount": 3250,
            "discount": 0,
            "total": 3818.75,
            "position": 2,
            "time_record_ids": [],
            "expense_ids": []
        },
        {
            "id": 3,
            "class": "InvoiceItem",
            "url_path": "\/invoice-items\/3",
            "parent_type": "Invoice",
            "parent_id": 1,
            "discount_rate": 0,
            "description": "Third item",
            "quantity": 15,
            "unit_cost": 25,
            "first_tax_rate_id": 0,
            "first_tax_value": 0,
            "first_tax_name": "",
            "first_tax_rate": 0,
            "second_tax_rate_id": 0,
            "second_tax_value": 0,
            "second_tax_name": "",
            "second_tax_rate": 0,
            "second_tax_is_enabled": false,
            "second_tax_is_compound": false,
            "subtotal": 375,
            "subtotal_without_discount": 375,
            "discount": 0,
            "total": 375,
            "position": 3,
            "time_record_ids": [],
            "expense_ids": []
        }
    ],
    "time_records": [],
    "expenses": [],
    "payments": []
}

and check payments again:

Response: HTTP 200, application/json (Hide)
GET /payments

Response:

1
[]