Back to Alchemy
Alchemy RecipeIntermediateautomation

Investment pitch deck generation from financial statements

24 March 2026

Introduction

Creating an investment pitch deck from raw financial statements is a task that typically takes finance professionals hours of manual work. You extract numbers from PDFs, format them into slides, design charts, and then realign everything with your narrative. Most of this is repetitive labour with high room for human error.

The workflow we're discussing today eliminates that friction entirely. By connecting three focused AI tools with an orchestration platform, you can feed in a financial statement PDF and receive a polished, presentation-ready pitch deck within minutes. No copy-pasting between tools, no manual chart creation, no reformatting. The entire process runs end to end without you touching anything after the initial upload.

This is an intermediate-level build. You'll need basic familiarity with webhooks and JSON payloads, but you don't need to write complex code. We'll use either Zapier, n8n, Make, or Claude Code depending on your comfort level and integration needs.

The Automated Workflow

How it works at a high level:

  1. Financial statement PDF is uploaded to a cloud folder (Google Drive, Dropbox) or submitted via a form.

  2. Chat-with-PDF-by-CopilotUS extracts key financial metrics, growth rates, and insights as structured JSON.

  3. Preswald AI takes that JSON and generates a full slide deck outline with content for each slide.

  4. Text2Infographic converts financial tables and key metrics into visual infographics.

  5. Preswald AI embeds those infographics into the final deck and exports as PPTX.

Choosing your orchestration platform:

For this workflow, I'd recommend n8n or Make if you want visual workflow building with good error handling. Zapier works but has limitations on complex JSON transformations. Claude Code is excellent if you want a single, self-contained script that you run locally or deploy as a serverless function.

Let's walk through the n8n approach first, since it gives you the most visibility and control.

Step 1: Trigger on file upload

Create a webhook trigger in n8n that listens for file uploads. You can connect this to Google Drive, Dropbox, or a simple HTTP POST from a web form.


{
  "trigger": "webhook",
  "event": "file.uploaded",
  "fileType": "application/pdf",
  "metadata": {
    "companyName": "string",
    "fiscalYear": "string"
  }
}

In n8n, add a Webhook node and set it to POST. Copy the webhook URL and use it as your file upload endpoint.

Step 2: Extract financial data with Chat-with-PDF-by-CopilotUS

The Chat-with-PDF API accepts a PDF URL and a prompt. You'll ask it to extract structured financial information.

First, if your PDF is in a cloud service, n8n can download it and pass the URL, or you can upload directly to CopilotUS's storage and reference it by token.


POST https://api.copilotus.app/v1/pdf/extract
Content-Type: application/json
Authorization: Bearer YOUR_COPILOTUS_API_KEY

{
  "pdfUrl": "https://storage.example.com/financial-statement.pdf",
  "prompt": "Extract all key financial metrics including revenue, EBITDA, net income, gross margin, operating margin, and growth rates year-over-year. Also identify the top 3 business risks and opportunities mentioned or implied in the document. Return as JSON with keys: revenue, ebitda, netIncome, grossMargin, operatingMargin, yoyGrowth, risks, opportunities, fundingHistory, keyMetrics.",
  "responseFormat": "json"
}

In n8n, use an HTTP Request node and map the webhook data to this request. The API returns structured JSON, which you then pass to the next step.

Example response:

{
  "revenue": {
    "2022": 45000000,
    "2023": 62000000,
    "yoyGrowth": 0.378
  },
  "ebitda": {
    "2022": 8100000,
    "2023": 13020000,
    "margin": 0.21
  },
  "netIncome": {
    "2022": 3600000,
    "2023": 5580000
  },
  "risks": ["Market saturation", "Regulatory changes"],
  "opportunities": ["Geographic expansion", "Product diversification"],
  "keyMetrics": {
    "burn_rate_monthly": 450000,
    "runway_months": 18,
    "customer_acquisition_cost": 1200
  }
}

Store this JSON output in n8n's internal variable store or pass it directly to the next node.

Step 3: Generate deck outline with Preswald AI

Preswald AI is an API-first presentation builder. You send it content and metadata, and it returns a structured deck blueprint that you can render to PPTX.


POST https://api.preswald.io/v1/decks/generate
Content-Type: application/json
Authorization: Bearer YOUR_PRESWALD_API_KEY

{
  "title": "Investment Pitch Deck",
  "companyName": "{{companyName}}",
  "theme": "professional",
  "slides": [
    {
      "slideType": "titleSlide",
      "title": "{{companyName}}",
      "subtitle": "Investment Opportunity",
      "backgroundColour": "#1a1a2e"
    },
    {
      "slideType": "bulletPoints",
      "title": "Key Metrics",
      "content": [
        "Revenue FY2023: ${{revenue.2023 | currency}}",
        "YoY Growth: {{revenue.yoyGrowth | percentage}}",
        "EBITDA Margin: {{ebitda.margin | percentage}}"
      ]
    },
    {
      "slideType": "richText",
      "title": "Market Opportunity & Risks",
      "content": "<h3>Opportunities</h3><ul>{{#each opportunities}}<li>{{this}}</li>{{/each}}</ul><h3>Risks</h3><ul>{{#each risks}}<li>{{this}}</li>{{/each}}</ul>"
    },
    {
      "slideType": "placeholder",
      "title": "Financial Overview",
      "contentId": "financial-infographic-1"
    },
    {
      "slideType": "bulletPoints",
      "title": "Ask & Use of Funds",
      "content": [
        "Seeking: $5M Series A",
        "Focus: Product development (40%)",
        "Sales & marketing (35%)",
        "Operations (25%)"
      ]
    }
  ],
  "variables": {
    "revenue": "{{extractedData.revenue}}",
    "ebitda": "{{extractedData.ebitda}}",
    "opportunities": "{{extractedData.opportunities}}",
    "risks": "{{extractedData.risks}}"
  }
}

Map the JSON output from Chat-with-PDF into Preswald's template variables. Preswald returns a deck ID and a preview URL.

Step 4: Create infographics with Text2Infographic

While Preswald generates the deck structure, Text2Infographic can create visual representations of your financial data. Call its API with your key metrics.


POST https://api.text2infographic.com/v1/generate
Content-Type: application/json
Authorization: Bearer YOUR_TEXT2INFOGRAPHIC_API_KEY

{
  "type": "chart",
  "chartType": "column",
  "title": "Revenue Growth",
  "data": {
    "labels": ["FY2022", "FY2023"],
    "datasets": [
      {
        "label": "Revenue",
        "values": [{{extractedData.revenue.2022}}, {{extractedData.revenue.2023}}],
        "colour": "#4CAF50"
      }
    ]
  },
  "outputFormat": "svg"
}

Make multiple calls for different visualisations: revenue trend, margin breakdown, unit economics, etc. Each call returns an SVG or PNG URL that you can embed in Preswald slides.

In n8n, use a Loop node to generate multiple infographics in sequence:

{
  "charts": [
    {
      "name": "revenue",
      "type": "line",
      "metric": "{{extractedData.revenue}}"
    },
    {
      "name": "ebitda_margin",
      "type": "gauge",
      "metric": "{{extractedData.ebitda.margin}}"
    },
    {
      "name": "unit_economics",
      "type": "bar",
      "metric": "{{extractedData.keyMetrics}}"
    }
  ]
}

Step 5: Insert infographics and export

Once you have infographic URLs, update your Preswald deck to embed them into the placeholder slides.


PATCH https://api.preswald.io/v1/decks/{{deckId}}/slides/3
Content-Type: application/json
Authorization: Bearer YOUR_PRESWALD_API_KEY

{
  "contentId": "financial-infographic-1",
  "imageUrl": "https://cdn.text2infographic.com/{{infographicId}}.svg"
}

Then export the final deck:


POST https://api.preswald.io/v1/decks/{{deckId}}/export
Content-Type: application/json
Authorization: Bearer YOUR_PRESWALD_API_KEY

{
  "format": "pptx",
  "fileName": "{{companyName}}-pitch-deck-{{timestamp}}.pptx"
}

Preswald returns a download URL. In n8n, you can save this to Google Drive, Dropbox, or email it to a designated inbox.

Complete n8n workflow structure:


[Webhook Trigger]
  ↓
[HTTP Request: Chat-with-PDF]
  ↓
[HTTP Request: Preswald Generate Deck]
  ↓
[Loop: Text2Infographic Charts]
  ↓
[HTTP Request: Preswald Update Slides]
  ↓
[HTTP Request: Preswald Export to PPTX]
  ↓
[Google Drive Upload / Email Notification]

Each HTTP Request node needs proper error handling. Add try-catch logic for API timeouts or rate limits. If Chat-with-PDF fails, the workflow should retry or send a notification to your team.

Alternative: Using Claude Code

If you prefer a single script approach, you can write a Python script using Claude's API that orchestrates all three tools.

import anthropic
import requests
import json
from typing import Optional

client = anthropic.Anthropic(api_key="YOUR_CLAUDE_API_KEY")

def extract_financial_data(pdf_url: str) -> dict:
    """Call Chat-with-PDF and parse response"""
    response = requests.post(
        "https://api.copilotus.app/v1/pdf/extract",
        headers={"Authorization": f"Bearer {COPILOTUS_API_KEY}"},
        json={
            "pdfUrl": pdf_url,
            "prompt": "Extract all financial metrics as JSON...",
            "responseFormat": "json"
        }
    )
    return response.json()

def generate_deck(financial_data: dict) -> str:
    """Call Preswald to generate deck structure"""
    response = requests.post(
        "https://api.preswald.io/v1/decks/generate",
        headers={"Authorization": f"Bearer {PRESWALD_API_KEY}"},
        json={
            "title": "Investment Pitch Deck",
            "companyName": financial_data.get("companyName"),
            "slides": build_slide_content(financial_data)
        }
    )
    return response.json()["deckId"]

def create_infographics(financial_data: dict) -> list:
    """Generate charts using Text2Infographic"""
    charts = []
    for metric_name, metric_data in financial_data.items():
        if isinstance(metric_data, dict) and "2022" in metric_data:
            response = requests.post(
                "https://api.text2infographic.com/v1/generate",
                headers={"Authorization": f"Bearer {TEXT2INFOGRAPHIC_API_KEY}"},
                json={
                    "type": "chart",
                    "chartType": "line",
                    "title": metric_name,
                    "data": {
                        "labels": ["FY2022", "FY2023"],
                        "datasets": [{
                            "label": metric_name,
                            "values": [metric_data.get("2022"), metric_data.get("2023")]
                        }]
                    }
                }
            )
            charts.append(response.json()["imageUrl"])
    return charts

def main(pdf_url: str, company_name: str):
    financial_data = extract_financial_data(pdf_url)
    financial_data["companyName"] = company_name
    
    deck_id = generate_deck(financial_data)
    infographic_urls = create_infographics(financial_data)
    
    # Update deck with infographics
    for idx, url in enumerate(infographic_urls):
        requests.patch(
            f"https://api.preswald.io/v1/decks/{deck_id}/slides/{4+idx}",
            headers={"Authorization": f"Bearer {PRESWALD_API_KEY}"},
            json={"contentId": f"infographic-{idx}", "imageUrl": url}
        )
    
    # Export to PPTX
    export_response = requests.post(
        f"https://api.preswald.io/v1/decks/{deck_id}/export",
        headers={"Authorization": f"Bearer {PRESWALD_API_KEY}"},
        json={"format": "pptx", "fileName": f"{company_name}-pitch-deck.pptx"}
    )
    
    return export_response.json()["downloadUrl"]

if __name__ == "__main__":
    pdf_url = "https://example.com/financial-statement.pdf"
    download_url = main(pdf_url, "Acme Corporation")
    print(f"Deck ready: {download_url}")

Deploy this as a serverless function on AWS Lambda or Google Cloud Functions, and trigger it via a simple API endpoint.

The Manual Alternative

If you want more control over each step or need to customise slides for specific investors, run the tools manually and sequentially.

Upload your PDF to Chat-with-PDF-by-CopilotUS's web interface and copy the extracted JSON. Paste that JSON into Preswald's slide builder to create your deck structure. Then use Text2Infographic's web interface to craft specific charts and manually insert them into Preswald. Finally, export from Preswald as PPTX.

This approach takes longer (30-45 minutes instead of 3-5 minutes) but gives you full editorial control at each stage. Use this method when your financial statements are particularly complex or when you're creating decks for multiple rounds with different narrative focuses.

Pro Tips

1. Handle PDF extraction failures gracefully

Not all PDFs parse cleanly. Some have scanned images instead of text, others use unusual table layouts. In your orchestration workflow, add conditional logic: if Chat-with-PDF confidence score is below 85%, trigger a manual review step. Send the extracted JSON to a Slack channel for a human to verify before proceeding.

{
  "condition": "confidence < 0.85",
  "action": "slack_notification",
  "message": "PDF extraction confidence low for {{companyName}}. Review extracted data before proceeding."
}

2. Respect API rate limits

All three tools have rate limits. Chat-with-PDF-by-CopilotUS allows 100 requests per minute on paid plans. Text2Infographic allows 50 per minute. Preswald allows 30 per minute. If you're generating multiple decks in parallel, implement exponential backoff and queue management in n8n or Make.

{
  "retryPolicy": {
    "maxRetries": 3,
    "backoffType": "exponential",
    "initialDelayMs": 1000,
    "maxDelayMs": 10000
  }
}

3. Cache infographics

Text2Infographic charges per chart. If you're generating decks for multiple companies with similar financial structures, cache the chart SVGs. Store URLs in a database keyed by metric type and year, so recurring metrics don't require new API calls.

4. Validate financial data consistency

Before feeding extracted data into Preswald, do quick sanity checks. Does revenue exceed EBITDA? Is YoY growth between -100% and 500%? Are margin percentages between 0 and 100? Add a validation step that flags outliers and pauses the workflow.

{
  "validations": [
    {"field": "revenue.2023", "rule": "> 0"},
    {"field": "revenue.yoyGrowth", "rule": "between -1 and 5"},
    {"field": "ebitda.margin", "rule": "between 0 and 1"}
  ]
}

5. Monitor costs per workflow run

Each tool charges differently. Track API calls and costs in your orchestration logs. After 10-20 runs, calculate your average cost per deck and optimise. You might find that requesting fewer infographics or extracting only critical metrics saves money without sacrificing quality.

Cost Breakdown

ToolPlan NeededMonthly CostNotes
Chat-with-PDF-by-CopilotUSProfessional$49100 PDFs/month; $0.49 per additional PDF
Preswald AIBusiness$9950 decks/month; includes exports; $2 per additional deck
Text2InfographicStandard$29100 charts/month; $0.30 per additional chart
n8nCloud Professional$505000 executions/month; covers ~50 full workflows
Make (Integromat)Standard$1010,000 ops/month; tight for heavy use
ZapierTeam$299Overkill for this use case unless you have other automations

For a typical scenario: 10 pitch decks per month with 3 infographics each, expect approximately $180/month in tool costs. That's roughly $18 per deck, saving you 2-3 hours of manual work per deck.