> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parzo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Extract Invoice

> Submit a PDF invoice for structured data extraction.

## POST /v1/extract/invoice

Submit a PDF invoice for extraction. Returns a `job_id` immediately — processing happens asynchronously in the background.

### Request

**Headers**

| Header      | Required | Description        |
| ----------- | -------- | ------------------ |
| `X-API-Key` | Yes      | Your Parzo API key |

**Body — `multipart/form-data`**

| Field    | Type   | Required | Description                                          |
| -------- | ------ | -------- | ---------------------------------------------------- |
| `file`   | PDF    | Yes      | Invoice PDF, max 50MB                                |
| `locale` | string | No       | Language hint: `it`, `en`, `de`, `fr`. Default: `it` |

**Alternative — `application/json`**

| Field         | Type   | Required | Description                |
| ------------- | ------ | -------- | -------------------------- |
| `file_base64` | string | Yes      | Base64-encoded PDF content |
| `locale`      | string | No       | Language hint              |

### Example request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.parzo.dev/v1/extract/invoice \
    -H "X-API-Key: inv_your_key_here" \
    -F "file=@invoice.pdf" \
    -F "locale=it"
  ```

  ```python Python theme={null}
  import requests

  with open("invoice.pdf", "rb") as f:
      response = requests.post(
          "https://api.parzo.dev/v1/extract/invoice",
          headers={"X-API-Key": "inv_your_key_here"},
          files={"file": f},
          data={"locale": "it"}
      )

  print(response.json())
  ```

  ```javascript Node.js theme={null}
  import FormData from "form-data";
  import fs from "fs";
  import fetch from "node-fetch";

  const form = new FormData();
  form.append("file", fs.createReadStream("invoice.pdf"));
  form.append("locale", "it");

  const response = await fetch("https://api.parzo.dev/v1/extract/invoice", {
    method: "POST",
    headers: {
      "X-API-Key": "inv_your_key_here",
      ...form.getHeaders()
    },
    body: form,
  });

  console.log(await response.json());
  ```
</CodeGroup>

### Response `202 Accepted`

```json theme={null}
{
  "job_id": "3419ae1e-93c3-48a1-95ac-833c390f9916",
  "status": "pending",
  "estimated_seconds": 15,
  "poll_url": "/v1/jobs/3419ae1e-93c3-48a1-95ac-833c390f9916",
  "webhook_configured": false,
  "quota_remaining": 99
}
```

### Output JSON schema

When the job completes, the full extracted data is available via `GET /v1/jobs/:id`:

```json theme={null}
{
  "vendor": {
    "name": "Acme Srl",
    "vat_number": "IT12345678903",
    "fiscal_code": null,
    "address": "Via Roma 1",
    "city": "Milano",
    "zip_code": "20100",
    "country": "IT",
    "email": "billing@acme.it",
    "phone": null,
    "iban": null,
    "sdi_code": null
  },
  "buyer": {
    "name": "Cliente SpA",
    "vat_number": "IT98765432109",
    "fiscal_code": null,
    "address": "Via Milano 5",
    "city": "Roma",
    "zip_code": "00100",
    "country": "IT",
    "email": null
  },
  "invoice": {
    "number": "FT-2026-001",
    "date": "2026-04-01",
    "due_date": "2026-05-01",
    "type": "invoice",
    "currency": "EUR",
    "payment_terms": "30gg d.f.",
    "payment_method": "bank_transfer",
    "po_number": null
  },
  "financials": {
    "subtotal": 1000.00,
    "tax_rate": 22,
    "tax_amount": 220.00,
    "total": 1220.00,
    "discount": null,
    "stamp_duty": null,
    "withholding_tax": null,
    "currency": "EUR"
  },
  "line_items": [
    {
      "description": "Servizio consulenza",
      "quantity": 10,
      "unit": "ore",
      "unit_price": 100.00,
      "amount": 1000.00,
      "tax_rate": 22,
      "discount_pct": null
    }
  ],
  "validation": {
    "confidence": 0.95,
    "is_scanned": false,
    "warnings": []
  }
}
```

### Error responses

| Status | Description                |
| ------ | -------------------------- |
| `401`  | Missing or invalid API key |
| `413`  | File exceeds 50MB limit    |
| `422`  | File is not a valid PDF    |
| `429`  | Monthly quota exhausted    |

<Note>
  Use `GET /v1/jobs/:id` to retrieve the result once processing is complete. Typical processing time is 5-30 seconds.
</Note>
