Document Intelligence API

What it is
A backend service that takes a PDF and returns structured JSON. It renders each page with pdf2image, sends it to GPT-4o Vision, and stores the extracted payload against a job record so a front end can poll for the result.
The problem it solves
Calling a vision model on a document is slow and occasionally fails. If you do it inside the request, the HTTP thread blocks for the length of an external API call you do not control, and a transient error loses the user’s upload. Most naive versions of this service are one endpoint that hangs and then 500s.
How I handled it
- Celery and Redis. Upload returns
202and a job ID immediately. The model call happens on a worker, so nothing blocks. - SHA-256 deduplication. Every file is hashed on arrival. Re-uploading a document that has already been processed returns the stored result instead of paying OpenAI a second time. On a document pipeline this is the difference between a viable cost model and a bad one.
- Exponential backoff. Model calls retry on transient failures rather than surfacing a stack trace to the caller.
- Explicit job states.
queued,processing,done,failed. The front end polls every two seconds until it reaches a terminal state, so a failure is a state the UI can render rather than a hang.
The API
POST /documents/upload: start an extraction, returns a job IDGET /documents/{job_id}/status: current stateGET /documents/{job_id}/result: the extracted JSONGET /documents/: paginated historyDELETE /documents/{job_id}: remove a job

What I would change
The deduplication key is the file hash alone, which means the same document extracted against a different schema would wrongly hit the cache. If this went to production the key would need to include the extraction schema version. It has not bitten me yet, which is exactly why it is worth writing down.