Skip to main content
When your platform receives bills or purchase invoices, pushing them directly into Qonto saves your team from re-uploading files manually and keeps expense tracking centralised. In this guide, we will upload a supplier invoice file via the bulk endpoint and verify the response to confirm it was ingested successfully.
Example: A procurement platform forwards vendor invoices received by email directly into Qonto as soon as they arrive, ready for approval without any manual upload.
Prerequisites:
  • A PDF invoice file ready to upload (max 10 MB).
  • Scope: supplier_invoice.write
1

Upload the invoice file

Send the PDF using POST /v2/supplier_invoices/bulk. You can upload the raw file binary or reference an existing attachment by its ID.Endpoint: Create supplier invoices
OAuth scope required: supplier_invoice.write.
Maximum 20 invoices per request. Each invoice requires a unique idempotency_key (UUID recommended) to prevent duplicate uploads. See Idempotent requests.
This endpoint returns HTTP 200 even when individual invoices fail to process. Always inspect the errors array in the response body for each invoice when you receive a 200.Authentication failures still return 401, permission issues return 403, and server-side errors return 500.
You must provide either file or attachment_id for each invoice, not both. Including both will result in an error.
import uuid
import requests

BASE_URL = "https://thirdparty.qonto.com/v2"
headers = {"Authorization": "Bearer {your_access_token}"}

with open("./invoice.pdf", "rb") as f:
    response = requests.post(
        f"{BASE_URL}/supplier_invoices/bulk",
        headers=headers,
        data={
            "supplier_invoices[][idempotency_key]": str(uuid.uuid4()),
            "source": "integration",
        },
        files={
            "supplier_invoices[][file]": ("invoice.pdf", f, "application/pdf"),
        },
    )

# Always 200 — check errors in body
result = response.json()
2

Check the response for errors

Inspect the response to confirm each invoice was processed successfully.
supplier_invoices = result.get("supplier_invoices", [])

for invoice in supplier_invoices:
    errors = invoice.get("errors", [])
    if errors:
        print(f"Failed: {errors}")
    else:
        print(f"Uploaded successfully: {invoice.get('id')}")
Common error codes to handle:
CodeCause
invalidFile too large or unsupported content type
requiredMissing idempotency_key
limit_reachedMore than 20 invoices in the request
internal_server_errorProcessing failed on Qonto’s side
Example output:
[Step 1] POST /supplier_invoices/bulk  (file: sample_invoice.pdf)
  HTTP status: 200

[Step 2] Check response
  Uploaded successfully: 019d0705-xxxx-xxxx-xxxx-xxxxxxxxxxxx
We now have the supplier invoice uploaded to Qonto and queued for review. It will appear in the “Supplier invoices” section of the Qonto app with status to_review.