Send a file and read it
Send a PDF, an image or an e-invoice, wait until Ocost has read it, then read its documents. One file can hold several documents. A scan of three invoices is one file with three documents.
Send the file
Post the file as multipart/form-data to POST /public/v1/files. The key needs the scope documents:write.
curl -sS https://api.ocost.io/public/v1/files \
-H "Authorization: Bearer $OCOST_KEY" \
-F "file=@scan.pdf" -F "name=scan.pdf" -F "external_ref=account.move,42"| Field | Meaning |
|---|---|
file | Required. A PDF, an image (JPEG, PNG, TIFF, WebP) or an e-invoice's XML (XRechnung, UBL, CII), up to 25 MB. Archives aren't read. |
name | The file name. Without it, Ocost takes the upload's. |
external_ref | Your own id, up to 200 characters, given back with the file. |
A new file answers 202 Accepted with "status": "received", and reading starts at once:
{ "id": "01a1b08c-6e3a-7562-8f4a-7924722667b1", "name": "scan.pdf", "status": "received", "external_ref": "account.move,42", "documents": [] }Every answer carries X-Ocost-Documents-Left, the documents your plan has left this month. Limits and errors lists the refusals.
Send it again safely
Ocost knows a file by the SHA-256 of its bytes, not by its name. The same bytes again answer 200 OK with that file as it is now. Ocost doesn't read or count it again, and the file keeps its first external_ref. So after a timeout, send the file again.
Wait until it is read
Ask for the file with GET /public/v1/files/{file_id}, scope documents:read. Poll every 2 to 3 seconds for half a minute, then every 10 to 30 seconds. Most PDFs take under a minute, long ones a few.
def wait_for(session, file_id, timeout=300):
started = time.monotonic()
while time.monotonic() - started < timeout:
file = session.get(f"{API}/files/{file_id}", timeout=15).json()
if file["status"] not in ("received", "reading"):
return file
time.sleep(3 if time.monotonic() - started < 30 else 15)
return fileThe file is done when its status is read, not_read or failed. Statuses and reasons explains each. For many files at once, stay in sync instead of polling each one.
Read its documents
A read file lists its documents in documents, each with its id, kind, number and pages. GET /public/v1/files/{file_id}/document answers the first one. GET /public/v1/documents/{document_id} answers any of them.
curl -sS https://api.ocost.io/public/v1/documents/01a1b08c-7aa1-7b52-9d4e-2f1f1c0c4f11 \
-H "Authorization: Bearer $OCOST_KEY"The answer is the document as ocost.document.v1. The document shows a whole one and explains every field.
Get the original
GET /public/v1/files/{file_id}/content answers the bytes as you sent them.
curl -sS -o scan.pdf https://api.ocost.io/public/v1/files/$FILE_ID/content \
-H "Authorization: Bearer $OCOST_KEY"Delete a file
DELETE /public/v1/files/{file_id} erases the file at once and for good. That includes its documents, what was read, its search index and the original. The key needs documents:write.
curl -sS -X DELETE https://api.ocost.io/public/v1/files/$FILE_ID \
-H "Authorization: Bearer $OCOST_KEY"Ocost answers 204, and 404 from then on. It refuses in two cases:
| Answer | What to do |
|---|---|
409 urn:ocost:file:reading | The file is being read. Try again later. |
409 urn:ocost:file:linked | Ocost still needs the file, for a booked invoice, a bank statement, an open question or a project. detail says which. Delete it in Ocost once nothing needs it. |