Response codes
| Code | Meaning | Retry? |
|---|---|---|
200 | The request was understood. Check the per-piece outcomes | No |
400 | The package or the JSON was rejected before any piece was read | Not without fixing it |
401 | The key is missing, invalid or revoked | No |
5xx | Our problem | Yes — keep the file and try again |
The one that catches people
200 does not mean everything worked.
Business rejections live in the per-piece outcomes, not in the HTTP status. A file where all three pieces were refused still returns 200, because the request itself was understood and answered correctly.
So the check is never just if (status == 200) ok(). It is:
status == 200 → read totais.recusadas and the itens list
We chose this over returning 400 for a partly-failed file because the file is not atomic: with 97 pieces created and 3 refused, neither "success" nor "failure" is true, and only the item list says what actually happened.
400 versus a refused piece
Both mean something is wrong with the data, but they happen at different moments and need different handling.
400 is the whole package being rejected before any row is read — a ZIP without a spreadsheet at its root, an unsupported extension, an unreadable spreadsheet. The body is plain text, with no item list, because no item ever existed.
REJECTED inside a 200 is one row that failed while the others went in. You fix that row and resend it alone.
5xx and what not to do
A 5xx means the content was never the problem. Network, database, a bug on our side.
Keep the file and retry. Do not move it to an error folder, do not mark the order as failed, and do not require someone to re-export it from your ERP. The same bytes will work once we are back.
This is exactly what the Mover.Glass Connector does at your site: transport failures leave the package in the input folder for the next cycle, and only a content rejection moves it aside. If you are writing your own client, that distinction is the one worth copying.