Skip to main content

Documentation Index

Fetch the complete documentation index at: https://duomi.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

A template is the brand and structural contract for everything you generate — fonts, colours, table styles, chart presets, master layouts. The API never invents a look; it conforms to whatever your .pptx encodes. Upload it once, analyze it once, and reference it by ID on every generation request.

Step 1: Prepare your template

Build the template in PowerPoint (or any tool that exports .pptx). A few things that help analysis identify slide structure cleanly:
  • Tables with the right column count and a populated header row
  • Charts with realistic sample categories and series
  • Distinct master layouts for distinct page types (table-heavy pages, chart pages, agenda, dividers)
  • Title placeholders on slides that should accept titles
The example used throughout this page is slide 1 of a small demo template — a single six-column table with a coloured header band:
Empty template slide with a teal/blue six-column header band.

Step 2: Upload

Two-step flow: the API returns a signed upload URL; you PUT the .pptx directly to storage; you confirm the upload.

Initiate

POST /api/v1/templates
X-API-Key: your-api-key
Content-Type: application/json

{
  "filename": "ic-memo-template.pptx",
  "file_size": 1048576,
  "metadata": {
    "category": "ic-memo",
    "tags": ["pe", "fund-1"],
    "description": "IC memo template for fund 1"
  }
}
{
  "template_id": "tmpl_abc123",
  "upload_url": "https://storage.example.com/signed-url...",
  "expires_in": 3600,
  "status": "pending"
}

Upload the file

PUT the .pptx bytes to upload_url. The bytes go directly to object storage; the API never sees them.

Confirm

POST /api/v1/templates/{template_id}/upload/confirm
X-API-Key: your-api-key
The service verifies the object exists and marks the template as uploaded.

Step 3: Run analysis

POST /api/v1/templates/{template_id}/analysis
X-API-Key: your-api-key
Content-Type: application/json

{
  "options": {
    "parse_master_template_layout": true,
    "parse_slides": true,
    "include_placeholder_positions": true,
    "include_table_details": true
  }
}
Analysis runs asynchronously; the response returns immediately with an analysis_id and status: "processing".

Step 4: Inspect the analysis output

Once analysis completes, fetch the results:
GET /api/v1/templates/{template_id}/analysis
X-API-Key: your-api-key
The response wraps the parser output. The top-level structure:
{
  "slides": [
    {
      "slideId": "slide_a3f81c92",
      "slideIndex": 0,
      "slideNumber": 1,
      "title": null,
      "dimension": { "width": 1440.0, "height": 810.0 },
      "shapes": [ /* one entry per shape on the slide */ ]
    },
    {
      "slideId": "slide_7e2bd445",
      "slideIndex": 1,
      "slideNumber": 2,
      "title": null,
      "dimension": { "width": 1440.0, "height": 810.0 },
      "shapes": [ /* ... */ ]
    }
  ]
}
Each slide gets its own slideId (assigned during analysis, stable across reads). Generation requests target slides by slideId, not by template — which means a single deck can mix slides from multiple templates by referencing each one’s slideId. slideIndex (0-based) and slideNumber (1-based, matches PowerPoint’s slide number) are also available if you need ordering. Each entry in shapes has a common set of fields, plus type-specific extras keyed off shape_type. The rest of this section walks through each shape type with a real excerpt from the parser running against slide 1 of the demo template above.

Common fields (every shape)

{
  "is_placeholder": true,
  "placeholder_type": "SLIDE_NUMBER",
  "placeholder_index": 13,
  "shape_type": "AutoShape",
  "name": "Slide Number Placeholder 1",
  "text": "1",
  "x": 1363.0147705078125,
  "y": 772.1712036132812,
  "width": 76.98519897460938,
  "height": 29.77204704284668
}
FieldMeaning
shape_typeAutoShape, Table, Chart, OleObjectFrame, etc.
nameThe shape’s name as set in PowerPoint
is_placeholdertrue if the shape is a master-layout placeholder
placeholder_typeTITLE, BODY, SLIDE_NUMBER, etc. (or null)
placeholder_indexIndex that ties the shape to its master-layout slot (or null)
textCurrent text on the shape (often "" for an unfilled template)
x, y, width, heightPosition and size in points

Placeholder shapes (TITLE, BODY, SLIDE_NUMBER)

Adds text_format, describing the font the template uses for that placeholder.
{
  "is_placeholder": true,
  "placeholder_type": "TITLE",
  "placeholder_index": 0,
  "shape_type": "AutoShape",
  "name": "Title 2",
  "text": "",
  "x": 66.0,
  "y": 64.91110229492188,
  "width": 1242.0,
  "height": 48.0,
  "text_format": {
    "font_color": { "r": 44, "g": 44, "b": 44 },
    "font_size": 33.75,
    "font_name": "Arial",
    "bold": true,
    "italic": false
  }
}
The text_format block tells you what the title (or body, etc.) will look like once populated — the same font and colour the template’s master layout encodes.

Table shapes

Adds table_rows / table_columns, plus table_info (dimensions, style preset, six PowerPoint table-style flags) and table_styling (per-cell formatting for the header and body rows).
{
  "shape_type": "Table",
  "name": "Table 4",
  "x": 66.0,
  "y": 140.69583129882812,
  "width": 1298.1602783203125,
  "height": 52.39228439331055,
  "table_rows": 1,
  "table_columns": 6,
  "table_info": {
    "rows": 1,
    "columns": 6,
    "width": 1298.1602783203125,
    "height": 52.39228439331055,
    "style_preset": "TableStylePreset.MEDIUM_STYLE_2_ACCENT_1",
    "has_first_row": false,
    "has_last_row": false,
    "has_first_col": false,
    "has_last_col": false,
    "horizontal_banding": false,
    "vertical_banding": false
  },
  "table_styling": {
    "header_row_format": [
      {
        "fill_type": "FillType.SOLID",
        "fill_color": { "r": 204, "g": 0, "b": 0 },
        "transparency": 0.0,
        "borders": {
          "left":   { "width": 2.25, "color": { "r": 255, "g": 255, "b": 255 }, "style": "LineStyle.SINGLE" },
          "top":    { "width": 2.25, "color": { "r": 255, "g": 255, "b": 255 }, "style": "LineStyle.SINGLE" },
          "right":  { "width": 2.25, "color": { "r": 255, "g": 255, "b": 255 }, "style": "LineStyle.SINGLE" },
          "bottom": { "width": 2.25, "color": { "r": 255, "g": 255, "b": 255 }, "style": "LineStyle.SINGLE" },
          "diagonal_down": { "width": null, "color": null, "style": "LineStyle.NOT_DEFINED" },
          "diagonal_up":   { "width": null, "color": null, "style": "LineStyle.NOT_DEFINED" }
        }
      }
    ],
    "body_row_format": [],
    "header_text_format": [
      { "font_color": { "r": 255, "g": 255, "b": 255 }, "font_size": 14.0, "font_name": "Arial", "bold": true, "italic": false, "alignment": "center" }
    ],
    "body_text_format": []
  }
}
The example shows one entry in each per-cell array; the real response has one entry per column (six entries, mostly identical). Each border block also includes diagonal_down and diagonal_up (typically LineStyle.NOT_DEFINED for tables that don’t use diagonals). table_styling arrays:
ArrayWhat it contains
header_row_formatOne entry per column of the header row: fill type, fill colour, transparency, and four borders + two diagonals
header_text_formatOne entry per column of the header row: font name, size, colour, bold/italic, alignment
body_row_formatSame shape as header_row_format, for body rows; empty when the template has no populated body row
body_text_formatSame shape as header_text_format, for body rows

Table-style flags

The six boolean flags inside table_info mirror PowerPoint’s “Table Tools → Design → Table Style Options” checkboxes. They control whether the applied style preset (e.g. MEDIUM_STYLE_2_ACCENT_1) emphasizes certain rows or columns:
FlagPowerPoint checkboxEffect when true
has_first_rowHeader RowFirst row gets the style’s header formatting
has_last_rowTotal RowLast row gets the style’s “totals” formatting
has_first_colFirst ColumnFirst column gets emphasized formatting
has_last_colLast ColumnLast column gets emphasized formatting
horizontal_bandingBanded RowsAlternating row colours from the style
vertical_bandingBanded ColumnsAlternating column colours from the style
These flags are independent of the cell-level formatting in header_row_format / header_text_format. In the example above all six are false because the header band is styled directly on each cell, not via the style preset.

Chart shapes

Charts return only the common shape fields — position, name, shape_type: "Chart". Example from a chart slide elsewhere in the same template:
{
  "is_placeholder": false,
  "placeholder_type": null,
  "placeholder_index": null,
  "shape_type": "Chart",
  "name": "Chart 4",
  "text": "",
  "x": 66.0,
  "y": 171.47369384765625,
  "width": 1242.0,
  "height": 553.6691284179688
}
The chart’s internal structure (categories, series, preset) lives inside the .pptx itself; generation requests reference the chart by its slide’s identifier and supply the data to populate it. See the chart guides for how to fill or refresh a chart.

Text-marker shapes (AutoShape placeholders)

Templates also use a second placeholder pattern: regular AutoShape shapes whose text field holds a recognized marker string. The API identifies these by their text value and swaps in the real content from the request payload. Common markers in the demo template: LHS_header, RHS_header, Bullet_placeholder, Text_placeholder. These have is_placeholder: false and placeholder_type: null (PowerPoint doesn’t classify them as native placeholders) but functionally they are content slots.
{
  "is_placeholder": false,
  "placeholder_type": null,
  "placeholder_index": null,
  "shape_type": "AutoShape",
  "name": "Rectangle 14",
  "text": "LHS_header",
  "x": 66.0,
  "y": 164.58921813964844,
  "width": 605.142822265625,
  "height": 48.2400016784668
}
The distinction:
ShapeIdentifier the API uses
Native PowerPoint placeholderplaceholder_type (TITLE, BODY, etc.)
Text-marker AutoShapetext value (LHS_header, etc.)
Decorative AutoShapeNone — has text: "" and is ignored at generation time

Authoring-tool artifacts

OleObjectFrame shapes are embedded objects from authoring tools, most commonly think-cell. They appear on every slide in templates built with such tools and don’t carry generatable content.
{
  "is_placeholder": false,
  "placeholder_type": null,
  "placeholder_index": null,
  "shape_type": "OleObjectFrame",
  "name": "think-cell data - do not delete",
  "text": "",
  "x": 0.12503936886787415,
  "y": 0.12503936886787415,
  "width": 0.09661417454481125,
  "height": 0.12503936886787415
}
The parser returns these as-is for completeness. Safe to ignore.

Step 5: Use it for generation

Generation requests reference slides by slideId. Because IDs are per-slide, a single deck can pull slides from multiple templates — useful for assembling pitch books, IC memos, or LP updates that combine standard cover/agenda slides from one template with content slides from another.
{
  "slides": [
    { "template_slide_id": "slide_a3f81c92", "slide_data": { /* ... */ } },
    { "template_slide_id": "slide_b1f9e2d7", "slide_data": { /* ... */ } },
    { "template_slide_id": "slide_c4d20af8", "slide_data": { /* ... */ } }
  ]
}
See Slide input for how to map your data onto each slide’s analysis structure, and Examples for copy-paste payloads against common slide shapes.

Maintenance

Template lifecycle

ActionEndpoint
List templatesGET /api/v1/templates
Get template details and the latest analysis summaryGET /api/v1/templates/{id}
Download the original .pptxGET /api/v1/templates/{id}/download
Update template metadata (name, tags, description)PATCH /api/v1/templates/{id}
Soft-delete a templateDELETE /api/v1/templates/{id}
Restore a soft-deleted templatePOST /api/v1/templates/{id}/restore

Analysis

ActionEndpoint
Re-run analysis (e.g. after parser updates, or to refresh with new options)POST /api/v1/templates/{id}/analysis
Check analysis status (lightweight, no full payload)GET /api/v1/templates/{id}/analysis/status
Get the full analysis resultsGET /api/v1/templates/{id}/analysis
Cancel a running analysisDELETE /api/v1/templates/{id}/analysis/{analysis_id}

Slides

ActionEndpoint
Get a specific slide’s analysis (by slide_number)GET /api/v1/templates/{id}/slides/{slide_number}
Render a slide as a PNG previewGET /api/v1/templates/{id}/slides/{slide_number}/preview
The slide preview endpoint is useful when an agent or app wants to show the user a thumbnail of the template slide they’re about to populate.

Updating templates

There is no endpoint to overwrite a template’s .pptx bytes. If you change the underlying file, upload it as a new template (new template_id) — generations reference templates by ID and the analysis is tied to the file that was uploaded. The PATCH endpoint only updates metadata (name, tags, description), not the file itself.
Looking for the endpoint that picks the best-fit slide for a given input shape? That’s POST /api/v1/templates/match, documented under Slide input since it’s part of composing a generation request rather than maintaining a template.