What this is
The AI-CORE API Gateway is the single public entry point to AI-CORE job services (metadata extraction, PDF anonymization, …). You authenticate with an API key, declare who is calling via identity headers, and submit jobs over plain HTTPS — either synchronously (for bounded tasks) or asynchronously with a callback webhook.
Interactive API reference: Swagger UI (try-it-out, Authorize button) · ReDoc (readable reference) · machine-readable OpenAPI schema.
Authentication
Every call to /api/v1/… requires three headers:
| Header | Required | Meaning |
|---|---|---|
X-Api-Key | yes | The API key issued by the gateway admin. 401 if missing, unknown, disabled or expired. Identifies your consumer system (baked into the key at issue time). |
X-Tenant | yes | Tenant on whose behalf the call is made. 400 if missing. Job results are only visible to this tenant. |
X-User | yes | End user on whose behalf the call is made. 400 if missing. |
Every identified call is recorded in the key's usage history (system, tenant, user, route, status, duration) — including denied attempts. Keys are issued per system with per-service permissions via the admin console (master key required) — ask the gateway administrator for one.
Quickstart
Synchronous call — metadata extraction
No callback_url: the response body is the service's native result (may take up to ~3 minutes).
curl -sS https://<gateway-host>/api/v1/metadata_extraction \
--max-time 220 \
-H "X-Api-Key: $API_KEY" \
-H "X-Tenant: mytenant" -H "X-User: some.user" \
-H "Content-Type: application/json" \
-d '{
"doc_reference": "https://example.org/documents/decreto.pdf",
"document_kind": "auto",
"max_pages": 10
}'
Asynchronous call — PDF anonymization
callback_url set: you get 202 {"job_id"} at once; the result is POSTed to your webhook. (Omit it to poll instead — see fire-and-poll.)
curl -sS https://<gateway-host>/api/v1/pdf_anonymization \
-H "X-Api-Key: $API_KEY" \
-H "X-Tenant: mytenant" -H "X-User: some.user" \
-H "Content-Type: application/json" \
-d '{
"doc_reference": "https://example.org/documents/referto.pdf",
"callback_url": "https://mysystem.example.org/webhooks/aicore"
}'
PDFs travel either by reference (doc_reference: a URL) or inline (doc_content: base64) — exactly one of the two must be set.
sync Sync-emulation flow
Available on bounded tasks only (currently metadata_extraction).
Omit callback_url and the gateway parks your request while the job runs:
- 200 with the service's native response — the normal case, within the 180 s park budget.
- Business errors keep their original HTTP status (
ResponseErrorbody; job timeout → 504). - If the budget expires (cold start, queue, long job) the call degrades to
202
{"job_id"}with aLocationheader → poll for the result.
async Async + callback flow
Set callback_url (optional on every route) and the submit returns
202 {"job_id"} immediately. When the job reaches a terminal
state, the platform POSTs this envelope to your webhook:
POST <callback_url>
Content-Type: application/json
{
"job_id": "1f0c1e0a-7b6e-4b9e-9b1a-2a7c8d9e0f11",
"service": "pdf-anonymization",
"task": "pdf_anonymization",
"status": "ok", // "ok" | "error"
"response": { ... }, // the service's native response when status=ok
"error": null, // error message when status=error
"error_code": null // business HTTP status when status=error (e.g. 504 timeout)
}
- A terminal callback is always delivered — business errors, timeouts and poison payloads all produce an error envelope, never silence.
- Undeliverable callbacks are retried with backoff, then dead-lettered for operator replay — answer with a 2xx quickly (ack first, process after).
- Your webhook must be reachable from the platform over HTTPS.
No webhook? Fire-and-poll
Omitting callback_url works on every route. On long tasks
(pdf_anonymization) the submit still answers 202
{"job_id"} immediately, with a Location header pointing at the
poll endpoint. Mind the windows: the job stays pollable as
pending while it runs, and the terminal result stays available for
600 s after completion — poll promptly, or prefer a callback for
unattended integrations.
Polling
For jobs submitted without a callback (fire-and-poll, or a sync call that degraded to 202):
curl -sS https://<gateway-host>/api/v1/jobs/$JOB_ID/result \
-H "X-Api-Key: $API_KEY" \
-H "X-Tenant: mytenant" -H "X-User: some.user"
| Status | Meaning |
|---|---|
| 200 | Terminal result — same envelope as the callback (status is ok or error). |
| 202 | Still pending — poll again (suggested interval: 2–5 s; for long jobs like pdf_anonymization, 5–15 s). |
| 404 | Unknown job_id, or the result expired — it stays available 600 s after completion. Jobs submitted by another tenant also read as 404. |
| 403 | Your key is not scoped for the polled job's task. |
Idempotency & retries
- Polls are always safe to retry —
GET, no side effects. - Do not blind-retry a submit that already returned 202. Each
POSTmints a newjob_id, so retrying a successful submit runs the job twice. Retry a submit only on a network error or 5xx where nojob_idreached you. - Transport-level retries of a single submit are deduplicated inside the platform — a job is never
dispatched twice for one accepted
job_id.
Error model
Two body shapes, depending on which layer rejects the call:
| Shape | Produced by | Statuses |
|---|---|---|
{"detail": "…"} |
Authentication / validation layer | 401 bad key · 403 system mismatch or missing scope · 400 missing identity headers · 422 request body validation |
{"code": int, "message": "…"} |
Job layer (ResponseError) |
404 unknown/expired job · 502 job failed · 503 orchestrator disabled · 504 job timeout |
Sync business errors propagate the service's own HTTP status (error_code parity with the callback envelope).
Permissions (scopes)
Keys carry a list of allowed services: ["*"] (all) or an explicit subset
(e.g. ["metadata_extraction"]). Calling a route outside your key's scopes returns
403 "API key not authorized for service '…'".
The jobs poll route checks the scope of the polled job's task.
Services
| Endpoint | Mode | Notes |
|---|---|---|
POST /api/v1/metadata_extraction |
sync or async | Extracts structured metadata (title, dates, issuing body, act number, …) from the leading pages of a PDF. Bounded task (~2 min typical) → sync-emulation allowed. max_pages 1–30, taxonomy hint via document_kind, optional output language. |
POST /api/v1/pdf_anonymization |
async — callback or poll | Redacts personal data from a PDF (returns the anonymized PDF as base64 + stats). Jobs can run ~15 min, so the submit always answers 202: result via callback_url, or poll the Location header without one (result window 600 s). Options: custom category prompt, checksum-validated Italian fiscal-code/VAT detection, embedded-file handling, metadata scrubbing. |
GET /api/v1/jobs/{job_id}/result |
— | Poll a parked job (see Polling). |
Full request/response schemas with field-level docs and examples: Swagger UI · ReDoc.