{
  "openapi": "3.0.2",
  "info": {
    "title": "Document API",
    "version": "1.0.0",
    "description": "A document generation API that allows you to generate documents from templates with variables.\n\n[Feature Documentation](https://docs.epilot.io/docs/files/document-generation)\n"
  },
  "tags": [
    {
      "name": "Documents",
      "description": "Document Generation"
    }
  ],
  "security": [
    {
      "EpilotAuth": []
    }
  ],
  "paths": {
    "/v2/documents:meta": {
      "post": {
        "operationId": "getTemplateMeta",
        "summary": "getTemplateMeta",
        "description": "Get metadata for a document template\n\nSupported input document types:\n- .docx\n",
        "tags": [
          "Documents"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentMetaRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentMetaResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorOutput"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorOutput"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported media type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorOutput"
                }
              }
            }
          }
        }
      }
    },
    "/v2/documents:generate": {
      "post": {
        "operationId": "generateDocumentV2",
        "summary": "generateDocumentV2",
        "description": "Generates documents from templates with variables.\n\nSupported document types as input:\n- .docx\n- .ics\n\nSupported document types as output:\n- .pdf\n- .docx but limited to only text based variables\n- .ics\n\nUses [Template Variables API](https://docs.epilot.io/api/template-variables) to replace variables in the input document.\n",
        "parameters": [
          {
            "in": "query",
            "name": "job_id",
            "description": "Job ID for tracking the status of document generation action",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "mode",
            "description": "Type of mode used for document generation flow:\n- partial_generation will have a intermediate step for users to validate and replace the variable values before generating the final document.\n- full_generation, goes through all the steps for the full generation of final document\n",
            "schema": {
              "type": "string",
              "enum": [
                "partial_generation",
                "full_generation"
              ],
              "description": "- partial_generation: Generates a partial document for user validation before final generation\n- full_generation: Completes the entire document generation process in one step\n",
              "default": "full_generation"
            }
          },
          {
            "in": "query",
            "name": "preview_mode",
            "description": "Type of mode used for document generation preview:\n- open - preview_url provides a link to open the file in a browser\n- download - preview_url provides a link to download the file\n",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "download"
              ],
              "description": "- open: Preview URL opens the file directly in browser\n- download: Preview URL triggers a download of the file\n",
              "default": "open"
            }
          }
        ],
        "tags": [
          "Documents"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentGenerationV2Request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated document output",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentGenerationV2Response"
                }
              }
            }
          }
        }
      }
    },
    "/v2/documents:convert": {
      "post": {
        "operationId": "convertDocument",
        "summary": "convertDocument",
        "description": "Converts a document to a different format.\n\nSupported input document types:\n- .docx\n\nSupported output document types:\n- .pdf\n",
        "tags": [
          "Documents"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConvertDocumentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversion job output",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConvertDocumentResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/templates:validate": {
      "post": {
        "operationId": "validateTemplate",
        "summary": "validateTemplate",
        "description": "Validates a document template's variable syntax and, optionally, proposes a hotfixed copy of it.\n\nThe endpoint compiles the template with docxtemplater's core parser (the xlsx module for\nspreadsheets), so a delimiter or tag error reported here is one generation would fail on.\nFailures specific to the image or HTML modules are not covered. Every problem it can repair\nunambiguously — a missing brace, an extra brace, a smart quote or a non-breaking space that\nWord substituted inside a tag — is applied to a **copy** of the template, which is uploaded\nand returned as `fixed_document`.\n\nThe original template is never modified. Accepting the fix is an explicit, separate step:\nthe caller shows the user `issues` (each with its `before`/`after`), lets them download\n`fixed_document.preview_url`, and only then replaces the template.\n\nSupported input document types:\n- .docx, .docm, .dotx\n- .xlsx, .xlsm\n- .pptx\n",
        "tags": [
          "Documents"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateValidationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validation result, with the hotfixed template when one could be produced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateValidationResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorOutput"
                }
              }
            }
          },
          "413": {
            "description": "Template larger than the validator accepts (25 MB)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorOutput"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported media type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorOutput"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "EpilotAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization header with epilot OAuth2 bearer token",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "S3Reference": {
        "type": "object",
        "properties": {
          "bucket": {
            "type": "string",
            "example": "document-api-prod"
          },
          "key": {
            "type": "string",
            "example": "uploads/my-template.pdf"
          }
        },
        "required": [
          "bucket",
          "key"
        ]
      },
      "ErrorOutput": {
        "type": "object",
        "properties": {
          "error_message": {
            "description": "Error message",
            "type": "string"
          },
          "error_code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "error_details": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InvalidCustomVariableErrorDetails"
              },
              {
                "$ref": "#/components/schemas/InternalErrorDetails"
              },
              {
                "$ref": "#/components/schemas/DocxTemplaterErrorDetails"
              }
            ]
          }
        }
      },
      "InvalidCustomVariableErrorDetails": {
        "description": "Error details for invalid custom variables. This error will appear under 'PARSE_ERROR' error code.",
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/InvalidCustomVariableErrorDetail"
        }
      },
      "InvalidCustomVariableErrorDetail": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "explanation": {
            "description": "Explanation for the error",
            "type": "string"
          },
          "context": {
            "description": "Context for the error",
            "type": "object",
            "properties": {
              "invalid_variables": {
                "description": "List of invalid variables",
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Invalid variable",
                  "properties": {
                    "variable": {
                      "description": "Variable name",
                      "type": "string"
                    },
                    "error": {
                      "description": "Explanation for the error",
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "InternalErrorDetails": {
        "description": "Error details for internal error. This error will appear under 'INTERNAL_ERROR' error code.",
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "items": {
              "$ref": "#/components/schemas/InternalErrorDetail"
            }
          }
        }
      },
      "InternalErrorDetail": {
        "type": "object",
        "description": "Internal error detail",
        "properties": {
          "name": {
            "description": "Name of the error",
            "type": "string"
          },
          "message": {
            "description": "Error message",
            "type": "string"
          },
          "stack": {
            "description": "Stack trace",
            "type": "string"
          },
          "cause": {
            "description": "Cause of the error",
            "type": "string"
          }
        }
      },
      "DocxTemplaterErrorDetails": {
        "description": "Error details for DocxTemplater error. This error will appear under 'PARSE_ERROR' error code.\nSee https://docxtemplater.com/docs/errors/#error-schema for more details.\n",
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/DocxTemplaterErrorDetail"
        }
      },
      "DocxTemplaterErrorDetail": {
        "type": "object",
        "description": "DocxTemplater error detail",
        "properties": {
          "id": {
            "description": "Id of the error",
            "type": "string"
          },
          "context": {
            "description": "Context of the error",
            "type": "string"
          },
          "explanation": {
            "description": "Explanation of the error",
            "type": "string"
          }
        }
      },
      "ErrorCode": {
        "description": "Error codes for document generation:\n- PARSE_ERROR - Error while parsing the document. Normally related with a bad template using the wrong DocxTemplater syntax.\n- DOC_TO_PDF_CONVERT_ERROR - Error while converting the document to PDF. Normally related with a ConvertAPI failure.\n- INTERNAL_ERROR - Internal error. Please contact support.\n- INVALID_TEMPLATE_FORMAT - Invalid template format (only .docx is supported). This can happen due to a bad word file or an unsupported file extension.\n- TEMPLATE_NOT_FOUND - Template file was not found in S3. This indicates the template was likely deleted.\n",
        "type": "string",
        "enum": [
          "PARSE_ERROR",
          "DOC_TO_PDF_CONVERT_ERROR",
          "INTERNAL_ERROR",
          "INVALID_TEMPLATE_FORMAT",
          "TEMPLATE_NOT_FOUND"
        ]
      },
      "TemplateValidationRequest": {
        "type": "object",
        "required": [
          "template_document"
        ],
        "properties": {
          "template_document": {
            "description": "Input template document",
            "type": "object",
            "required": [
              "s3ref"
            ],
            "properties": {
              "filename": {
                "type": "string",
                "description": "Document original filename, used to name the fixed copy",
                "example": "Umzugsmeldung.xlsx"
              },
              "s3ref": {
                "$ref": "#/components/schemas/S3Reference"
              }
            }
          },
          "fix": {
            "description": "Attempt to produce a hotfixed copy of the template. When false, the template is only\ninspected and no file is written.\n",
            "type": "boolean",
            "default": true
          },
          "fix_level": {
            "description": "How far the hotfix may go:\n- safe - only repairs where the author's intent is unambiguous from the syntax\n  (unbalanced or duplicated braces, editor-substituted characters inside a tag).\n- aggressive - additionally promotes single-brace placeholders such as `{contact.name}`\n  to `{{contact.name}}`. These are common in customer templates but indistinguishable\n  from prose that uses braces, so they are reported with `confidence: low`.\n",
            "type": "string",
            "enum": [
              "safe",
              "aggressive"
            ],
            "default": "safe"
          }
        }
      },
      "TemplateValidationResponse": {
        "type": "object",
        "properties": {
          "valid": {
            "description": "Whether the template compiled cleanly before any repair was attempted",
            "type": "boolean",
            "example": false
          },
          "fixed": {
            "description": "Whether a corrected copy of the template could be produced",
            "type": "boolean",
            "example": true
          },
          "issues": {
            "description": "Everything found in the template, whether or not it could be repaired",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateIssue"
            }
          },
          "unresolved_errors": {
            "description": "Parser errors that remain after the hotfix (or the original errors when nothing was\nfixed). Empty when the template is valid.\n",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocxTemplaterErrorDetail"
            }
          },
          "fixed_document": {
            "description": "The corrected copy, for the user to review and accept. Absent when no repair was\napplied. The original template is left untouched.\n",
            "type": "object",
            "properties": {
              "s3ref": {
                "$ref": "#/components/schemas/S3Reference"
              },
              "filename": {
                "type": "string",
                "example": "Umzugsmeldung (fixed).xlsx"
              },
              "preview_url": {
                "description": "Short-lived download link for the corrected copy",
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "TemplateIssue": {
        "type": "object",
        "description": "A single template syntax problem, and the repair proposed for it",
        "properties": {
          "id": {
            "description": "Problem kind. Reuses docxtemplater's error vocabulary where one exists\n(`unopened_tag`, `unclosed_tag`, `duplicate_open_tag`, `duplicate_close_tag`), plus\n`malformed_tag` for single-brace placeholders and `typographic_characters` for\neditor-substituted characters inside an otherwise valid tag.\n",
            "type": "string",
            "example": "unopened_tag"
          },
          "file": {
            "description": "Zip part the problem was found in",
            "type": "string",
            "example": "xl/sharedStrings.xml"
          },
          "location": {
            "description": "Where the user can find it — a cell reference for spreadsheets, a part label\n(`Document body`, `Header 1`, `Slide 3`) otherwise.\n",
            "type": "string",
            "example": "Tabelle1!N4"
          },
          "context": {
            "description": "The offending text with surrounding context",
            "type": "string",
            "example": "…Datum: {system.date}} Unterschrift…"
          },
          "explanation": {
            "description": "Why the template parser rejects it",
            "type": "string",
            "example": "The tag is missing an opening brace."
          },
          "fixable": {
            "description": "Whether the proposed repair was applied to the fixed copy",
            "type": "boolean",
            "example": true
          },
          "confidence": {
            "description": "How sure we are that the repair is what the author meant",
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ]
          },
          "rule": {
            "description": "The repair rule that produced `after`",
            "type": "string",
            "example": "balance_opening_delimiter"
          },
          "before": {
            "description": "The text as it is in the template",
            "type": "string",
            "example": "{system.date}}"
          },
          "after": {
            "description": "The text as it would be in the fixed copy",
            "type": "string",
            "example": "{{system.date}}"
          }
        }
      },
      "TemplateSettings": {
        "type": "object",
        "description": "Template Settings for document generation",
        "properties": {
          "custom_margins": {
            "description": "Custom margins for the document",
            "type": "object",
            "properties": {
              "top": {
                "description": "Top margin in cm",
                "type": "number",
                "example": 2.54
              },
              "bottom": {
                "description": "Bottom margin in cm",
                "type": "number",
                "example": 2.54
              }
            }
          },
          "suggested_margins": {
            "description": "Suggested margins for the document",
            "type": "object",
            "properties": {
              "top": {
                "description": "Top margin in cm",
                "type": "number",
                "example": 2.54
              },
              "bottom": {
                "description": "Bottom margin in cm",
                "type": "number",
                "example": 2.54
              }
            }
          },
          "display_margin_guidelines": {
            "description": "Display margin guidelines (applicable to partial generation only)",
            "type": "boolean",
            "example": true
          },
          "enable_data_table_margin_autofix": {
            "description": "Enable data table margin autofix",
            "type": "boolean",
            "example": false
          },
          "template_with_datatable": {
            "description": "A flag that indicates whether the template has 1 or more data tables in it",
            "type": "boolean",
            "example": false
          },
          "enabled_template_settings_persistence": {
            "description": "Enables the persistance of template settings",
            "type": "boolean",
            "example": false
          },
          "misconfigured_margins": {
            "description": "An indication that the page margins are misconfigured",
            "type": "boolean",
            "example": false
          },
          "file_entity_id": {
            "description": "The file entity id, used when persisting a new template version with updated settings",
            "type": "string",
            "format": "uuid",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          }
        }
      },
      "DocumentMetaRequest": {
        "type": "object",
        "properties": {
          "template_document": {
            "description": "Input template document",
            "type": "object",
            "properties": {
              "s3ref": {
                "$ref": "#/components/schemas/S3Reference"
              }
            }
          }
        }
      },
      "DocumentMetaResponse": {
        "type": "object",
        "properties": {
          "page_margins": {
            "description": "Page margins for the document",
            "type": "object",
            "properties": {
              "top": {
                "description": "Top margin in cm",
                "type": "number",
                "example": 2.54
              },
              "bottom": {
                "description": "Bottom margin in cm",
                "type": "number",
                "example": 2.54
              },
              "left": {
                "description": "Left margin in cm",
                "type": "number",
                "example": 2.54
              },
              "right": {
                "description": "Right margin in cm",
                "type": "number",
                "example": 2.54
              },
              "header": {
                "description": "Header margin in cm",
                "type": "number",
                "example": 2.54
              },
              "footer": {
                "description": "Footer margin in cm",
                "type": "number",
                "example": 2.54
              }
            }
          },
          "variables": {
            "description": "List of variables in the document",
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "order.billing_contact.0.salutation",
              "order.billing_contact.0.title",
              "order_table",
              "stayHardStatic",
              "opportunity[attribute_name]",
              "opportunity[\"attribute_name\"]",
              "opportunity.[attribute_name]",
              "attribute_name",
              "opportunities.0.attribute_name",
              "opportunities[0].attribute_name",
              "contact.opportunities[0].attribute_name",
              "opportunities[Primary].attribute_name"
            ]
          }
        }
      },
      "DocumentGenerationV2Request": {
        "type": "object",
        "properties": {
          "template_document": {
            "description": "Input template document",
            "type": "object",
            "properties": {
              "filename": {
                "type": "string",
                "description": "Document original filename",
                "example": "my-template-{{order.order_number}}.docx"
              },
              "s3ref": {
                "$ref": "#/components/schemas/S3Reference"
              }
            }
          },
          "context_entity_id": {
            "type": "string",
            "format": "uuid",
            "description": "Entity to use for variable context",
            "example": "bcd0aab9-b544-42b0-8bfb-6d449d02eacc"
          },
          "user_id": {
            "type": "string",
            "description": "User Id for variable context",
            "example": "100321"
          },
          "language": {
            "type": "string",
            "description": "Language",
            "example": "de"
          },
          "variable_payload": {
            "description": "Custom values for variables in the template. Takes the higher precedence than others.",
            "type": "object",
            "properties": {
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "context_data": {
            "description": "Custom values for variables in the template. Takes the higher precedence than others.",
            "type": "object",
            "properties": {
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "template_settings": {
            "$ref": "#/components/schemas/TemplateSettings"
          }
        },
        "required": [
          "template_document"
        ]
      },
      "DocumentGenerationV2Response": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "job_status": {
            "description": "Status of the job",
            "type": "string",
            "enum": [
              "STARTED",
              "PROCESSING",
              "SUCCESS",
              "FAILED"
            ]
          },
          "message": {
            "description": "A message explaining the progress",
            "type": "string"
          },
          "ics_output": {
            "type": "object",
            "properties": {
              "output_document": {
                "type": "object",
                "properties": {
                  "filename": {
                    "description": "Generated document filename for ICS",
                    "type": "string",
                    "example": "my-appointment-OR-001.ics"
                  },
                  "s3ref": {
                    "$ref": "#/components/schemas/S3Reference"
                  }
                },
                "example": {
                  "s3ref": {
                    "bucket": "document-api-preview-prod",
                    "key": "preview/my-appointment.ics"
                  }
                }
              }
            }
          },
          "pdf_output": {
            "type": "object",
            "properties": {
              "preview_url": {
                "description": "Pre-signed S3 GET URL for PDF preview",
                "type": "string",
                "example": "https://document-api-prod.s3.eu-central-1.amazonaws.com/preview/my-template-OR-001.pdf"
              },
              "output_document": {
                "type": "object",
                "properties": {
                  "filename": {
                    "description": "Generated document filename for PDF",
                    "type": "string",
                    "example": "my-template-OR-001.pdf"
                  },
                  "s3ref": {
                    "$ref": "#/components/schemas/S3Reference"
                  }
                },
                "example": {
                  "s3ref": {
                    "bucket": "document-api-preview-prod",
                    "key": "preview/my-template.pdf"
                  }
                }
              }
            }
          },
          "docx_output": {
            "type": "object",
            "properties": {
              "preview_url": {
                "description": "Pre-signed S3 GET URL for DOCX preview",
                "type": "string",
                "example": "https://document-api-prod.s3.eu-central-1.amazonaws.com/preview/my-template-OR-001.docx"
              },
              "output_document": {
                "type": "object",
                "properties": {
                  "filename": {
                    "description": "Generated document filename for DOCX",
                    "type": "string",
                    "example": "my-template-OR-001.docx"
                  },
                  "s3ref": {
                    "$ref": "#/components/schemas/S3Reference"
                  }
                },
                "example": {
                  "s3ref": {
                    "bucket": "document-api-preview-prod",
                    "key": "preview/my-template.docx"
                  }
                }
              }
            }
          },
          "xlsx_output": {
            "type": "object",
            "properties": {
              "preview_url": {
                "description": "Pre-signed S3 GET URL for XLSX preview",
                "type": "string",
                "example": "https://document-api-prod.s3.eu-central-1.amazonaws.com/preview/my-template-OR-001.xlsx"
              },
              "output_document": {
                "type": "object",
                "properties": {
                  "filename": {
                    "description": "Generated document filename for XLSX",
                    "type": "string",
                    "example": "my-template-OR-001.xlsx"
                  },
                  "s3ref": {
                    "$ref": "#/components/schemas/S3Reference"
                  }
                },
                "example": {
                  "s3ref": {
                    "bucket": "document-api-preview-prod",
                    "key": "preview/my-template.xlsx"
                  }
                }
              }
            }
          },
          "error_output": {
            "$ref": "#/components/schemas/ErrorOutput"
          },
          "variable_payload": {
            "description": "List of variables and its corresponding replaced values from the document template",
            "type": "object",
            "properties": {
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "template_settings": {
            "$ref": "#/components/schemas/TemplateSettings"
          }
        }
      },
      "ConvertDocumentRequest": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string",
            "description": "Language",
            "example": "de"
          },
          "input_document": {
            "description": "Input document",
            "type": "object",
            "properties": {
              "s3ref": {
                "$ref": "#/components/schemas/S3Reference"
              }
            },
            "required": [
              "s3ref"
            ]
          },
          "output_format": {
            "description": "Output format of the document",
            "type": "string",
            "enum": [
              "pdf"
            ]
          },
          "output_filename": {
            "description": "Filename of the output document (optional)",
            "type": "string",
            "example": "converted.pdf"
          }
        },
        "required": [
          "input_document",
          "output_format"
        ]
      },
      "ConvertDocumentResponse": {
        "type": "object",
        "properties": {
          "output_document": {
            "type": "object",
            "properties": {
              "preview_url": {
                "description": "Pre-signed URL for the converted document",
                "type": "string",
                "example": "https://document-api-prod.s3.eu-central-1.amazonaws.com/preview/converted.pdf"
              },
              "s3ref": {
                "$ref": "#/components/schemas/S3Reference"
              }
            }
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://document.sls.epilot.io"
    }
  ]
}
