BL / docs /api-spec.md
youssefboutaleb's picture
Clean up dead code and add client CRM integration architecture guide
4124165
|
Raw History Blame Contribute Delete
3.76 kB
# Delivery Note OCR API Specification
Base URL: `https://<backend-host>`
The API is frontend-agnostic. Web apps, mobile apps, CLI tools, automations, and
the Hugging Face Space all consume the same HTTP contract.
## Authentication and Secrets
This backend currently protects the upstream Mistral credential by keeping it on
the server side as `MISTRAL_API_KEY`. Clients never send the provider key.
Add caller authentication at the API gateway or with a FastAPI dependency before
public internet exposure.
## Endpoints
| Method | Path | Purpose |
| --- | --- | --- |
| `GET` | `/health` | Liveness and provider configuration status |
| `GET` | `/v1/schema` | JSON schema used for structured extraction |
| `POST` | `/v1/ocr` | Multipart image upload OCR/inference |
| `POST` | `/v1/ocr/base64` | JSON base64 OCR/inference for non-browser clients |
Interactive OpenAPI docs are available at `/docs` when the backend is running.
## `POST /v1/ocr`
Request: `multipart/form-data`
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `file` | file | yes | `.jpg`, `.jpeg`, `.png`, or `.webp` image |
| `repair` | query bool | no | Defaults to `true`; applies deterministic repair |
| `validate` | query bool | no | Defaults to `true`; returns validation warnings |
Example:
```bash
curl -X POST \
-F "file=@scan.jpg" \
"http://localhost:8000/v1/ocr?repair=true&validate=true"
```
## `POST /v1/ocr/base64`
Request body:
```json
{
"filename": "scan.jpg",
"content_type": "image/jpeg",
"image_base64": "<base64-or-data-url>",
"repair": true,
"validate": true
}
```
## Response Shape
```json
{
"filename": "scan.jpg",
"content_type": "image/jpeg",
"checksum_md5": "string",
"annotation": {
"delivery_note_full": {"value": "111565/2026", "confidence": 0.99},
"products": []
},
"schema_valid": true,
"schema_errors": [],
"validation_warnings": [],
"repairs": [
{
"path": "products[0].pharmacist_price_ttc",
"original": 7.89,
"value": 5.35,
"reason": "derived from line_total_ttc / quantity"
}
],
"raw_provider_response": {},
"parse_error": null,
"metadata": {
"provider": "mistral",
"model": "mistral-ocr-latest",
"retry_count": 0,
"critical_retry_reasons": [],
"retry_reasons": [],
"duration_ms": 1234
}
}
```
Field notes:
- `annotation` is the frontend-friendly structured extraction. Every leaf is a
`{value, confidence}` object; `value` may be `null` when a field is absent. The
annotation is always schema-clean — repair provenance never appears inside it.
- `schema_valid` / `schema_errors` report whether the (post-repair) annotation
validates against `/v1/schema`. Each error carries `path`, `message`, and
`validator`.
- `repairs` are structured, deterministic corrections applied server-side. Each
record carries `path`, `original` (the OCR reading), `value` (the corrected
number), and `reason` (the accounting identity used).
- `validation_warnings` are non-blocking consistency notes (row-count, line
arithmetic, total reconciliation) for human review.
- `raw_provider_response` preserves the original OCR provider response for
debugging and replay.
Entity resolution against a client database (supplier / pharmacy / product
matching) is **not** performed here; it is the CRM's responsibility. See
`docs/client-integration-guide.md`.
## Deployment
Backend:
```bash
cp .env.example .env
# edit MISTRAL_API_KEY in .env
docker compose up --build
```
Hugging Face Space:
1. Create a Gradio Space.
2. Deploy the Gradio UI (`app.py`) with its dependencies.
3. Set `BACKEND_API_URL` to the deployed backend URL.
No backend code changes are required when the frontend URL or hosting platform
changes.