{
  "openapi": "3.1.0",
  "info": {
    "title": "DocuSense API",
    "version": "1.0.0",
    "summary": "Extract structured data from invoices, tax slips, pay stubs and bank statements.",
    "description": "The DocuSense REST API turns documents into structured JSON. Send a file, get named fields back, and receive signed webhooks when processing finishes.",
    "contact": {
      "name": "DocuSense support",
      "email": "support@docusense.pro",
      "url": "https://docusense.pro"
    },
    "termsOfService": "https://docusense.pro/terms"
  },
  "servers": [
    {
      "url": "https://api.docusense.pro/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Documents",
      "description": "Upload a document, read its extracted data, correct fields, export and delete it."
    },
    {
      "name": "Jobs",
      "description": "Follow an asynchronous extraction until it finishes."
    },
    {
      "name": "Batches",
      "description": "Send a ZIP archive or a multi-document PDF: DocuSense splits it and extracts every document."
    },
    {
      "name": "Review",
      "description": "Documents waiting for a human check (low confidence, missing fields, rules)."
    },
    {
      "name": "Search",
      "description": "Ask questions across your documents (smart search, Pro plan and above)."
    },
    {
      "name": "Reconciliation",
      "description": "Match invoices with bank statement payments (Pro plan and above)."
    },
    {
      "name": "Tax folder",
      "description": "Yearly tax folder: slips and pay stubs compared, ready for your accountant (Pro plan and above)."
    }
  ],
  "paths": {
    "/documents": {
      "post": {
        "tags": [
          "Documents"
        ],
        "operationId": "createDocument",
        "summary": "Extract a document",
        "description": "Uploads a file (base64) and extracts its fields. By default the call waits for the result and returns the extracted data (`201`). With `async: true`, it returns `202` immediately: follow the job with `GET /jobs/{documentId}` or a `document.completed` webhook. Use `documentType: \"AUTO\"` to let DocuSense recognise the type.",
        "x-permission": "documents:write",
        "x-rate-limit": "30 uploads per minute",
        "x-file-field": "fileBase64",
        "x-file-name": "invoice.pdf",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadRequest"
              },
              "example": {
                "documentType": "AUTO",
                "mimeType": "application/pdf",
                "language": "en",
                "fileName": "invoice.pdf",
                "fileBase64": "JVBERi0xLjcKJ..."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Extracted (synchronous mode).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentEnvelope"
                },
                "examples": {
                  "invoice": {
                    "$ref": "#/components/examples/DocumentResponse"
                  }
                }
              }
            }
          },
          "202": {
            "description": "Queued (asynchronous mode).",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                    "status": "PENDING",
                    "documentType": "AUTO"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          },
          "422": {
            "$ref": "#/components/responses/ExtractionFailed"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "get": {
        "tags": [
          "Documents"
        ],
        "operationId": "listDocuments",
        "summary": "List documents",
        "description": "Your documents, newest first, without their extracted data (read one document to get it).",
        "x-permission": "documents:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Limit100"
          },
          {
            "name": "type",
            "in": "query",
            "description": "Filter by document type.",
            "schema": {
              "$ref": "#/components/schemas/DocumentType"
            },
            "example": "INVOICE"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by status.",
            "schema": {
              "$ref": "#/components/schemas/DocumentStatus"
            },
            "example": "COMPLETED"
          },
          {
            "name": "channel",
            "in": "query",
            "description": "Filter by origin.",
            "schema": {
              "type": "string",
              "enum": [
                "app",
                "api",
                "batch"
              ]
            },
            "example": "api"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of documents.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "documents": [
                      {
                        "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                        "documentType": "INVOICE",
                        "language": "en",
                        "status": "COMPLETED",
                        "sourceName": "invoice.pdf",
                        "reviewRequired": false,
                        "tags": [
                          "approval_required"
                        ],
                        "checkStatus": "ok",
                        "channel": "api",
                        "apiKeyName": "Production server",
                        "batchId": null,
                        "createdAt": "2026-10-08T14:02:11.000Z",
                        "updatedAt": "2026-10-08T14:02:19.000Z",
                        "retainUntil": "2033-12-31T00:00:00.000Z"
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "limit": 20,
                      "total": 128,
                      "pages": 7
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/documents/usage": {
      "get": {
        "tags": [
          "Documents"
        ],
        "operationId": "getUsage",
        "summary": "Usage this month",
        "description": "Documents created since the start of the billing period, by origin.",
        "x-permission": "documents:read",
        "responses": {
          "200": {
            "description": "Usage by origin.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "since": "2026-10-01T00:00:00.000Z",
                    "app": 42,
                    "api": 311,
                    "batch": 57,
                    "unknown": 0,
                    "total": 410
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/documents/{documentId}": {
      "get": {
        "tags": [
          "Documents"
        ],
        "operationId": "getDocument",
        "summary": "Retrieve a document",
        "description": "The document with its extracted data, checks, review state and correction history.",
        "x-permission": "documents:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "200": {
            "description": "The document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentEnvelope"
                },
                "examples": {
                  "invoice": {
                    "$ref": "#/components/examples/DocumentResponse"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Documents"
        ],
        "operationId": "deleteDocument",
        "summary": "Delete a document",
        "description": "Deletes the document and its extracted data. Tax documents under legal retention are kept anonymised until their retention date.",
        "x-permission": "documents:delete",
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "message": "Document deleted."
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/documents/{documentId}/review": {
      "patch": {
        "tags": [
          "Documents"
        ],
        "operationId": "reviewDocument",
        "summary": "Approve or reject a document",
        "description": "Closes the review of a document waiting for a human check.",
        "x-permission": "documents:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "outcome"
                ],
                "additionalProperties": false,
                "properties": {
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "approved",
                      "rejected"
                    ]
                  }
                }
              },
              "example": {
                "outcome": "approved"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated document.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                    "reviewRequired": false,
                    "reviewOutcome": "approved",
                    "reviewedAt": "2026-10-08T15:10:00.000Z"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The document is not waiting for review.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "NOT_IN_REVIEW",
                    "message": "This document is not waiting for review."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/documents/{documentId}/checks": {
      "post": {
        "tags": [
          "Documents"
        ],
        "operationId": "runChecks",
        "summary": "Run invoice checks again",
        "description": "Re-runs the automatic invoice checks (line totals, tax rates, duplicates) — useful after correcting fields.",
        "x-permission": "documents:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "200": {
            "description": "The document with its checks.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                    "checkStatus": "warning",
                    "checks": [
                      {
                        "code": "tax_rate_unexpected",
                        "severity": "warning",
                        "params": {
                          "rate": 13
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "409": {
            "description": "Checks only apply to extracted invoices.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "NOT_CHECKABLE",
                    "message": "Checks apply to extracted invoices."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/documents/{documentId}/fields": {
      "patch": {
        "tags": [
          "Documents"
        ],
        "operationId": "correctFields",
        "summary": "Correct extracted fields",
        "description": "Replaces single values in the extracted data. Each change keeps the field's type and is recorded in the correction history. Masked identifiers cannot be edited.",
        "x-permission": "documents:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FieldChanges"
              },
              "example": {
                "changes": [
                  {
                    "path": [
                      "invoiceNumber"
                    ],
                    "value": "INV-0425"
                  },
                  {
                    "path": [
                      "lineItems",
                      0,
                      "amount"
                    ],
                    "value": 1200
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The corrected document.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                    "corrections": [
                      {
                        "path": "invoiceNumber",
                        "before": "INV-0428",
                        "after": "INV-0425",
                        "createdAt": "2026-10-08T15:20:00.000Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "409": {
            "description": "Only extracted documents can be corrected.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "NOT_READY",
                    "message": "Only extracted documents can be corrected."
                  }
                }
              }
            }
          },
          "422": {
            "description": "Invalid change (unknown field, wrong type, protected field).",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "TYPE_MISMATCH",
                    "message": "The new value must keep the field's type (number, text or yes/no).",
                    "field": "total"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/documents/{documentId}/export/{format}": {
      "get": {
        "tags": [
          "Documents"
        ],
        "operationId": "exportDocument",
        "summary": "Export a document",
        "description": "Exports the extracted data as JSON, CSV (top-level fields) or in a tax-authority layout (CRA, IRS, HMRC, DGFiP).",
        "x-permission": "documents:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          },
          {
            "name": "format",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv",
                "cra",
                "irs",
                "hmrc",
                "dgfip"
              ]
            },
            "example": "csv"
          }
        ],
        "responses": {
          "200": {
            "description": "The export (CSV as a file, other formats as JSON).",
            "content": {
              "text/csv": {
                "example": "field,value\ninvoiceNumber,INV-0425\ntotal,4280.52\ncurrency,CAD"
              },
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "format": "cra",
                    "documentType": "T4",
                    "exportedAt": "2026-10-08T15:30:00.000Z",
                    "payload": {
                      "taxYear": 2025,
                      "boxes": {
                        "box14": 68450,
                        "box22": 12310
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unsupported format.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "UNSUPPORTED_FORMAT",
                    "message": "Supported formats: json, csv, cra, irs, hmrc, dgfip"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found or extraction not complete.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "NOT_READY",
                    "message": "Document extraction not complete."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{documentId}": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "getJob",
        "summary": "Follow an asynchronous extraction",
        "description": "Poll this endpoint (every 2–5 seconds) after an upload with `async: true`, or subscribe to the `document.completed` webhook instead. When `done` is true, read the result at `resultUrl`.",
        "x-permission": "documents:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "200": {
            "description": "The job status.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                    "documentType": "INVOICE",
                    "status": "COMPLETED",
                    "done": true,
                    "error": null,
                    "resultUrl": "/api/v1/documents/8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                    "createdAt": "2026-10-08T14:02:11.000Z",
                    "updatedAt": "2026-10-08T14:02:19.000Z"
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/batches": {
      "post": {
        "tags": [
          "Batches"
        ],
        "operationId": "createBatch",
        "summary": "Upload a batch",
        "description": "Send the raw bytes of a ZIP archive or a multi-document PDF (up to 60 MB, limited by your plan). DocuSense detects each document, splits PDFs by page range and extracts everything in the background. Follow progress with `GET /batches/{batchId}` or the `batch.*` webhooks.",
        "x-permission": "documents:write",
        "x-rate-limit": "20 batches per hour",
        "x-binary-file": "statements.zip",
        "parameters": [
          {
            "name": "fileName",
            "in": "query",
            "description": "Original file name (display only).",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "statements.zip"
          },
          {
            "name": "language",
            "in": "query",
            "description": "Main language of the documents.",
            "schema": {
              "$ref": "#/components/schemas/Language"
            },
            "example": "en"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "application/pdf": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted, processing in the background.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "b7e1d2c3-0a9f-4e8d-8c7b-6a5f4e3d2c1b",
                    "status": "QUEUED",
                    "fileName": "statements.zip",
                    "mimeType": "application/zip",
                    "language": "en",
                    "documentsDetected": 0,
                    "processed": 0,
                    "failed": 0,
                    "reviewRequired": 0,
                    "createdAt": "2026-10-08T16:00:00.000Z",
                    "updatedAt": "2026-10-08T16:00:00.000Z"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The file exceeds the batch size of your plan.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "BATCH_TOO_LARGE",
                    "message": "This file exceeds the batch size allowed by your plan."
                  }
                }
              }
            }
          },
          "415": {
            "description": "Unsupported content type.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "UNSUPPORTED_MEDIA_TYPE",
                    "message": "Send the file as application/zip or application/pdf."
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "get": {
        "tags": [
          "Batches"
        ],
        "operationId": "listBatches",
        "summary": "List batches",
        "x-permission": "documents:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Items per page (1–50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            },
            "example": 20
          }
        ],
        "responses": {
          "200": {
            "description": "A page of batches.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "batches": [
                      {
                        "id": "b7e1d2c3-0a9f-4e8d-8c7b-6a5f4e3d2c1b",
                        "status": "COMPLETED",
                        "fileName": "statements.zip",
                        "documentsDetected": 12,
                        "processed": 12,
                        "failed": 0,
                        "reviewRequired": 1,
                        "createdAt": "2026-10-08T16:00:00.000Z"
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "limit": 20,
                      "total": 3,
                      "pages": 1
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/batches/{batchId}": {
      "get": {
        "tags": [
          "Batches"
        ],
        "operationId": "getBatch",
        "summary": "Retrieve a batch",
        "description": "Batch progress and the documents it produced (up to 500).",
        "x-permission": "documents:read",
        "parameters": [
          {
            "name": "batchId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "b7e1d2c3-0a9f-4e8d-8c7b-6a5f4e3d2c1b"
          }
        ],
        "responses": {
          "200": {
            "description": "The batch.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "b7e1d2c3-0a9f-4e8d-8c7b-6a5f4e3d2c1b",
                    "status": "PROCESSING",
                    "documentsDetected": 12,
                    "processed": 7,
                    "failed": 0,
                    "reviewRequired": 1,
                    "documents": [
                      {
                        "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                        "documentType": "BANK_STATEMENT",
                        "status": "COMPLETED",
                        "pageStart": 1,
                        "pageEnd": 3,
                        "classificationConfidence": 0.97,
                        "reviewRequired": false
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/review": {
      "get": {
        "tags": [
          "Review"
        ],
        "operationId": "listReview",
        "summary": "List documents to review",
        "description": "Documents waiting for a human check, with the reasons (low confidence, missing required fields, your rules and workflows).",
        "x-permission": "documents:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Limit100"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of documents to review.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "documents": [
                      {
                        "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                        "documentType": "INVOICE",
                        "documentTypeSource": "auto",
                        "classificationConfidence": 0.71,
                        "status": "COMPLETED",
                        "reviewReasons": [
                          "classification_low_confidence"
                        ],
                        "tags": [],
                        "createdAt": "2026-10-08T14:02:11.000Z"
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "limit": 20,
                      "total": 4,
                      "pages": 1
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/search": {
      "post": {
        "tags": [
          "Search"
        ],
        "operationId": "search",
        "summary": "Search your documents",
        "description": "Natural-language search over your indexed documents. `list` mode returns passages with their source; `answer` mode (Ultra and Mega) also writes an answer whose every figure is checked against the cited passages.",
        "x-permission": "documents:read",
        "x-rate-limit": "20 searches per minute",
        "x-plan": "Pro",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              },
              "example": {
                "query": "How much income tax was withheld on my 2025 T4 slips?",
                "mode": "list",
                "limit": 5,
                "filters": {
                  "documentTypes": [
                    "T4"
                  ],
                  "year": 2025
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Results.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "mode": "list",
                    "query": {
                      "filters": {
                        "documentTypes": [
                          "T4"
                        ],
                        "year": 2025
                      },
                      "terms": [
                        "income",
                        "tax",
                        "withheld"
                      ]
                    },
                    "results": [
                      {
                        "ref": 1,
                        "chunkId": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
                        "documentId": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                        "documentType": "T4",
                        "createdAt": "2026-03-02T10:15:00.000Z",
                        "page": 1,
                        "year": 2025,
                        "issuer": "Example Employer Inc.",
                        "excerpt": "T4 2025 · Example Employer Inc. — income tax deducted (box 22): 12310",
                        "score": 0.92
                      }
                    ],
                    "answer": null,
                    "notices": [],
                    "retrievers": {
                      "structured": 1,
                      "lexical": 3,
                      "vector": 5
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "Search temporarily unavailable.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "SEARCH_UNAVAILABLE",
                    "message": "Search is temporarily unavailable."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/reconciliation": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "operationId": "getReconciliation",
        "summary": "Reconcile invoices and payments",
        "description": "Matches your extracted invoices with the transactions of your bank statements: paid, paid twice, amount mismatch, unpaid, or not covered by a statement.",
        "x-permission": "documents:read",
        "x-plan": "Pro",
        "parameters": [
          {
            "name": "year",
            "in": "query",
            "description": "Invoice year.",
            "schema": {
              "type": "integer",
              "minimum": 2000,
              "maximum": 2100
            },
            "example": 2026
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only one status.",
            "schema": {
              "type": "string",
              "enum": [
                "paid",
                "paid_twice",
                "amount_mismatch",
                "unpaid",
                "not_covered"
              ]
            },
            "example": "unpaid"
          }
        ],
        "responses": {
          "200": {
            "description": "Reconciled invoices.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "summary": {
                      "total": 42,
                      "paid": 35,
                      "paid_twice": 1,
                      "amount_mismatch": 2,
                      "unpaid": 3,
                      "not_covered": 1,
                      "overdue": 2
                    },
                    "items": [
                      {
                        "documentId": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                        "invoiceNumber": "INV-0425",
                        "vendor": "Example Supplies Inc.",
                        "buyer": "Example Client Ltd.",
                        "total": 4280.52,
                        "currency": "CAD",
                        "invoiceDate": "2026-10-15",
                        "dueDate": "2026-11-14",
                        "status": "paid",
                        "confidence": "high",
                        "overdue": false,
                        "payments": [
                          {
                            "documentId": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
                            "date": "2026-11-02",
                            "amount": 4280.52,
                            "description": "EXAMPLE SUPPLIES INC"
                          }
                        ]
                      }
                    ],
                    "meta": {
                      "invoices": 42,
                      "statements": 6,
                      "truncated": false
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          }
        }
      }
    },
    "/tax-folder": {
      "get": {
        "tags": [
          "Tax folder"
        ],
        "operationId": "getTaxFolder",
        "summary": "Retrieve the tax folder",
        "description": "Your tax slips and pay stubs for a year, grouped by employer, with slip ↔ pay stub comparisons and findings.",
        "x-permission": "documents:read",
        "x-plan": "Pro",
        "parameters": [
          {
            "name": "year",
            "in": "query",
            "description": "Tax year (defaults to the newest year with documents).",
            "schema": {
              "type": "integer",
              "minimum": 2000,
              "maximum": 2100
            },
            "example": 2025
          }
        ],
        "responses": {
          "200": {
            "description": "The tax folder.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "years": [
                      2025,
                      2024
                    ],
                    "truncated": false,
                    "folder": {
                      "year": 2025,
                      "employers": [
                        {
                          "employer": "Example Employer Inc.",
                          "documents": [
                            {
                              "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                              "documentType": "T4"
                            }
                          ],
                          "comparisons": [
                            {
                              "slip": "T4",
                              "box": "14",
                              "label": "Employment income",
                              "slipValue": 68450,
                              "payslipValue": 68450,
                              "difference": 0,
                              "matches": true
                            }
                          ]
                        }
                      ],
                      "totals": {
                        "employmentIncome": 68450,
                        "incomeTaxWithheld": 12310,
                        "quebecTaxWithheld": 0
                      },
                      "findings": []
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          }
        }
      }
    },
    "/tax-folder/export": {
      "get": {
        "tags": [
          "Tax folder"
        ],
        "operationId": "exportTaxFolder",
        "summary": "Export the tax folder",
        "x-permission": "documents:read",
        "x-plan": "Pro",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "csv",
                "json"
              ]
            },
            "example": "csv"
          },
          {
            "name": "year",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 2000,
              "maximum": 2100
            },
            "example": 2025
          }
        ],
        "responses": {
          "200": {
            "description": "The export.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "fileName": "docusense-tax-folder-2025.csv",
                    "mimeType": "text/csv;charset=utf-8",
                    "content": "section,employer,item,slip,slip_value,payslip_value,difference,status\ndocument,Example Employer Inc.,T4_2025.pdf,T4,,,,\n…"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unsupported format.",
            "content": {
              "application/json": {
                "example": {
                  "success": false,
                  "error": {
                    "code": "UNSUPPORTED_FORMAT",
                    "message": "Supported formats: csv, json"
                  }
                }
              }
            }
          }
        },
        "description": "Returns the folder as a file to save: `fileName`, `mimeType` and the file `content` (CSV with a BOM for Excel, or JSON)."
      }
    }
  },
  "webhooks": {
    "document.completed": {
      "post": {
        "summary": "A document was extracted",
        "description": "Sent when an extraction finishes. `extractedData` is included only if the connection has “Include extracted data” turned on.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
                "event": "document.completed",
                "created_at": "2026-10-08T14:02:20.000Z",
                "data": {
                  "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
                  "documentType": "INVOICE",
                  "status": "COMPLETED",
                  "reviewRequired": false,
                  "tags": [
                    "approval_required"
                  ],
                  "batchId": null,
                  "createdAt": "2026-10-08T14:02:11.000Z",
                  "updatedAt": "2026-10-08T14:02:19.000Z",
                  "sourceName": "invoice.pdf",
                  "extractedData": {
                    "invoiceNumber": "INV-0425",
                    "total": 4280.52,
                    "currency": "CAD"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx within 10 seconds."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Create a key in Dashboard → API keys. Keep it on your server: never ship it in a browser or mobile app."
      }
    },
    "parameters": {
      "DocumentId": {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "Document id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "example": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f"
      },
      "Page": {
        "name": "page",
        "in": "query",
        "description": "Page number (from 1).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        },
        "example": 1
      },
      "Limit100": {
        "name": "limit",
        "in": "query",
        "description": "Items per page (1–100).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        },
        "example": 20
      }
    },
    "schemas": {
      "DocumentType": {
        "type": "string",
        "enum": [
          "INVOICE",
          "BANK_STATEMENT",
          "T4",
          "RL1",
          "ROE",
          "PAYSTUB_CA",
          "W2",
          "PAYSTUB_EU",
          "P60",
          "P45",
          "AVIS_IMPOSITION",
          "CONTRACT",
          "EXTRACT"
        ]
      },
      "DocumentStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "PROCESSING",
          "COMPLETED",
          "FAILED"
        ]
      },
      "Language": {
        "type": "string",
        "enum": [
          "en",
          "fr",
          "de",
          "nl",
          "it",
          "es"
        ],
        "default": "en"
      },
      "UploadRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "fileBase64",
          "mimeType",
          "documentType"
        ],
        "properties": {
          "fileBase64": {
            "type": "string",
            "description": "The file, base64-encoded (10 MB max before encoding)."
          },
          "mimeType": {
            "type": "string",
            "enum": [
              "application/pdf",
              "image/jpeg",
              "image/png",
              "image/webp",
              "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
              "text/csv"
            ],
            "description": "Type of the file."
          },
          "documentType": {
            "type": "string",
            "enum": [
              "AUTO",
              "INVOICE",
              "BANK_STATEMENT",
              "T4",
              "RL1",
              "ROE",
              "PAYSTUB_CA",
              "W2",
              "PAYSTUB_EU",
              "P60",
              "P45",
              "AVIS_IMPOSITION",
              "CONTRACT",
              "EXTRACT"
            ],
            "description": "`AUTO` detects the type. Each type requires a plan (see Document types)."
          },
          "language": {
            "$ref": "#/components/schemas/Language",
            "description": "Main language of the document."
          },
          "fileName": {
            "type": "string",
            "maxLength": 255,
            "description": "Original file name (display only)."
          },
          "async": {
            "type": "boolean",
            "default": false,
            "description": "Return `202` immediately and process in the background."
          },
          "index": {
            "type": "boolean",
            "default": false,
            "description": "Add the document to smart search."
          },
          "taxYear": {
            "type": "integer",
            "minimum": 2000,
            "maximum": 2100,
            "description": "Tax year hint for tax slips."
          },
          "country": {
            "type": "string",
            "enum": [
              "FR",
              "BE",
              "DE",
              "NL",
              "CH",
              "IT",
              "ES",
              "LU"
            ],
            "description": "Required for `PAYSTUB_EU`."
          },
          "province": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "Province or state hint (e.g. `QC`)."
          }
        }
      },
      "FieldChanges": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "changes"
        ],
        "properties": {
          "changes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "path",
                "value"
              ],
              "properties": {
                "path": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 10,
                  "items": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer",
                        "minimum": 0
                      }
                    ]
                  },
                  "description": "Path to the value, e.g. `[\"lineItems\", 0, \"amount\"]`."
                },
                "value": {
                  "oneOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "number"
                    },
                    {
                      "type": "boolean"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "SearchRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "minLength": 2,
            "maxLength": 500,
            "description": "Your question, in plain language."
          },
          "mode": {
            "type": "string",
            "enum": [
              "list",
              "answer"
            ],
            "default": "list",
            "description": "`answer` needs Ultra or Mega."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 10
          },
          "filters": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "documentTypes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DocumentType"
                }
              },
              "year": {
                "type": "integer"
              },
              "minAmount": {
                "type": "number",
                "minimum": 0
              },
              "maxAmount": {
                "type": "number",
                "minimum": 0
              },
              "issuer": {
                "type": "string",
                "maxLength": 120
              }
            }
          }
        }
      },
      "DocumentEnvelope": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "array"
              }
            }
          }
        }
      }
    },
    "examples": {
      "DocumentResponse": {
        "summary": "An extracted invoice",
        "value": {
          "success": true,
          "data": {
            "id": "8f3c2b1e-4a5d-4c6e-9f70-1a2b3c4d5e6f",
            "documentType": "INVOICE",
            "documentTypeSource": "auto",
            "classificationConfidence": 0.98,
            "language": "en",
            "status": "COMPLETED",
            "sourceName": "invoice.pdf",
            "extractedData": {
              "invoiceNumber": "INV-0425",
              "invoiceDate": "2026-10-15",
              "dueDate": "2026-11-14",
              "currency": "CAD",
              "vendor": {
                "name": "Example Supplies Inc.",
                "address": "123 Example St, Montréal QC"
              },
              "buyer": {
                "name": "Example Client Ltd."
              },
              "lineItems": [
                {
                  "description": "Document scanning service",
                  "quantity": 1,
                  "amount": 1200
                },
                {
                  "description": "Data entry (120 h)",
                  "quantity": 120,
                  "amount": 1800
                },
                {
                  "description": "Cloud archive · 12 months",
                  "quantity": 1,
                  "amount": 723
                }
              ],
              "subtotal": 3723,
              "taxLines": [
                {
                  "name": "GST",
                  "rate": 5,
                  "amount": 186.15
                },
                {
                  "name": "QST",
                  "rate": 9.975,
                  "amount": 371.37
                }
              ],
              "total": 4280.52
            },
            "checkStatus": "ok",
            "checks": [],
            "reviewRequired": false,
            "reviewReasons": [],
            "tags": [],
            "channel": "api",
            "apiKeyName": "Production server",
            "batchId": null,
            "corrections": [],
            "retainUntil": "2033-12-31T00:00:00.000Z",
            "createdAt": "2026-10-08T14:02:11.000Z",
            "updatedAt": "2026-10-08T14:02:19.000Z"
          }
        }
      }
    },
    "responses": {
      "ValidationError": {
        "description": "Invalid request.",
        "content": {
          "application/json": {
            "example": {
              "success": false,
              "error": {
                "code": "VALIDATION_ERROR",
                "message": "Invalid request",
                "details": [
                  {
                    "path": [
                      "mimeType"
                    ],
                    "message": "Invalid enum value"
                  }
                ]
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid or revoked API key.",
        "content": {
          "application/json": {
            "example": {
              "success": false,
              "error": {
                "code": "UNAUTHORIZED",
                "message": "Authentication required."
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found (or not yours).",
        "content": {
          "application/json": {
            "example": {
              "success": false,
              "error": {
                "code": "NOT_FOUND",
                "message": "Document not found"
              }
            }
          }
        }
      },
      "PlanRequired": {
        "description": "Your plan does not include this document type or feature.",
        "content": {
          "application/json": {
            "example": {
              "success": false,
              "error": {
                "code": "PLAN_REQUIRED",
                "message": "Document type T4 requires the PRO plan. Current plan: BASIC.",
                "requiredPlan": "PRO"
              }
            }
          }
        }
      },
      "ExtractionFailed": {
        "description": "The file was refused or could not be extracted.",
        "content": {
          "application/json": {
            "example": {
              "success": false,
              "error": {
                "code": "EXTRACTION_FAILED",
                "message": "The extraction failed. Please try again or choose another document type."
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit or monthly page limit reached.",
        "content": {
          "application/json": {
            "example": {
              "success": false,
              "error": {
                "code": "RATE_LIMIT_EXCEEDED",
                "message": "Upload rate limit exceeded."
              }
            }
          }
        }
      }
    }
  }
}
