INV-01 | List invoices | GET /invoices | 200 | 200 | 256 ms | Pass |
INV-02 | Pagination: page size and next cursor | GET /invoices?limit=20 | 20 + cursor | 20 + cursor | 309 ms | Pass |
INV-03 | Pagination: last page has no cursor | GET /invoices?cursor=… | no cursor | no cursor | 132 ms | Pass |
INV-04 | Limit above 100 rejected | GET /invoices?limit=500 | 400 | 400 | 185 ms | Pass |
INV-05 | Sort by creation date, descending | GET /invoices?sort=-createdAt | sorted | sorted | 238 ms | Pass |
INV-06 | Filter by status | GET /invoices?status=… | matching items only | matching items only | 291 ms | Pass |
INV-07 | Filter by customerId | GET /invoices?customerId=… | matching items only | matching items only | 344 ms | Pass |
INV-08 | Filter by issuedFrom | GET /invoices?issuedFrom=… | matching items only | matching items only | 167 ms | Pass |
INV-09 | Filter by issuedTo | GET /invoices?issuedTo=… | matching items only | matching items only | 220 ms | Pass |
INV-10 | Filter by dueFrom | GET /invoices?dueFrom=… | matching items only | matching items only | 273 ms | Pass |
INV-11 | Filter by currency | GET /invoices?currency=… | matching items only | matching items only | 326 ms | Pass |
INV-12 | Filter by number | GET /invoices?number=… | matching items only | matching items only | 149 ms | Pass |
INV-13 | Get by id | GET /invoices/{id} | 200 | 200 | 202 ms | Pass |
INV-14 | Unknown id | GET /invoices/{id} | 404 | 404 | 255 ms | Pass |
INV-15 | Other tenant's id | GET /invoices/{id} | 404 | 404 | 308 ms | Pass |
INV-16 | Response matches OpenAPI schema | GET /invoices/{id} | valid | valid | 131 ms | Pass |
INV-17 | Create (dry run) | POST /invoices?dryRun=true | 200 | 200 | 184 ms | Pass |
INV-18 | Rejects negative quantity | POST /invoices?dryRun=true | 400 | 400 | 237 ms | Pass |
INV-19 | Rejects unknown currency | POST /invoices?dryRun=true | 400 | 400 | 290 ms | Pass |
INV-20 | Rejects missing customer | POST /invoices?dryRun=true | 400 | 400 | 343 ms | Pass |
INV-21 | Rejects due date before issue date | POST /invoices?dryRun=true | 400 | 400 | 166 ms | Pass |
INV-22 | Rejects more than 500 lines | POST /invoices?dryRun=true | 400 | 400 | 219 ms | Pass |
INV-23 | Rejects discount over 100% | POST /invoices?dryRun=true | 400 | 400 | 272 ms | Pass |
INV-24 | Missing scope rejected | GET /invoices | 403 | 403 | 325 ms | Pass |
INV-25 | Invalid status value rejected · ACME-513 | GET /invoices?status=payed | 400 | 200 | 148 ms | Fail |
INV-26 | Every listed invoice can be retrieved · ACME-512 | GET /invoices → /invoices/{id} | 200 | 404 for 5 of 20 | 201 ms | Fail |
INV-27 | Totals computed correctly (net, VAT, gross) | POST /invoices?dryRun=true | match | match | 254 ms | Pass |
INV-28 | Rounding: 3 × €0.333 at 23% VAT | POST /invoices?dryRun=true | €1.23 gross | €1.23 gross | 307 ms | Pass |
INV-29 | Invoice PDF download | GET /invoices/{id}/pdf | 200 application/pdf | 200 application/pdf | 770 ms | Pass |
INV-30 | PDF of another tenant's invoice | GET /invoices/{id}/pdf | 404 | 404 | 823 ms | Pass |
INV-31 | totalItems equals the sum of pages | GET /invoices | equal | equal | 236 ms | Pass |
INV-32 | Numbering is sequential per series | GET /invoices?series=2026 | no gaps | no gaps | 289 ms | Pass |
INV-33 | Send invoice (dry run) | POST /invoices/{id}/send?dryRun=true | 202 | 202 | 342 ms | Pass |
INV-34 | Cancelled invoice cannot be sent | POST /invoices/{id}/send?dryRun=true | 409 | 409 | 165 ms | Pass |
INV-35 | Peppol e-invoice export (feature flag off on staging) | GET /invoices/{id}/ubl | 200 | – | – | Skipped |