DEV Community

OnePassApps
OnePassApps

Posted on

The Invoice Maker's Draft JSON: 669 Bytes, Three Refusals, and a 1 MiB Limit Measured

I work on OnePassApps, the team behind app.onepassapps.com. This post measures a part of the Invoice Maker that no channel of ours has touched yet: the draft JSON the app writes when you press "Export draft JSON", and the gate it applies to a file you hand back to it with "Import draft JSON".

Everything below was measured on 10 November 2026 in the live build, signed out, in one browser on our own desktop. Facts file: content/invoice-import-contract-2026-11-10.json. Tools: tools/invoice-import-probe2-2026-11-10.js through tools/invoice-import-probe9-2026-11-10.js.

What the app writes

Fill in a client, one line and a tax rate, then press "Export draft JSON" and the browser writes a file named after the invoice number - invoice-INV-2026-042.json in my run, 669 bytes, SHA-256 27761e213c90f6c2cdf161dcdae3f11dffdbb22a9360ceaff1eadff8f85142e3. The panel says "Editable draft downloaded as JSON, including any unfinished fields."

The file is one object with a version of 1 and an invoice object inside it:

{
  "version": 1,
  "invoice": {
    "docType": "invoice",
    "paper": "a4",
    "seller": { "name": "", "address": "", "email": "", "taxId": "" },
    "client": { "name": "Northgate Studio", "address": "", "email": "" },
    "number": "INV-2026-042",
    "issueDate": "2026-11-10",
    "dueMode": "terms",
    "termsDays": "30",
    "dueDate": "",
    "currency": "GBP",
    "items": [
      { "description": "Design work", "quantity": "2", "unitPrice": "150", "taxRate": "20" }
    ],
    "discountKind": "none",
    "discountValue": "",
    "notes": "",
    "payment": ""
  }
}
Enter fullscreen mode Exit fullscreen mode

Two details are worth stopping on. Every number is a string - quantity "2", unit price "150", tax rate "20" - and a field you never filled in is an empty string, not null. The panel says so itself: "Nothing is saved automatically. Export a draft (up to 1 MiB) to keep your work."

Three ways the import says no

I fed the file input nine files, one at a time, and read the panel after each. It answers with one of three messages, and in every failing case the second line is "Import failed. Your current draft was kept."

A file that is not JSON at all gets "This is not a valid JSON file."

A file that parses but is not the shape the app writes gets "This file is not a supported Invoice Maker export. Invalid input". That covers a JSON object with the wrong keys, a JSON array, and a file whose own keys are fine but whose version is not 1.

A file that is too big gets "Choose an invoice JSON file no larger than 1 MiB."

In every one of the nine attempts the draft on screen was untouched afterwards - the client name, the subtotal and the total were exactly what they were before the attempt.

The 1 MiB line is on the bytes

I built three files of exactly 1,048,575, exactly 1,048,576 and exactly 1,048,577 bytes. The 1,048,577-byte file draws the size message. The other two pass the size check and fall through to the shape check, where they draw "This file is not a supported Invoice Maker export. Invalid input" because their contents are a padded object rather than an export. So the limit is on the file's bytes, not on what it parses to, and a file of exactly 1,048,576 bytes is inside it.

The shape check is strict

Six small changes to a valid export, one at a time, and every one of them is refused with "This file is not a supported Invoice Maker export. Invalid input".

Raising "version" to 2. Adding an unknown key at the top level and another inside "invoice". Removing the "invoice" object entirely. Writing quantity and unit price as JSON numbers instead of the strings the app itself writes. And handing the app a JSON array.

The file input declares accept=".json,application/json", but the extension is not what the gate checks. When a file named .txt was fed to the input directly, the app read its contents and answered with the shape message, not a type message.

The one thing I did not resolve

When I handed the app a valid export - the very file it had just written - the panel answered "Cancelled. Your current draft was kept." and the draft on screen was unchanged. I looked for a confirmation step and did not find one: there is no dialog element, no visible modal and no call to a confirmation function in the page, and the file input fired only its input and change events. I drove the file input from the browser's own file chooser, so I am reporting what I saw and I am not claiming what a person choosing the same file in their operating system's own file dialog would see.

How to use it

Export a draft, edit the JSON, import it back, and your file has to clear three checks: it must be JSON, it must be the shape the app writes with version 1 and string values, and it must be 1 MiB or smaller. If it clears all three and your draft still does not come back, that is the case I could not settle here.

The Invoice Maker is at https://app.onepassapps.com/apps/invoice-maker?utm_source=devto&utm_medium=post&utm_campaign=invoice-import-contract&utm_content=invoice-maker-link and its guide is at https://app.onepassapps.com/guides/invoice-maker?utm_source=devto&utm_medium=post&utm_campaign=invoice-import-contract&utm_content=guides-link

Limits of this measurement

One build, one day, one signed-out session, one browser. Nine import attempts and one export, all in the live app at /apps/invoice-maker. I did not print or save a PDF, and I did not check the import path on any other build or in any other browser.

Top comments (0)