Download icon
Script icon
ChatCompletion icon
Queries icon
SlackIncomingWebhook icon

AI Document Data Extraction: Parse PDFs and Web Pages into Structured JSON with OpenAI

Extract structured data from PDFs and web pages with Kestra and OpenAI GPT-4o. Parse documents into JSON fields and store results in PostgreSQL and Slack.

Categories
AIData

Extract structured data from unstructured documents using OpenAI GPT-4o and a configurable JSON schema. This blueprint downloads a document from any URL (PDF, HTML page, or plain text), parses readable text with format detection, sends it to GPT-4o to pull out the exact fields you define at runtime, and persists the results to PostgreSQL and Slack. It turns invoices, contracts, receipts, reports, and forms into queryable, auditable data without standing up a dedicated document processing service or hand coding a parser per document type.

How it works

  1. The download_document task (io.kestra.plugin.core.http.Download) fetches the file from the document_url input over HTTP.
  2. The extract_text task (io.kestra.plugin.scripts.python.Script) inspects the file header and extracts text accordingly: PDFs via PyPDF2, HTML and text via BeautifulSoup4 (stripping script, style, nav, and footer tags). It truncates content to 8000 characters to stay within token limits and reports a character count.
  3. The extract_structured_data task (io.kestra.plugin.openai.ChatCompletion) sends the text to gpt-4o with a jsonResponseSchema, returning extracted_fields, a confidence score, missing_fields, and extraction_notes. The extraction_schema and document_type inputs steer the prompt so you control which fields come back.
  4. The save_to_postgres task (io.kestra.plugin.jdbc.postgresql.Queries) creates a document_extractions table if needed and inserts the extracted JSONB, confidence, and source metadata. It runs conditionally via runIf based on the output_destination input.
  5. The notify_slack task (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) posts a formatted message with the extracted fields, confidence percentage, characters processed, and any missing fields, also gated by runIf.

What you get

  • One reusable flow that handles PDF, HTML, and plain text input
  • Field extraction driven by a runtime JSON schema, not hardcoded logic
  • Confidence scores and missing-field tracking for quality control
  • Results in a queryable PostgreSQL JSONB column with source metadata
  • A Slack preview for fast human review of low-confidence extractions

Who it's for

  • Finance and operations teams automating invoice, receipt, and contract data entry
  • Legal and compliance teams pulling clauses, dates, and parties from contracts at scale
  • Data engineering teams building document ingestion pipelines for reports and filings
  • No-code automation builders who want the output schema as a configuration parameter

Why orchestrate this with Kestra

OpenAI gives you a model API, not a pipeline. Kestra supplies the orchestration around it: declarative YAML you can version and review, event triggers and schedules to process documents as they arrive, retries on transient HTTP or API failures, conditional runIf branching to route output, and full execution lineage so every extraction is traceable from source URL to stored row. The model has no scheduler, no state, and no way to chain download, parse, persist, and notify into one auditable run. Kestra fills that gap.

Prerequisites

  • A Kestra instance (local or cloud)
  • An OpenAI API key with access to gpt-4o
  • A reachable PostgreSQL database (if using the Postgres destination)
  • A Slack incoming webhook URL (if using the Slack destination)

Secrets

Configure these secrets in your Kestra instance:

  • OPENAI_API_KEY: API key for the OpenAI ChatCompletion task
  • SLACK_WEBHOOK_URL: incoming webhook URL for Slack notifications
  • POSTGRES_URL: JDBC connection URL for the target database
  • POSTGRES_USER: PostgreSQL username
  • POSTGRES_PASSWORD: PostgreSQL password

Quick start

  1. Add the blueprint to your namespace and set the secrets above.
  2. Run the flow with a document_url pointing to a sample PDF or web page.
  3. Adjust the extraction_schema input to match the fields you need.
  4. Pick an output_destination (postgres, slack, or both) and execute.
  5. Inspect the stored row or the Slack message to confirm the extracted data.

How to extend

  • Loop over a batch of documents with ForEach for bulk processing.
  • Add a human-approval gate for extractions below a confidence threshold.
  • Swap the HTTP download for an S3 or GCS task to read from object storage.
  • Chain into a downstream flow that creates ERP or accounting records from invoices.
  • Add a schedule or a webhook trigger to process documents automatically on arrival.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.