AgilePixel is the eyesight service: give it a document, a utility bill, a scan or a photo taken with a phone, and it returns the fields as JSON, each with its own confidence. It runs on our own machines, in Europe: no document is forwarded to third parties.
Three capabilities, one contract:
Formats: PDFs with a text layer, scanned PDFs, scanner images and phone photos (perspective, shadows, folds, compression). The photo is the hard exam, and it is the one we measure ourselves against.
Every field goes through a deterministic validator before it leaves: POD and PDR
energy identifiers, Italian tax code and VAT number with their check digit, IBAN with mod 97,
coherent billing period dates, the sum of bands F1+F2+F3 equal to the total, taxable amount
plus VAT equal to the amount due. A field that fails comes back as null, its name goes
into the da_verificare list (to be checked) and motivi (reasons) says which
check it failed: it never comes back as a plausible wrong value. In an automated process, the error that costs most is the one reported as certain.
Callers need not know where the engine runs, nor change anything when the engines become two or ten.
One licence per tenant, with plan, scopes, monthly quota, per-minute limit and expiry. API keys live under the licence: they are issued, rotated and revoked from the tenant console without touching the licence.
price on request
price on request
price on request
The quotas and limits above are the ones the service actually enforces, not a brochure. Price on
request applies to all three plans: it is agreed with Agile together with the expected volume
and the service level. Past the quota the licence does not break: it answers
quota_superata, with the month's count in dettaglio.
The per-minute limit is counted per clock minute, not over a sliding
window: across a minute boundary up to twice the stated number can go through within a
few seconds.
The per-minute limit is a ceiling on you, not a reserved seat.
The work seats — how many documents the service keeps in progress and how many it keeps waiting —
belong to the service and are shared with every other customer: the queue does not
know whose job it is. So coda_piena (503) can reach you
because of another customer's traffic, with your quota untouched and on your
first request of the minute. It
is not a fault and it costs you no quota: it is a 503 and you retry, with a doubling wait. Measured
live on 3/10/2026 with two real customers: the second one, which had made a single
request, got coda_piena in 55 ms without consuming quota, and the door stayed shut for
18.6 seconds, the time of the jobs ahead of it. How much queue each customer is entitled to is still
an open choice: when there is a number, this line will say it. Details in
API.md, limits and rules.
The contract is versioned and published: /openapi.json (OpenAPI), the
integrator's guide is in API.md, and the interactive pages live at
/documentazione. Errors carry a stable name (for
instance chiave_sconosciuta, quota_superata,
nessun_motore_disponibile): you program against the name, not against the prose.
curl -X POST https://api.agilepixel.agile.software/v1/documenti/estrai \
-H "Authorization: Bearer <key>" \
-F "documento=@bill.pdf" \
-F "tipo=bolletta_luce"
{
"lavoro": "lav_9f2c41d7a3b05e62",
"motore": "motore-1",
"pagine": 2,
"ms": 1840,
"ms_fronte": 1902,
"campi": {
"pod": "IT001E12345678",
"periodo_dal": "2026-07-01",
"periodo_al": "2026-08-31",
"consumo_totale": 412.0,
"totale_da_pagare": 118.34,
"potenza_impegnata_kw": null
},
"confidenze": {
"pod": 0.99,
"periodo_dal": 0.98,
"periodo_al": 0.98,
"consumo_totale": 0.97,
"totale_da_pagare": 0.96,
"potenza_impegnata_kw": null
},
"da_verificare": ["potenza_impegnata_kw"],
"motivi": { "potenza_impegnata_kw": ["potenza_implausibile"] }
}
The last field is the point: the engine had read a contracted power impossible for a domestic
supply, so the service zeroes it and says so instead of handing over a
plausible wrong number. The same call on /v1/documenti/leggi returns the text, on
/v1/immagini/descrivi the description.
The tenant governs its own keys at /console/licenze: issue, rotation with a
24-hour grace period on the old key (time to update your systems without a minute of
downtime) and immediate revocation. Consumption is read from
/console/licenze/{id}/uso, month by month, in pages and images.
We measure ourselves on a two-arm bench: the same pages go through our engine and through the market leader, and the fields are compared against ground truth. The cells below are filled by the bench: no quality figure is hand-written on this page, and while a measurement does not exist the cell says «not measured yet». The yardstick and the targets are public in our target document; figures published by third-party vendors are not passed off as our own measurements.
| Metric | AgilePixel | Leader |
|---|---|---|
| Critical fields exact — digital PDFs | not measured yet | not measured yet |
| Critical fields exact — scans and photos | not measured yet | not measured yet |
| «Confidently wrong» errors | not measured yet | not measured yet |
| Fields returned as to be checked | not measured yet | not measured yet |
| POD, PDR, tax code, VAT number (check digit) | not measured yet | not measured yet |
| Character error rate — PDFs | not measured yet | not measured yet |
| Character error rate — photos | not measured yet | not measured yet |
| F1 F2 F3 band table reconstructed | not measured yet | not measured yet |
| Latency per page, ninety-fifth percentile | not measured yet | not measured yet |
| Cost per thousand pages | not measured yet | not measured yet |
How to read it: synthetic pages only, never customer documents; ground truth is generated together with the pages, so it is exact to the cent; zero tolerance on amounts; the leader's arm runs on the same pages in the same round. When a row changes, it changes because the bench ran again.
The service is answering, at reduced capacity.
The status above is the real one, read at the moment this page was composed, from the very same /health our own systems use. When no engine is ready the service says so: there is no courtesy «all good» here.
Leave us two lines: we answer at the address you give, with the plan that fits your volume and the price. We ask only for what is needed to answer.
The form works without JavaScript. The service answers with a request number: keep it, it is the reference for your case. There is a per-network-address rate limit, to keep the bots out.