{
  "openapi": "3.0.3",
  "info": {
    "title": "MCA Forms API",
    "version": "1.0.0",
    "description": "Programmatic API for filing Ministry of Corporate Affairs (MCA) forms for Indian LLPs and Companies.\n\n## Authentication — Two Modes\n\n### Mode A: Single user (direct cookie inject)\nFor a single logged-in user or a server-side script:\n1. Log into [MCA Portal](https://www.mca.gov.in) in Chrome\n2. DevTools → Application → Cookies → copy all cookies as one string\n3. `POST /api/auth/inject-session` with `{ \"cookies\": \"...\" }`\n4. Use returned `sessionId` in `X-Session-Id` header for all requests\n\n### Mode B: Multi-user B2B (CoSec Office / SaaS)\nFor applications serving many users — no cookie pasting ever:\n1. `POST /api/connect/register` (master key required) → get `apiKey` + `connectUrl` per user\n2. Store `apiKey` against the user in your database\n3. Show the user a 'Connect MCA' button that opens `connectUrl` in their browser\n4. The MCA Connector Chrome Extension auto-detects the page and syncs cookies silently\n5. `GET /api/connect/status?apiKey=xxx` to check if the user is connected\n6. Before filing: `GET /api/connect/session?apiKey=xxx` → get cookies → `POST /api/auth/inject-session` → file\n\nDownload the Chrome Extension: `GET /api/extension/download`\n\n## Currently Supported Forms\n- **Form 11** — LLP Annual Return (`/api/form11/*`)\n- **Form 8** — LLP Statement of Account & Solvency (`/api/form8/*`)\n- **Form DPT-3** — Return of Deposit (Companies) (`/api/dpt3/*`)\n- **Master Data Search** — public CIN/LLPIN lookup (`/api/master/*`) — requires injected MCA session like the form filing endpoints.\n- **Dashboard** — view + download all your MCA filings (`/api/dashboard/*`).\n\nBoth forms support optional file attachments (PDF/DOC/DOCX, max 2 MB) uploaded to MCA's Document Management System (DMS).\n\n## Duplicate filing protection\nMCA only accepts ONE filing per LLPIN per financial year for both Form 8 and Form 11. A second submission for the same period returns `resCode=210` with message \"Technical Error\" / `SubmissionRestricted=Y`. To re-file, the user must first withdraw the existing SRN on the MCA portal.\n\n## Planned Forms\n- **AOC-4** — Company Annual Financial Statement (`/api/aoc4/*`)\n- **MGT-7A** — Small Company / OPC Annual Return (`/api/mgt7a/*`)\n\n## Shared LLP Data\nUse `/api/llp/*` endpoints to fetch LLP master info and partner details — these work across all form types.",
    "contact": {
      "name": "MCA Forms API"
    }
  },
  "servers": [
    { "url": "", "description": "Same origin (current server)" }
  ],
  "tags": [
    { "name": "Auth",    "description": "Session management — inject browser cookies, check status, login via captcha" },
    { "name": "Connect", "description": "Multi-user MCA session management for B2B apps (e.g. CoSec Office). Each user connects their MCA account once via a Chrome Extension — no cookie pasting ever." },
    { "name": "LLP",     "description": "LLP master data — name, address, partners, DPIN lookup. Shared across all form types." },
    { "name": "Form 11", "description": "LLP Annual Return (Form 11) — prefill, submit, save draft, download PDF, upload attachment" },
    { "name": "Form 8",  "description": "LLP Statement of Account & Solvency (Form 8) — prefill, submit, save draft, download PDF, upload attachment" },
    { "name": "Form DPT-3", "description": "Form DPT-3 — Return of Deposit for Companies. Four statutory purposes (A/B/C/D); UI surfaces sections conditionally. Same MCA session as Form 8 / Form 11 / Master Data / Dashboard." },
    { "name": "Master Data", "description": "Public CIN / LLPIN lookup using MCA's MDS portal. Requires active MCA session (Akamai blocks server-IP requests). Each lookup needs a CAPTCHA solved by the user." },
    { "name": "Dashboard", "description": "My Applications dashboard — list filings, search by CIN/SRN, download single or bulk PDFs. All endpoints require an injected MCA session (same as Form 8 / Form 11 / Master Data)." },
    { "name": "VPD",       "description": "View Public Documents — pay ₹100 per company for 7-day download access to all filed documents. Two-phase flow: pre-payment (search → preview → cart) → user pays on MCA portal → post-payment (workspace → documents → download). 11 endpoints under /api/vpd/. Recommended download path: `POST /api/vpd/download-one` per doc, called 8-in-parallel client-side — server caches MCA session-priming state per-SRN (5-min TTL) so a 20-doc burst takes ~15-20s. Bulk `/api/vpd/download` available if you want one merged ZIP server-side. See VPD_API.md for the full Cursor integration guide with end-to-end examples and MCA quirks." },
    { "name": "Form MGT-7A", "description": "MGT-7A — Annual Return for Small Companies / One Person Companies (OPCs). First endpoint: prior-FY Share Capital snapshot used to pre-populate opening balances on new MGT-7A drafts. Same MCA session as Form 8 / 11 / DPT-3." },
    { "name": "Form AOC-4",  "description": "AOC-4 — Annual Financial Statements for Companies (Section 137). The most complex MCA filing — ~155 fields across THREE composite sub-forms (main, Auditor's Report, Director's Report). Endpoints include HAR-verified working templates and a single orchestrator (/submit) that runs the full Save→Proceed→Save→Proceed→Save→Submit chain. See AOC4_API.md for the Cursor integration guide." },
    { "name": "Future",  "description": "Planned endpoints for the rest of MGT-7A (not yet implemented)" }
  ],
  "components": {
    "securitySchemes": {
      "SessionId": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Session-Id",
        "description": "Server-side session ID returned by inject-session or login. Ties your request to the stored MCA cookies."
      },
      "MasterKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Connect-Master-Key",
        "description": "Secret key set via `CONNECT_MASTER_KEY` environment variable on the server. Required for Connect admin endpoints (register, session retrieval, disconnect, list). Only your backend should ever hold this key — never expose it to browsers."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error":  { "type": "string", "description": "Human-readable error message" },
          "detail": { "type": "string", "description": "Technical error details" },
          "hint":   { "type": "string", "description": "Suggested action to resolve the error" }
        },
        "required": ["error"]
      },
      "Address": {
        "type": "object",
        "description": "MCA registered office address (structured). The server accepts any of these key variants: `line1`/`line2` OR `addressline1`/`addressline2` OR `addressLine1`/`addressLine2`. They are all normalised to MCA's required key shape internally.",
        "properties": {
          "line1":    { "type": "string", "example": "SHOP NO. K-50, LGF, REVERA", "description": "Address line 1 (also accepted: `addressline1`)" },
          "line2":    { "type": "string", "example": "PLOT NO 1-8, RAM CHANDRAPURA JAGATPURA", "description": "Address line 2 (also accepted: `addressline2`)" },
          "area":     { "type": "string", "example": "Sitapura Industrial Area" },
          "city":     { "type": "string", "example": "Jaipur" },
          "district": { "type": "string", "example": "Jaipur" },
          "state":    { "type": "string", "example": "Rajasthan" },
          "country":  { "type": "string", "example": "India" },
          "pincode":  { "type": "string", "example": "302022", "description": "PIN code as a string or number — both accepted" },
          "latitude":  { "type": "string", "example": "26.78354" },
          "longitude": { "type": "string", "example": "75.862126" }
        }
      },
      "Partner": {
        "type": "object",
        "description": "A single LLP partner or designated partner",
        "properties": {
          "dpin":                     { "type": "string",  "example": "01234567", "description": "DPIN / DIN / PAN / Passport number of the partner" },
          "name":                     { "type": "string",  "example": "JOHN DOE", "description": "Full name as registered with MCA" },
          "designation":              { "type": "string",  "enum": ["Designated Partner", "Partner"], "example": "Designated Partner" },
          "appointmentDate":          { "type": "string",  "format": "date", "example": "2020-01-15", "description": "Date of appointment (YYYY-MM-DD)" },
          "cessationDate":            { "type": "string",  "format": "date", "nullable": true, "example": null, "description": "Date of cessation, null if still active" },
          "obligationOfContribution": { "type": "string",  "example": "100000", "description": "Agreed contribution amount in INR" },
          "contributionReceived":     { "type": "string",  "example": "100000", "description": "Actual contribution received in INR" },
          "residentInIndia":          { "type": "boolean", "example": true },
          "numberOfLLPs":             { "type": "string",  "example": "1", "description": "Number of other LLPs this partner is associated with" },
          "numberOfCompanies":        { "type": "string",  "example": "0", "description": "Number of companies this partner is a director of" }
        }
      },
      "ConnectUser": {
        "type": "object",
        "description": "A registered user slot in the multi-user connect store",
        "properties": {
          "apiKey":      { "type": "string",  "example": "a3f9e2b1c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3", "description": "48-char hex API key — store this against the user in your app" },
          "appId":       { "type": "string",  "example": "user_123", "description": "Your app's internal user ID" },
          "label":       { "type": "string",  "example": "Priya Sharma", "description": "Human-readable label for admin UI" },
          "connected":   { "type": "boolean", "example": true, "description": "True when the user has synced their MCA session via the Chrome Extension" },
          "mcaUserId":   { "type": "string",  "example": "MCAUSER123456", "description": "MCA user ID resolved from the session" },
          "mcaUserName": { "type": "string",  "example": "Priya Sharma", "description": "Full name as returned by MCA" },
          "mcaEmail":    { "type": "string",  "example": "priya@example.com" },
          "lastSync":    { "type": "string",  "format": "date-time", "description": "When the extension last synced cookies" },
          "createdAt":   { "type": "string",  "format": "date-time" }
        }
      },
      "PartnerInput": {
        "type": "object",
        "description": "Partner data required when submitting Form 11",
        "required": ["dpin", "name", "designation"],
        "properties": {
          "dpin":                     { "type": "string",  "example": "01234567" },
          "name":                     { "type": "string",  "example": "JOHN DOE" },
          "designation":              { "type": "string",  "enum": ["Designated Partner", "Partner"], "default": "Designated Partner" },
          "appointmentDate":          { "type": "string",  "format": "date", "example": "2020-01-15", "description": "YYYY-MM-DD" },
          "cessationDate":            { "type": "string",  "format": "date", "nullable": true, "example": null },
          "obligationOfContribution": { "type": "string",  "example": "100000", "default": "0" },
          "contributionReceived":     { "type": "string",  "example": "100000", "default": "0" },
          "residentInIndia":          { "type": "boolean", "default": true },
          "numLLPs":                  { "type": "string",  "example": "1", "default": "0" },
          "numCompanies":             { "type": "string",  "example": "0", "default": "0" }
        }
      },
      "BalanceSheet": {
        "type": "object",
        "description": "Balance Sheet (Statement of Account) — used for both currentStatementOfAccount and previousStatementOfAccount in Form 8. All amounts are numbers in INR.",
        "properties": {
          "contributionReceived":                       { "type": "number", "example": 100000 },
          "reservesAndSurplus":                         { "type": "number", "example": 50000 },
          "securedLoans":                               { "type": "number", "example": 0 },
          "unsecuredLoans":                             { "type": "number", "example": 0 },
          "shortTermBorrowings":                        { "type": "number", "example": 0 },
          "creditorsTradePayablesAdvanceFromCustomers": { "type": "number", "example": 25000 },
          "amountOfOtherLiabilities":                   { "type": "number", "example": 0 },
          "amountOfOtherLiabilitiesDescription":        { "type": "string", "nullable": true, "example": null, "description": "Required when amountOfOtherLiabilities > 0" },
          "provisionsForTaxation":                      { "type": "number", "example": 0 },
          "provisionsForContingencies":                 { "type": "number", "example": 0 },
          "provisionsForInsurance":                     { "type": "number", "example": 0 },
          "otherProvisions":                            { "type": "number", "example": 0 },
          "contributionAndLiabilitiesTotal":            { "type": "number", "example": 175000, "description": "Sum of contribution + liabilities side" },
          "grossFixedAssets":                           { "type": "number", "example": 80000 },
          "lessDepreciationAndAmortization":            { "type": "number", "example": 5000 },
          "netFixedAssets":                             { "type": "number", "example": 75000 },
          "investments":                                { "type": "number", "example": 0 },
          "loansAndAdvances":                           { "type": "number", "example": 10000 },
          "inventories":                                { "type": "number", "example": 0 },
          "debtorsTradeReceivables":                    { "type": "number", "example": 40000 },
          "cashAndCashEquivalents":                     { "type": "number", "example": 50000 },
          "amountOfOtherAssets":                        { "type": "number", "example": 0 },
          "amountOfOtherAssetsDescription":             { "type": "string", "nullable": true, "example": null, "description": "Required when amountOfOtherAssets > 0" },
          "assestsTotal":                               { "type": "number", "example": 175000, "description": "Sum of assets side — must equal contributionAndLiabilitiesTotal" }
        }
      },
      "IncomeExpenditure": {
        "type": "object",
        "description": "Profit & Loss (Income & Expenditure) — used for both currentIncomeExpenditure and previousIncomeExpenditure in Form 8. All amounts are numbers in INR.",
        "properties": {
          "grossTurnOver":                            { "type": "number", "example": 500000 },
          "domesticTurnoverSaleOfGoodsManufactured":  { "type": "number", "example": 0 },
          "exportTurnoverSaleOfGoodsManufactured":    { "type": "number", "example": 0 },
          "domesticTurnoverSaleOfGoodsTraded":        { "type": "number", "example": 0 },
          "exportTurnoverSaleOfGoodsTraded":          { "type": "number", "example": 0 },
          "domesticTurnoverSaleOrSupplyOfServices":   { "type": "number", "example": 500000 },
          "exportTurnoverSaleOrSupplyOfServices":     { "type": "number", "example": 0 },
          "lessExciseDutyOrServiceTax":               { "type": "number", "example": 0 },
          "netTurnoverDetails":                       { "type": "number", "example": 500000 },
          "otherIncome":                              { "type": "number", "example": 0 },
          "totalIncome":                              { "type": "number", "example": 500000 },
          "rawMaterialConsumed":                      { "type": "number", "example": 0 },
          "purchasesMadeForResale":                   { "type": "number", "example": 0 },
          "increaseDecreaseInStocks":                 { "type": "number", "example": 0 },
          "consumptionOfStoresAndSpareParts":         { "type": "number", "example": 0 },
          "personnelExpenses":                        { "type": "number", "example": 200000 },
          "powerAndFuel":                             { "type": "number", "example": 12000 },
          "administrativeExpenses":                   { "type": "number", "example": 50000 },
          "sellingExpenses":                          { "type": "number", "example": 10000 },
          "insuranceExpenses":                        { "type": "number", "example": 0 },
          "depreciationAndAmortization":              { "type": "number", "example": 5000 },
          "interest":                                 { "type": "number", "example": 0 },
          "paymentToAuditors":                        { "type": "number", "example": 10000 },
          "otherExpenses":                            { "type": "number", "example": 5000 },
          "totalExpenditure":                         { "type": "number", "example": 292000 },
          "netProfitOrNetLoss":                       { "type": "number", "example": 208000 },
          "profitAfterTax":                           { "type": "number", "example": 158000 },
          "provisionForTax":                          { "type": "number", "example": 50000 },
          "profitTransferredToReservesAndSurplus":    { "type": "number", "example": 0 },
          "profitTransferredToPartnersAccount":       { "type": "number", "example": 158000 }
        }
      },
      "DMSAttachmentResponse": {
        "type": "object",
        "description": "Object returned by MCA's DMS upload endpoint. The full object is passed verbatim into the formAttachment[] array of the formService Submit payload.",
        "properties": {
          "attachmentLabel":      { "type": "string", "example": "Statement of Account" },
          "attachmentCategory":   { "type": "string", "example": "pdf" },
          "activityFileName":     { "type": "string", "example": "form8_attachment.pdf" },
          "activityFileSrcPath":  { "type": "string", "example": "/dms/folders/zcU9K123456/form8_attachment.pdf" },
          "activityFileSrcType":  { "type": "string", "example": "application/pdf" },
          "activityFileExt":      { "type": "string", "example": "pdf" },
          "activityFileSize":     { "type": "string", "example": "245678" },
          "attachmentDMSId":      { "type": "string", "example": "1-12AB34CD", "description": "Unique DMS document ID for this upload" },
          "totalNoOfPages":       { "type": "string", "example": "3" },
          "activityFileDate":     { "type": "string", "example": "11/05/2026" },
          "publicDocument":       { "type": "string", "example": "N" },
          "activityComments":     { "type": "string", "example": "" },
          "folderName":           { "type": "string", "example": "1-9ABCDEF", "description": "Equals the referenceNumber used as the DMS foldername" },
          "folderId":             { "type": "string", "example": "1-9ABCDEF" },
          "version":              { "type": "string", "example": "1" },
          "addedBy":              { "type": "string", "example": "MCAUSER123456" }
        }
      },
      "Form8SubmitRequest": {
        "type": "object",
        "description": "Form 8 (LLP Statement of Account & Solvency) submission payload. May be sent as `application/json` OR as `multipart/form-data` (in which case put this object's JSON-serialized form into the `payload` form field, plus an optional `attachmentFile` file field).",
        "required": ["llpin", "llpName", "fyFrom", "fyTo", "dscDetails", "dpCertificate", "professionalCertificate", "currentStatementOfAccount", "previousStatementOfAccount", "currentIncomeExpenditure", "previousIncomeExpenditure", "statementOfSolvency", "totalMonetaryObligationContribution", "addressObj"],
        "properties": {
          "llpin":   { "type": "string", "example": "AAJ-2620" },
          "llpName": { "type": "string", "example": "EXAMPLE CONSULTING LLP" },
          "fyFrom":  { "type": "string", "format": "date", "example": "2025-04-01" },
          "fyTo":    { "type": "string", "format": "date", "example": "2026-03-31" },
          "dscDetails": {
            "type": "object",
            "description": "Designated partners signing the form",
            "required": ["dp1Dpin", "dp2Dpin"],
            "properties": {
              "dp1Dpin": { "type": "string", "example": "01234567", "description": "DPIN of first signing Designated Partner" },
              "dp2Dpin": { "type": "string", "example": "98765432", "description": "DPIN of second signing Designated Partner" }
            }
          },
          "dpCertificate": {
            "type": "object",
            "description": "Designated partner certification block",
            "required": ["certifiedBy", "certifiedId", "certifiedName"],
            "properties": {
              "certifiedBy":   { "type": "string", "default": "Designated partner", "example": "Designated partner" },
              "certifiedId":   { "type": "string", "example": "01234567", "description": "DPIN of the certifying DP" },
              "certifiedName": { "type": "string", "example": "JOHN DOE" }
            }
          },
          "professionalCertificate": {
            "type": "object",
            "description": "Section B — Practising Professional (CA / CS / CMA) certifying the financial statements. Required for every Form 8 filing.",
            "required": ["category", "professionalType", "certificateOfPracticeNumber", "name"],
            "properties": {
              "category": {
                "type": "string",
                "description": "Full professional-type string. MCA's formService rejects short codes — must be the exact full string. The server auto-expands `CA`/`CS`/`CMA` short codes for convenience but using the full string is recommended.",
                "enum": [
                  "Chartered Accountant in whole time practice",
                  "Company Secretary in whole time practice",
                  "Cost Accountant in whole time practice"
                ],
                "example": "Company Secretary in whole time practice"
              },
              "professionalType":            { "type": "string", "enum": ["Fellow", "Associate"], "example": "Fellow" },
              "certificateOfPracticeNumber": { "type": "string", "example": "13370" },
              "name":                        { "type": "string", "example": "JANE SMITH" }
            }
          },
          "currentStatementOfAccount":  { "$ref": "#/components/schemas/BalanceSheet", "description": "Balance Sheet for the current FY (fyFrom → fyTo)" },
          "previousStatementOfAccount": { "$ref": "#/components/schemas/BalanceSheet", "description": "Balance Sheet for the previous FY" },
          "currentIncomeExpenditure":   { "$ref": "#/components/schemas/IncomeExpenditure", "description": "P&L for the current FY" },
          "previousIncomeExpenditure":  { "$ref": "#/components/schemas/IncomeExpenditure", "description": "P&L for the previous FY" },
          "statementOfSolvency": {
            "type": "object",
            "required": ["canPayDebts", "turnOver", "obligationOfContribution"],
            "properties": {
              "canPayDebts":              { "type": "string", "enum": ["is", "is not"], "default": "is", "example": "is" },
              "turnOver":                 { "type": "string", "enum": ["does not exceed", "exceeds"], "default": "does not exceed", "example": "does not exceed" },
              "obligationOfContribution": { "type": "string", "enum": ["does not exceed", "exceeds"], "default": "does not exceed", "example": "does not exceed" }
            }
          },
          "totalMonetaryObligationContribution": { "type": "string", "example": "200000", "description": "Total partner monetary obligation as registered with MCA (FDM value)" },
          "addressObj":     { "$ref": "#/components/schemas/Address" },
          "email":          { "type": "string", "example": "contact@example.com" },
          "policeStation":  { "type": "string", "example": "Connaught Place PS" },
          "hasContingentLiabilities": { "type": "string", "enum": ["Y", "N"], "default": "N", "example": "N" },
          "contingentLiabilities": {
            "type": "array",
            "default": [],
            "items": {
              "type": "object",
              "properties": {
                "particulars": { "type": "string" },
                "amount":      { "type": "number" }
              }
            }
          },
          "integrationId":     { "type": "string", "description": "Optional — provide to update an existing draft instead of creating a new SR entry" },
          "referenceNumber":   { "type": "string", "description": "Optional — Siebel CRM SR number from a previous createForm8Entry" },
          "formIntegrationId": { "type": "string", "description": "Optional — returned by Save 1; pass to skip Save 1" },
          "formVersion":       { "type": "string", "description": "Optional — usually auto-derived from the AEM page prefetch" }
        }
      },
      "Form8SubmitResponse": {
        "type": "object",
        "properties": {
          "srn":             { "type": "string", "nullable": true, "example": "M31091669", "description": "Service Request Number generated by formService Submit. Null if Submit failed (e.g. duplicate filing — see resCode 210)." },
          "integrationId":   { "type": "string", "example": "1-9ABCDEF" },
          "referenceNumber": { "type": "string", "example": "1-9ABCDEF", "description": "Siebel CRM SR number — also used as the DMS foldername for attachments" },
          "formServiceSave": {
            "type": "object",
            "description": "Result of the first Save call (operation=Save, formIntegrationId=861 placeholder). Returns the real formIntegrationId for use in subsequent Save 2 / Submit.",
            "properties": {
              "formIntegrationId": { "type": "string" },
              "integrationId":     { "type": "string" },
              "error":             { "type": "string" }
            }
          },
          "formServiceSubmit": {
            "type": "object",
            "description": "Raw formService Submit response. Check resCode and validationResponse to detect duplicate filings (resCode=210, SubmissionRestricted=Y).",
            "properties": {
              "srn":                { "type": "string", "nullable": true },
              "resCode":            { "type": "string", "example": "200", "description": "200=success; 210=technical error / duplicate filing" },
              "srnStatus":          { "type": "string", "example": "Pending Approval" },
              "integrationId":      { "type": "string" },
              "formIntegrationId":  { "type": "string" },
              "validationResponse": {
                "type": "object",
                "properties": {
                  "SubmissionRestricted": { "type": "string", "enum": ["Y", "N"], "description": "Y when MCA blocks the submission (commonly because Form 8 is already filed for this LLPIN+FY)" }
                }
              }
            }
          },
          "createFormEntryError": { "type": "string", "nullable": true },
          "attachmentUpload":     {
            "oneOf": [
              { "$ref": "#/components/schemas/DMSAttachmentResponse" },
              { "type": "object", "properties": { "error": { "type": "string" } } }
            ],
            "nullable": true,
            "description": "DMS upload response when an attachment was included; null otherwise"
          },
          "submission":   { "type": "object", "properties": { "status": { "type": "integer" }, "hasData": { "type": "boolean" } }, "description": "Result of internalsubmit.jsp — Akamai may block this with 403, but is non-fatal since the SRN is generated earlier." },
          "pdf":          { "type": "object", "nullable": true, "properties": { "status": { "type": "integer" }, "error": { "type": "string" } } },
          "dmsid":        { "type": "string", "nullable": true, "description": "DMS document ID for the generated PDF — pass to /api/form8/download-pdf?dmsid=" },
          "downloadUrl":  { "type": "string", "nullable": true, "example": "/api/form8/download-pdf?dmsid=12345" },
          "confirmation": { "type": "object", "nullable": true, "description": "Result of the ACK email send" },
          "_debug":       { "type": "object", "description": "Diagnostic fields: userId, formIntegrationId, certifiedBy/Id, profCategory/Membership, dp1Dpin, dp2Dpin, stmtDate, BS 'Others' description verification, saveTwo result, formAttachmentCount" }
        }
      },
      "MDSCaptchaResponse": {
        "type": "object",
        "description": "Captcha challenge for Master Data Search. Image and audio are returned as data URLs ready to embed in `<img>` / `<audio>` tags. The `preCT` is a single-use HMAC token tied to this captcha — echo it back in the next /lookup or /search call.",
        "properties": {
          "image": { "type": "string", "nullable": true, "example": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...", "description": "PNG captcha image as a data URL" },
          "audio": { "type": "string", "nullable": true, "example": "data:audio/wav;base64,UklGRiQAAABXQVZF...", "description": "WAV audio captcha as a data URL (accessibility)" },
          "preCT": { "type": "string", "example": "rejr7Sh76S38nQK6yYwAfFQqXn6f...", "description": "Single-use HMAC token tied to this captcha. Pass back in /lookup or /search." }
        },
        "required": ["preCT"]
      },
      "MDSLookupRequest": {
        "type": "object",
        "required": ["id", "type", "userInput", "preCT"],
        "properties": {
          "id":        { "type": "string", "example": "U74999RJ2018PTC060472", "description": "CIN (21-char) or LLPIN (e.g. AAJ-2620)" },
          "type":      { "type": "string", "enum": ["cin", "llpin"], "example": "cin" },
          "userInput": { "type": "string", "example": "1DbF0q", "description": "Captcha solution typed by the user" },
          "preCT":     { "type": "string", "example": "rejr7Sh76S38nQK6yYwAfFQqXn6f...", "description": "Token from GET /api/master/captcha" }
        }
      },
      "MDSSearchRequest": {
        "type": "object",
        "required": ["query", "type", "userInput", "preCT"],
        "properties": {
          "query":     { "type": "string", "example": "fastlegal", "description": "Partial company / LLP name" },
          "type":      { "type": "string", "enum": ["company", "llp"], "example": "company" },
          "userInput": { "type": "string", "example": "1DbF0q" },
          "preCT":     { "type": "string", "example": "rejr7Sh76S38nQK6yYwAfFQqXn6f..." }
        }
      },
      "MDSAddress": {
        "type": "object",
        "description": "An entry in `companyData.MCAMDSCompanyAddress[]` — registered office and other addresses on file.",
        "properties": {
          "streetAddress":  { "type": "string", "example": "SHOP NO. K-50, LGF, REVERA" },
          "streetAddress2": { "type": "string", "example": "PLOT NO 1-8, RAM CHANDRAPURA JAGATPURA" },
          "addressType":    { "type": "string", "example": "Registered" },
          "locality":       { "type": "string", "example": "Sitapura Industrial Area" },
          "district":       { "type": "string", "example": "Jaipur" },
          "city":           { "type": "string", "example": "Jaipur" },
          "state":          { "type": "string", "example": "Rajasthan" },
          "country":        { "type": "string", "example": "India" },
          "postalCode":     { "type": "string", "example": "302022" },
          "activeStatus":   { "type": "string", "example": "Y" }
        }
      },
      "MDSDirector": {
        "type": "object",
        "description": "An entry in `data.directorData[]`. Naming is per MCA's payload — note CamelCase + ALLCAPS mix.",
        "properties": {
          "DIN":                  { "type": "string", "example": "07591685" },
          "PAN":                  { "type": "string", "example": "ABCDE1234F" },
          "dateOfAppointment":    { "type": "string", "example": "2018-04-12" },
          "DirectorDisqualified": { "type": "string", "example": "N" },
          "FirstName":            { "type": "string", "example": "AMIT" },
          "MiddleName":           { "type": "string", "example": "" },
          "LastName":             { "type": "string", "example": "SHARMA" },
          "MCAUserRole":          { "type": "array", "items": { "type": "object" }, "description": "Roles the director holds (Director / Designated Partner / etc.) with appointment metadata" }
        }
      },
      "MDSMasterDataResponse": {
        "type": "object",
        "description": "Parsed JSON straight from MCA's MDSMasterDataServlet. Top-level fields wrap a `data` object with `companyData` and `directorData[]`.",
        "properties": {
          "error":   { "type": "string", "nullable": true, "example": null },
          "message": { "type": "string", "nullable": true, "example": "Success" },
          "data": {
            "type": "object",
            "properties": {
              "companyData": {
                "type": "object",
                "description": "Master record. The full payload contains many fields; the most useful are documented below — anything not listed should be treated as additional fields passed straight from MCA.",
                "properties": {
                  "CIN":                     { "type": "string", "example": "U74999RJ2018PTC060472" },
                  "company":                 { "type": "string", "example": "FASTLEGAL TECHNOLOGIES PRIVATE LIMITED" },
                  "companyType":             { "type": "string", "example": "Company limited by shares" },
                  "dateOfIncorporation":     { "type": "string", "example": "2018-04-12" },
                  "llpStatus":               { "type": "string", "example": "Active", "description": "Reused field name — populated for both companies and LLPs" },
                  "authorisedCapital":       { "type": "string", "example": "100000" },
                  "paidUpCapital":           { "type": "string", "example": "100000" },
                  "rocName":                 { "type": "string", "example": "RoC-Jaipur" },
                  "MCAMDSCompanyAddress":    { "type": "array", "items": { "$ref": "#/components/schemas/MDSAddress" } },
                  "balanceSheet3years":      { "type": "array", "items": { "type": "object" }, "description": "Last three years' balance sheet filing summary" },
                  "annualReturns3years":     { "type": "array", "items": { "type": "object" }, "description": "Last three years' annual return filing summary" }
                },
                "additionalProperties": true
              },
              "directorData": {
                "type": "array",
                "items": { "$ref": "#/components/schemas/MDSDirector" }
              }
            }
          }
        }
      },
      "DashboardTab": {
        "type": "object",
        "description": "One tab in the My Applications dashboard. Tab codes are short uppercase strings used by MCA's backend to filter the filings list.",
        "properties": {
          "code": {
            "type": "string",
            "enum": ["CR", "UP", "PS", "AR", "CL", "NO", "RN", "CX"],
            "description": "MCA tab code. CR=Receipts (default), UP=Under Processing, PS=Payment Status, AR=Approved, CL=Certificates, NO=Letters/Notices, RN=Rejected, CX=Cancelled.",
            "example": "CR"
          },
          "label":       { "type": "string", "example": "Receipts", "description": "Human-readable label for the tab" },
          "description": { "type": "string", "example": "Challan receipts for all filings (purpose:\"Receipt\")" }
        },
        "required": ["code", "label", "description"]
      },
      "DashboardRow": {
        "type": "object",
        "description": "One row from MCA's My Applications list. The shape mirrors MCA's `/bin/mca/applicationHistory` payload — the most useful fields are documented below; the rest are returned as-is via `additionalProperties: true`.",
        "properties": {
          "srn":                  { "type": "string", "example": "M30858649", "description": "MCA Service Request Number (primary identifier for the filing)" },
          "srNumber":             { "type": "string", "example": "1-25371230946", "description": "Alternate long-form SRN reference used by some MCA backends" },
          "integrationId":        { "type": "string", "example": "1-25371230946", "description": "Internal MCA integration identifier" },
          "dmsId":                { "type": "string", "example": "647181288", "description": "Document Management System ID. Non-zero ⇒ a PDF is downloadable via /api/dashboard/download. `0` means MCA has not yet generated the document." },
          "formName":             { "type": "string", "example": "Form 11", "description": "MCA form name (e.g. \"Form 11\", \"Form 8\", \"INC-22\", \"CHG-1\")" },
          "entityName":           { "type": "string", "example": "FASTLEGAL TECHNOLOGIES PRIVATE LIMITED", "description": "Company / LLP name as registered with MCA" },
          "identificationNumber": { "type": "string", "example": "U74999RJ2018PTC060472", "description": "CIN (companies) or LLPIN (LLPs)" },
          "srStatus":             { "type": "string", "example": "Approved", "description": "Current MCA processing status (e.g. Approved, Under Processing, Rejected, Cancelled)" },
          "srLastUpdated":        { "type": "string", "example": "10/05/2026", "description": "Last status update date in DD/MM/YYYY format" },
          "transactionDate":      { "type": "string", "example": "01/05/2026", "description": "Date the SRN was created (DD/MM/YYYY)" },
          "expiryDate":           { "type": "string", "example": "31/05/2026", "description": "Resubmission / payment expiry date (DD/MM/YYYY), if applicable" },
          "paymentAmount":        { "type": "string", "example": "100", "description": "Fees paid for this filing in INR" },
          "purpose":              { "type": "string", "example": "Receipt", "description": "MCA-assigned purpose tag — \"Receipt\" (CR tab), \"Default\" (UP tab), \"Certificates\" (CL tab), etc." },
          "submittedBy":          { "type": "string", "example": "MCAUSER123456", "description": "MCA user ID that submitted the filing" }
        },
        "additionalProperties": true
      },
      "DashboardListResponse": {
        "type": "object",
        "description": "Wrapped response from GET /api/dashboard. The raw MCA `data` array is passed through; `tab`, `tabLabel` and `count` are added by this server for convenience.",
        "properties": {
          "tab":      { "type": "string", "example": "CR", "description": "Echo of the requested tab code" },
          "tabLabel": { "type": "string", "example": "Receipts", "description": "Human-readable label for the tab" },
          "count":    { "type": "integer", "example": 12, "description": "Number of rows returned in `data`" },
          "data":     { "type": "array", "items": { "$ref": "#/components/schemas/DashboardRow" } },
          "message":  { "type": "string", "example": "Data fetched Successfully", "description": "Pass-through message from MCA" }
        }
      },
      "BulkDownloadRequest": {
        "type": "object",
        "description": "Body for POST /api/dashboard/bulk-download. Provide an `items` array (max 50). Each item must carry `dmsid` (preferred) or `srn` (the server will resolve dmsId via MCA polling). `filename` is the base name used inside the resulting ZIP archive — collisions get a `__2`, `__3`, … suffix automatically.",
        "required": ["items"],
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "description": "List of documents to fetch. Maximum 50 items per request.",
            "items": {
              "type": "object",
              "properties": {
                "dmsid":    { "type": "string", "example": "647181288", "description": "DMS ID from a DashboardRow (preferred — skips the SRN→dmsId resolution round-trip)" },
                "srn":      { "type": "string", "example": "M30858649", "description": "Service Request Number — used to resolve dmsId if `dmsid` is absent" },
                "filename": { "type": "string", "example": "ack_Form_11_2026_M30858649", "description": "Base filename inside the ZIP (no extension). Recommended: `ack_<FormName>_<Year>_<SRN>` for receipts, `<FormName>_<Year>_<SRN>` for other forms." }
              }
            }
          }
        }
      },
      "Dpt3Purpose": {
        "type": "object",
        "description": "One of the four statutory purposes for filing DPT-3.",
        "properties": {
          "code":  { "type": "string", "enum": ["A", "B", "C", "D"], "example": "C" },
          "label": { "type": "string", "example": "Particulars of transactions by a company not considered as deposit as per rule 2(1)(c) of the Companies (Acceptance of Deposit) Rules, 2014" },
          "sections": {
            "type": "object",
            "description": "Which form sections the UI should surface for this purpose.",
            "properties": {
              "particularsOfReceipt": { "type": "boolean", "example": true,  "description": "True for A, C, D — the 49-row receipts table is required" },
              "depositReturn":        { "type": "boolean", "example": false, "description": "True for B, D — networth + deposits + credit-rating + auditor sections required" },
              "auditorCertificate":   { "type": "boolean", "example": false, "description": "True for B, D — auditor certificate required" }
            }
          }
        }
      },
      "Dpt3ReceiptCategory": {
        "type": "object",
        "description": "One of MCA's 49 statutory `amountRecievedType` categories used in `particularsOfReceipt[]`. The 0-based `index` corresponds to its position in the form table.",
        "properties": {
          "index": { "type": "integer", "example": 0, "description": "0-based position in the 49-row table" },
          "label": { "type": "string", "example": "Any amount received from the Central Government / State Government / local authority / statutory authority", "description": "Exact MCA label — must be used verbatim as `amountRecievedType`" }
        }
      },
      "Dpt3CategoriesResponse": {
        "type": "object",
        "description": "Static catalogue: 4 purposes + 49 receipt categories + 5 most-common categories.",
        "properties": {
          "purposes":          { "type": "array", "items": { "$ref": "#/components/schemas/Dpt3Purpose" } },
          "receiptCategories": { "type": "array", "items": { "$ref": "#/components/schemas/Dpt3ReceiptCategory" } },
          "quickPick":         { "type": "array", "items": { "type": "string" }, "description": "The 5 most-common categories, useful for a quick-pick UI", "example": ["Loan from directors", "Loan from banks", "Customer advances", "Loan from other companies", "Loan from scheduled banks"] }
        }
      },
      "Dpt3CompaniesResponse": {
        "type": "object",
        "description": "List of companies the logged-in MCA user is associated with.",
        "properties": {
          "userId":   { "type": "string", "example": "MCAUSER123456" },
          "userInfo": { "type": "object", "description": "Raw user info from MCA — includes name, email, roles" },
          "companies": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "cin":  { "type": "string", "example": "U74999RJ2018PTC060472" },
                "role": { "type": "string", "example": "DIRECTOR" }
              }
            }
          }
        }
      },
      "Dpt3PrefillResponse": {
        "type": "object",
        "description": "Master data for a CIN, shaped for DPT-3's company section.",
        "properties": {
          "cin":               { "type": "string", "example": "U74999RJ2018PTC060472" },
          "companyName":       { "type": "string", "example": "FASTLEGAL TECHNOLOGIES PRIVATE LIMITED" },
          "companytype":       { "type": "string", "example": "Company limited by shares" },
          "companygov":        { "type": "string", "enum": ["Y", "N"], "example": "N", "description": "Y = government company, N = non-government (Indian-origin)" },
          "companyobject":     { "type": "string", "example": "Business and management consultancy activities" },
          "dateOfIncorporation": { "type": "string", "example": "07/06/2018" },
          "email":             { "type": "string", "example": "info@fastlegal.in" },
          "paidupCapital":     { "type": "string", "example": "100000" },
          "authorisedCapital": { "type": "string", "example": "100000" },
          "address": {
            "type": "object",
            "properties": {
              "line1":         { "type": "string", "example": "SHOP NO. K-50, LGF, REVERA" },
              "line2":         { "type": "string", "nullable": true, "example": "PLOT NO 1-8, RAM CHANDRAPURA JAGATPURA" },
              "country":       { "type": "string", "example": "India" },
              "pincode":       { "type": "integer", "example": 302022 },
              "arealocality":  { "type": "string", "example": "Sitapura Industrial Area" },
              "city":          { "type": "string", "example": "Jaipur" },
              "district":      { "type": "string", "example": "Jaipur" },
              "state":         { "type": "string", "example": "Rajasthan" },
              "companymailid": { "type": "string", "example": "info@fastlegal.in" }
            }
          },
          "raw": { "type": "object", "description": "Raw MCA master-data response — useful for fields not surfaced above" }
        }
      },
      "Dpt3ReceiptRow": {
        "type": "object",
        "description": "One row of the `particularsOfReceipt[]` table. All amount fields are STRINGS — that's what MCA expects. NOTE: the `amountRecievedType` typo (\"Recieved\" instead of \"Received\") is MCA's official spelling and must be matched exactly.",
        "properties": {
          "amountRecievedType":              { "type": "string", "example": "Loan from directors", "description": "Must match one of the 49 labels from `/api/dpt3/categories` exactly (MCA spelling, typo and all)." },
          "openingBalance":                  { "type": "string", "example": "0" },
          "additionalLoan":                  { "type": "string", "example": "500000" },
          "repaidDuringYear":                { "type": "string", "example": "0" },
          "otherAdjustment":                 { "type": "string", "example": "0" },
          "closingBalance":                  { "type": "string", "example": "500000" },
          "loanOutstandingForLTETOneYear":   { "type": "string", "example": "500000", "description": "Outstanding for less-than-or-equal-to one year" },
          "loanOutstandingForLTThreeYearMTOneYear": { "type": "string", "example": "0", "description": "Outstanding for >1 year and <=3 years" },
          "loanOutstandingForMOTThreeYear":  { "type": "string", "example": "0", "description": "Outstanding for more than three years" }
        }
      },
      "Dpt3SubmitRequest": {
        "type": "object",
        "description": "Request body for `/api/dpt3/save-only` and `/api/dpt3/submit`. Optional sections (`networth`, `deposits`, `creditRating`, `auditor`, `particularsOfReceipt`) are surfaced based on `purposeCode` — see the section-visibility flags returned by `/api/dpt3/categories`.",
        "required": ["cin", "companyName", "purposeCode", "returnfilingperiod"],
        "properties": {
          "cin":         { "type": "string", "example": "U74999RJ2018PTC060472" },
          "companyName": { "type": "string", "example": "FASTLEGAL TECHNOLOGIES PRIVATE LIMITED" },
          "purposeCode": {
            "type": "string",
            "enum": ["A", "B", "C", "D"],
            "example": "C",
            "description": "Statutory purpose:\n- **A**: One-time return for outstanding money / loan not considered as deposits\n- **B**: Return of Deposit (annual)\n- **C**: Particulars of transactions not considered as deposit per rule 2(1)(c) — most common\n- **D**: Return of Deposit AND particulars of non-deposit transactions"
          },
          "returnfilingperiod":   { "type": "string", "example": "03/31/2026", "description": "Period end date in MM/DD/YYYY (typically the FY end, 03/31/YYYY)" },
          "companytype":          { "type": "string", "example": "Company limited by shares" },
          "companygov":           { "type": "string", "enum": ["Y", "N"], "example": "N" },
          "companyobject":        { "type": "string", "example": "Business and management consultancy activities" },
          "companydepositpublic": { "type": "string", "enum": ["Y", "N"], "example": "N", "description": "Whether the company is eligible to accept deposits from the public" },
          "eventDate":            { "type": "string", "example": "03/31/2026", "description": "Event date — MM/DD/YYYY. Defaults to `returnfilingperiod` when omitted." },
          "address":              { "type": "object", "description": "Registered-office address (see `Dpt3PrefillResponse.address` for shape)" },
          "networth":             { "type": "object", "description": "Net worth section — only used for purposes B and D" },
          "deposits":             { "type": "object", "description": "Deposits section — only used for purposes B and D" },
          "creditRating":         { "type": "object", "description": "Credit rating section — only used for purpose B" },
          "auditor":              { "type": "object", "description": "Auditor section — only used for purposes B and D" },
          "declaration":          { "type": "object", "description": "Declaration / signatory block" },
          "particularsOfReceipt": {
            "type": "array",
            "description": "Subset of receipt rows (only used for purposes A, C, D). The server pads this to 49 rows server-side before sending to MCA, so you may send 1 to 49 rows — any unused categories are filled with zeros.",
            "items": { "$ref": "#/components/schemas/Dpt3ReceiptRow" }
          },
          "attachmentFilenames": {
            "type": "object",
            "description": "Echo back filenames returned by prior `/api/dpt3/upload-attachment` calls. For inline upload, use multipart on `/submit` with field names `copyOfMinutesOfDecision`, `copyOfMinutesOfDecision1`, `copyOfMinutesOfDecision2`.",
            "properties": {
              "copyOfMinutesOfDecision":  { "type": "string", "example": "board-resolution.pdf" },
              "copyOfMinutesOfDecision1": { "type": "string" },
              "copyOfMinutesOfDecision2": { "type": "string" }
            }
          },
          "formAttachmentMeta": {
            "type": "array",
            "description": "REQUIRED when using the incremental `/upload-attachment` → JSON `/submit` flow. Each entry is the verbatim DMS response from `/upload-attachment` (`attachmentLabel`, `attachmentDMSId`, `folderId`, `activityFileSrcPath`, etc.). MCA uses this array to link the stored PDF in DMS back to the SRN — without it, the application-history page shows the filename but the attachment slot stays blank. The inline-multipart `/submit` flow populates this automatically.",
            "items": { "type": "object" }
          },
          "integrationId":     { "type": "string", "example": "1-BPK3G22", "description": "Resume an existing draft — usually returned by a prior `/save-only`" },
          "referenceNumber":   { "type": "string", "example": "1-25490013194" },
          "formintegrationid": { "type": "string", "example": "1-BPK3G24" }
        }
      },
      "Dpt3ValidationError": {
        "type": "object",
        "description": "One entry of MCA's per-field validation. Extracted from `validationResponseBody[]` by the route for convenience.",
        "properties": {
          "code":    { "type": "string", "nullable": true, "example": "ER16_DPT3", "description": "MCA's `alertCategory` — useful programmatic identifier. Common: `ER16_DPT3`/`ER17_DPT3` (duplicate filing)." },
          "message": { "type": "string", "example": "DPT-3 form for the financial year 2026 is already filed by the user as per MCA records." }
        }
      },
      "Dpt3ErrorResponse": {
        "type": "object",
        "description": "Returned by `/api/dpt3/save-only` and `/api/dpt3/submit` when MCA rejects the request. Watch for `error: \"Duplicate filing — ...\"` when the company has already filed DPT-3 for this FY.",
        "properties": {
          "error":  { "type": "string", "example": "Duplicate filing — MCA already has a DPT-3 for this CIN + FY" },
          "detail": { "type": "string", "description": "One-line summary of MCA's alert(s). For multiple errors, items are joined with `|`." },
          "validationErrors": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Dpt3ValidationError" },
            "description": "MCA's per-field alerts extracted from `validationResponseBody[]`. Show these directly to the user."
          },
          "submissionRestricted": { "type": "string", "enum": ["Y", "N"], "description": "When `Y`, MCA blocked the submit (usually a validation failure)." },
          "hint": { "type": "string", "description": "Actionable next step for the caller (e.g. \"Withdraw the existing DPT-3 SRN on MCA portal...\")" },
          "field": { "type": "string", "nullable": true, "description": "For 400 responses — the specific field name that failed our pre-MCA validation (e.g. `declaration.resolutionNumber`)." },
          "fix":   { "type": "string", "nullable": true, "description": "For 400 responses — concrete fix instruction (e.g. 'Replace with a plain ASCII identifier')." },
          "integrationId":     { "type": "string", "nullable": true },
          "referenceNumber":   { "type": "string", "nullable": true },
          "formintegrationid": { "type": "string", "nullable": true },
          "mca": { "type": "object", "description": "Raw MCA response for advanced debugging.", "properties": { "resCode": { "type": "string" }, "raw": { "type": "object" } } }
        }
      },
      "Dpt3SubmitResponse": {
        "type": "object",
        "description": "Common response for `/save-only` and `/submit`.",
        "properties": {
          "success":   { "type": "boolean", "example": true },
          "operation": { "type": "string", "enum": ["Save", "Submit"], "example": "Submit" },
          "srn":       { "type": "string", "nullable": true, "example": "AC3417914", "description": "Service Request Number — only returned for successful Submit" },
          "srnStatus": { "type": "string", "nullable": true, "example": "Pending for DSC Upload and Payment" },
          "integrationId":     { "type": "string", "example": "1-BPK3G22" },
          "referenceNumber":   { "type": "string", "example": "1-25490013194" },
          "formintegrationid": { "type": "string", "example": "1-BPK3G24" },
          "attachmentUploads": { "type": "array", "items": { "type": "object" }, "description": "Per-file DMS upload result (only present when `/submit` was called with multipart files)" },
          "saveResult": {
            "type": "object",
            "properties": {
              "resCode": { "type": "string", "example": "200" },
              "message": { "type": "string" },
              "error":   { "type": "string", "nullable": true },
              "validationResponse": {
                "type": "object",
                "description": "MCA's per-field validation result. When `submissionRestricted = 'Y'`, look in `validationResponseBody[]` for the actual field errors.",
                "properties": {
                  "submissionRestricted": { "type": "string", "enum": ["Y", "N"], "example": "N" },
                  "validationResponseBody": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "alertType":        { "type": "string", "example": "E", "description": "E = error, W = warning" },
                        "alertDescription": { "type": "string", "example": "Net worth as on date of application is mandatory" },
                        "alertCategory":    { "type": "string", "example": "Field" }
                      }
                    }
                  }
                }
              }
            }
          },
          "pdf":          { "type": "object", "nullable": true, "description": "AsyncGeneratePdf result (best-effort, only on successful Submit)" },
          "confirmation": { "type": "object", "nullable": true, "description": "FormSubmitConfirmation result (best-effort, only on successful Submit)" }
        }
      }
    }
  },
  "security": [{ "SessionId": [] }],
  "paths": {

    "/api/auth/inject-session": {
      "post": {
        "tags": ["Auth"],
        "summary": "Inject MCA browser session cookies",
        "description": "The primary authentication method. Copy all cookies from your logged-in MCA browser session (DevTools → Application → Cookies) and paste them here.\n\nAfter injection the server immediately calls MCA's session endpoint with full browser headers to resolve your `userId`. The userId is cached server-side and returned in the response — it's needed for partner prefill and form submission.\n\nThe returned `sessionId` must be sent as `X-Session-Id` header in all subsequent requests.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["cookies"],
                "properties": {
                  "cookies": {
                    "type": "string",
                    "description": "Raw MCA cookie header string copied from browser DevTools",
                    "example": "cookiesession1=ABC123; sessionID=xyz789; _csrf=tok123; deviceId=dev456"
                  },
                  "userId": {
                    "type": "string",
                    "description": "Optional: MCA user ID. Provide this if session check keeps failing (e.g. on cloud servers with IP restrictions). Find it in MCA portal → My Profile.",
                    "example": "MCAUSER123456"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session injected successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":    { "type": "boolean", "example": true },
                    "sessionId":  { "type": "string",  "example": "sess_abc123", "description": "Use this in X-Session-Id header for all subsequent requests" },
                    "userId":     { "type": "string",  "example": "MCAUSER123456", "description": "MCA user ID resolved from session. Empty string if MCA blocked the check." },
                    "isLoggedIn": { "type": "boolean", "example": true, "description": "True if MCA confirmed the session is active" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing cookies field", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/auth/session": {
      "get": {
        "tags": ["Auth"],
        "summary": "Check current session status",
        "description": "Returns the current session state. Always returns HTTP 200 — check `isLoggedIn` and `hasInjectedCookies` in the response body.\n\n- `isLoggedIn: true` — MCA confirmed the session is active and returned user info\n- `hasInjectedCookies: true, isLoggedIn: false` — cookies are loaded server-side but MCA session check was blocked (IP restriction). Filing APIs still work.\n- Both false — no session, call inject-session first.",
        "responses": {
          "200": {
            "description": "Session status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "isLoggedIn":        { "type": "boolean" },
                    "hasInjectedCookies":{ "type": "boolean" },
                    "userId":            { "type": "string"  },
                    "firstName":         { "type": "string"  },
                    "lastName":          { "type": "string"  },
                    "emailId":           { "type": "string"  },
                    "mobile":            { "type": "string"  },
                    "sessionId":         { "type": "string"  }
                  }
                }
              }
            }
          }
        }
      }
    },

    "/api/auth/captcha": {
      "get": {
        "tags": ["Auth"],
        "summary": "Get CAPTCHA image (for credential-based login)",
        "description": "Alternative to inject-session. Fetch CAPTCHA, then POST credentials to /api/auth/login. Prefer inject-session for reliability.",
        "security": [],
        "responses": {
          "200": {
            "content": { "application/json": { "schema": { "type": "object", "properties": {
              "image":     { "type": "string", "description": "data:image/png;base64,... URL ready for <img src>" },
              "sessionId": { "type": "string" }
            }}}}
          }
        }
      }
    },

    "/api/auth/login": {
      "post": {
        "tags": ["Auth"],
        "summary": "Login with MCA credentials + CAPTCHA",
        "description": "Alternative to inject-session. Load CAPTCHA first, then call this endpoint.",
        "security": [],
        "requestBody": {
          "content": { "application/json": { "schema": { "type": "object", "required": ["username","password","captcha"], "properties": {
            "username": { "type": "string" },
            "password": { "type": "string", "description": "Plain text password — server hashes it with SHA-1 before sending to MCA" },
            "captcha":  { "type": "string" }
          }}}}
        },
        "responses": {
          "200": { "description": "Login result from MCA (check resCode field)" }
        }
      }
    },

    "/api/auth/logout": {
      "post": {
        "tags": ["Auth"],
        "summary": "Logout and clear server-side session",
        "responses": { "200": { "description": "Logged out" } }
      }
    },

    "/api/llp/master": {
      "get": {
        "tags": ["LLP"],
        "summary": "LLP master information",
        "description": "Fetch LLP name, registered address, status, PAN, ROC, date of incorporation, and business activity codes from MCA's company database.\n\nWorks for any LLP registered with MCA. Does not require filing-related session state — basic company info is returned even with minimal session.",
        "parameters": [
          {
            "name": "llpin",
            "in": "query",
            "required": true,
            "schema": { "type": "string", "pattern": "^[A-Z]{3}-\\d{4}$" },
            "description": "LLP Identification Number",
            "example": "AAJ-2620"
          }
        ],
        "responses": {
          "200": {
            "description": "LLP master data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "llpin":                      { "type": "string",  "example": "AAJ-2620" },
                    "name":                       { "type": "string",  "example": "EXAMPLE CONSULTING LLP" },
                    "status":                     { "type": "string",  "example": "Active", "description": "Active | Strike Off | Under Liquidation | Dissolved" },
                    "email":                      { "type": "string",  "example": "contact@example.com" },
                    "phone":                      { "type": "string",  "example": "9876543210" },
                    "pan":                        { "type": "string",  "example": "ABCDE1234F" },
                    "rocCode":                    { "type": "string",  "example": "RD-NW" },
                    "rocName":                    { "type": "string",  "example": "Registrar of Companies, Delhi" },
                    "dateOfIncorporation":        { "type": "string",  "format": "date", "example": "2020-01-15" },
                    "numberOfPartners":           { "type": "string",  "example": "2" },
                    "numberOfDesignatedPartners": { "type": "string",  "example": "2" },
                    "businessActivity":           { "type": "string",  "example": "Management Consulting" },
                    "nicCode1":                   { "type": "string",  "example": "7010" },
                    "nicCode1Desc":               { "type": "string",  "example": "Activities of head offices" },
                    "address":                    { "$ref": "#/components/schemas/Address" },
                    "addressString":              { "type": "string",  "example": "Plot 12, Sector 5, Connaught Place, New Delhi, Central Delhi, Delhi, 110001" },
                    "policeStation":              { "type": "string",  "example": "Connaught Place PS" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing llpin" },
          "404": { "description": "LLP not found in MCA database" },
          "502": { "description": "MCA API error" }
        }
      }
    },

    "/api/llp/partners": {
      "get": {
        "tags": ["LLP"],
        "summary": "LLP partner list for a financial year",
        "description": "Returns all partners and designated partners of an LLP for the specified financial year.\n\nData source priority:\n1. **annualReturn API** — most accurate, requires userId from active session\n2. **formService Prefill** — works when FY is not yet filed\n3. **Next-FY Prefill fallback** — when current FY is already filed (resCode 206), automatically retries with FY+1 to get current partner data\n\nIf `totalPartners` is 0, inject/re-inject your MCA session and retry.",
        "parameters": [
          {
            "name": "llpin",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "example": "AAJ-2620"
          },
          {
            "name": "fy_from",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "format": "date", "default": "2025-04-01" },
            "description": "Financial year start date (YYYY-MM-DD). Indian FY typically starts April 1.",
            "example": "2025-04-01"
          },
          {
            "name": "fy_to",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "format": "date", "default": "2026-03-31" },
            "description": "Financial year end date (YYYY-MM-DD). Indian FY typically ends March 31.",
            "example": "2026-03-31"
          }
        ],
        "responses": {
          "200": {
            "description": "Partner list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "llpin":                    { "type": "string",  "example": "AAJ-2620" },
                    "financialYearFrom":        { "type": "string",  "example": "2025-04-01" },
                    "financialYearTo":          { "type": "string",  "example": "2026-03-31" },
                    "partners":                 { "type": "array", "items": { "$ref": "#/components/schemas/Partner" } },
                    "totalPartners":            { "type": "integer", "example": 2 },
                    "totalDesignatedPartners":  { "type": "integer", "example": 2 },
                    "totalObligation":          { "type": "number",  "example": 200000 },
                    "totalContribution":        { "type": "number",  "example": 200000 },
                    "source":                   { "type": "string",  "example": "annualReturn", "description": "annualReturn | formServicePrefill | formServicePrefill/nextFY | none" }
                  }
                }
              }
            }
          }
        }
      }
    },

    "/api/llp/dpin/{dpin}": {
      "get": {
        "tags": ["LLP"],
        "summary": "Resolve DIN / DPIN to person's name",
        "description": "Looks up a Director Identification Number (DIN), Designated Partner Identification Number (DPIN), or CA Membership Number in MCA's database and returns the person's name.\n\nUsed to auto-fill signer and certifier names in all MCA form types.\n\nRequires: `_csrf` cookie in injected session.",
        "parameters": [
          {
            "name": "dpin",
            "in": "path",
            "required": true,
            "schema": { "type": "string", "minLength": 6 },
            "description": "8-digit DIN or DPIN, or CA Membership Number",
            "example": "01234567"
          }
        ],
        "responses": {
          "200": {
            "description": "Person details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dpin":        { "type": "string",  "example": "01234567" },
                    "found":       { "type": "boolean", "example": true },
                    "name":        { "type": "string",  "example": "JOHN DOE" },
                    "status":      { "type": "string",  "example": "Approved" },
                    "designation": { "type": "string",  "example": "Designated Partner" }
                  }
                }
              }
            }
          },
          "401": { "description": "No _csrf cookie — inject session first" }
        }
      }
    },

    "/api/form11/prefill": {
      "get": {
        "tags": ["Form 11"],
        "summary": "Prefill Form 11 — LLP details + partner list",
        "description": "Single call to fetch all data needed to populate Form 11 (LLP Annual Return):\n- LLP name, status, address, email, police station\n- Business classification and NIC activity code\n- Full partner list with DPINs, contributions, dates\n\nData is fetched from three MCA sources in parallel and merged:\n1. `annualReturn` API — partners and business fields\n2. `formServicePrefill` — saved draft / prefill data for the FY\n3. `companyInfo` — registered address (always works)\n\nIf `formServicePrefill` returns resCode 206 (FY already filed), automatically retries with the next FY to get current partner data.\n\nThe response can be used directly as the body for `POST /api/form11/submit`.",
        "parameters": [
          {
            "name": "llpin",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "example": "AAJ-2620"
          },
          {
            "name": "fy_from",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "format": "date", "default": "2025-04-01" },
            "example": "2025-04-01"
          },
          {
            "name": "fy_to",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "format": "date", "default": "2026-03-31" },
            "example": "2026-03-31"
          }
        ],
        "responses": {
          "200": {
            "description": "Prefill data for Form 11",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "llpin":                     { "type": "string", "example": "AAJ-2620" },
                    "nameOfLLP":                 { "type": "string", "example": "EXAMPLE CONSULTING LLP" },
                    "llpStatus":                 { "type": "string", "example": "Active" },
                    "address":                   { "type": "string", "example": "Plot 12, Sector 5, New Delhi, Delhi, 110001", "description": "Full address as a single string" },
                    "addressObj":                { "$ref": "#/components/schemas/Address" },
                    "email":                     { "type": "string", "example": "contact@example.com" },
                    "policeStation":             { "type": "string", "example": "Connaught Place PS" },
                    "dateOfIncorporation":       { "type": "string", "example": "2020-01-15" },
                    "financialYearFrom":         { "type": "string", "example": "2025-04-01" },
                    "financialYearTo":           { "type": "string", "example": "2026-03-31" },
                    "turnoverExceeds5Cr":        { "type": "string", "enum": ["Y","N"], "example": "N" },
                    "businessClassification":    { "type": "string", "enum": ["Business","Occupation","Profession","Service","Others"], "example": "Business" },
                    "principalBusinessActivity": { "type": "string", "example": "74", "description": "NIC code for principal business activity" },
                    "partners":                  { "type": "array", "items": { "$ref": "#/components/schemas/Partner" } },
                    "source":                    { "type": "string", "example": "annualReturn" },
                    "_debug":                    { "type": "object", "description": "Debug info: userId, annualReturnOk, formServiceResCode, partnerCount, partnerSourceFrom" }
                  }
                }
              }
            }
          }
        }
      }
    },

    "/api/form11/submit": {
      "post": {
        "tags": ["Form 11"],
        "summary": "Submit Form 11 to MCA",
        "description": "Full end-to-end Form 11 submission flow:\n1. Pre-warms the Form-11 AEM page\n2. Creates a new SR draft (`createFormEntry`) — OR resumes an existing draft if `integrationId`+`referenceNumber` are supplied in the body\n3. **(if attachments provided)** Uploads each file to MCA DMS using `referenceNumber` as foldername — all use label `OptAttachmentForm11`\n4. `formService Submit` (operation=Submit, with `formAttachment[]`) → generates SRN\n5. Submits AEM adaptive form via `internalsubmit.jsp`\n6. Generates unsigned PDF (`AsyncGeneratePdf`)\n7. Sends ACK email (`FormSubmitConfirmation`)\n\nReturns the SRN on success. Use the SRN to download the PDF via `/api/form11/download-pdf`.\n\n## Content types\n\nThis endpoint accepts **either** `application/json` **or** `multipart/form-data`:\n\n- **JSON** — send the body directly (no attachment, OR pass `formAttachment[]` of DMS responses from prior `/upload-attachment` calls to resume a draft with attachments).\n- **Multipart** — put the JSON-stringified body into a form field named `payload`, and (optionally) include **up to 5** files in the `attachmentFile` field (repeat the field name for each file). Each attachment must be PDF/DOC/DOCX, max 2 MB.\n\n## Multiple attachments\n\nForm 11 supports multiple optional attachments — verified from HAR (2 PDFs uploaded with the same `attachmentLabel: \"OptAttachmentForm11\"`). The server uploads each file to DMS sequentially and aggregates the responses into `formAttachment[]` automatically. Per-file results are returned in `attachmentUploads[]`.\n\n## Resume / edit an existing draft\n\nPass `integrationId` + `referenceNumber` + (optionally) `formIntegrationId` in the body to resume an existing draft instead of creating a new SR. Useful for adding attachments to a previously-saved draft.\n\n## Duplicate filing\n\nForm 11 can only be filed once per LLPIN per FY. Re-submitting for the same period returns `formServiceSubmit.resCode=\"210\"` (\"Technical Error\") with `validationResponse.SubmissionRestricted=\"Y\"` and `srn=null`. Withdraw the existing SRN on the MCA portal first.\n\n**Note:** Call `/api/form11/prefill` first to get the complete partner list and address data, then submit that data here.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["payload"],
                "properties": {
                  "payload":        { "type": "string", "description": "JSON-serialized Form 11 submit body (same shape as the application/json variant)" },
                  "attachmentFile": {
                    "type": "array",
                    "maxItems": 5,
                    "items": { "type": "string", "format": "binary" },
                    "description": "Up to 5 PDF/DOC/DOCX attachments (max 2 MB each). Repeat the field name for multiple files."
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["llpin", "nameOfLLP", "partners", "signerDpin", "signerName", "certDpin"],
                "properties": {
                  "llpin":                     { "type": "string",  "example": "AAJ-2620" },
                  "nameOfLLP":                 { "type": "string",  "example": "EXAMPLE CONSULTING LLP" },
                  "financialYearFrom":         { "type": "string",  "format": "date", "default": "2025-04-01", "example": "2025-04-01" },
                  "financialYearTo":           { "type": "string",  "format": "date", "default": "2026-03-31", "example": "2026-03-31" },
                  "llpStatus":                 { "type": "string",  "default": "Active" },
                  "email":                     { "type": "string",  "example": "contact@example.com" },
                  "policeStation":             { "type": "string",  "example": "Connaught Place PS" },
                  "businessClassification":    { "type": "string",  "default": "Business" },
                  "principalBusinessActivity": { "type": "string",  "default": "74" },
                  "turnoverExceeds5Cr":        { "type": "string",  "enum": ["Y","N"], "default": "N" },
                  "addressObj": {
                    "allOf": [{ "$ref": "#/components/schemas/Address" }],
                    "description": "Structured address object — use addressObj from prefill response"
                  },
                  "partners": {
                    "type": "array",
                    "minItems": 1,
                    "items": { "$ref": "#/components/schemas/PartnerInput" },
                    "description": "Use partners array from prefill response"
                  },
                  "signerDpin":        { "type": "string",  "example": "01234567", "description": "DPIN of the Designated Partner signing the form" },
                  "signerName":        { "type": "string",  "example": "JOHN DOE", "description": "Full name of the signing Designated Partner" },
                  "signerDesignation": { "type": "string",  "default": "Designated Partner", "description": "Usually 'Designated Partner'" },
                  "certDpin":          { "type": "string",  "example": "98765432", "description": "DIN/DPIN of the certifying professional (CA/CS) or a second DP" }
                }
              },
              "example": {
                "llpin": "AAJ-2620",
                "nameOfLLP": "EXAMPLE CONSULTING LLP",
                "financialYearFrom": "2025-04-01",
                "financialYearTo": "2026-03-31",
                "email": "contact@example.com",
                "businessClassification": "Business",
                "principalBusinessActivity": "74",
                "turnoverExceeds5Cr": "N",
                "addressObj": {
                  "line1": "Plot No. 12, Sector 5",
                  "city": "New Delhi",
                  "state": "Delhi",
                  "country": "India",
                  "pincode": "110001"
                },
                "partners": [
                  { "dpin": "01234567", "name": "JOHN DOE", "designation": "Designated Partner", "appointmentDate": "2020-01-15", "obligationOfContribution": "100000", "contributionReceived": "100000", "residentInIndia": true, "numLLPs": "1", "numCompanies": "0" }
                ],
                "signerDpin": "01234567",
                "signerName": "JOHN DOE",
                "certDpin": "98765432"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Submission result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "srn":              { "type": "string",  "example": "M31091669", "description": "Service Request Number — save this to track or download the filing" },
                    "integrationId":    { "type": "string",  "description": "MCA internal form integration ID" },
                    "referenceNumber":  { "type": "string",  "description": "Siebel CRM SR number" },
                    "downloadUrl":      { "type": "string",  "example": "/api/form11/download-pdf?dmsid=12345", "description": "URL to download the filed PDF once available" },
                    "formServiceSubmit":{ "type": "object",  "description": "Raw formService Submit response including validationResponse" },
                    "submission":       { "type": "object",  "description": "Raw internalsubmit.jsp response" },
                    "pdf":              { "type": "object",  "description": "AsyncGeneratePdf response" },
                    "confirmation":     { "type": "object",  "description": "FormSubmitConfirmation (ACK email) response" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing required fields (llpin, partners, signerDpin)" },
          "502": { "description": "MCA submission failed" }
        }
      }
    },

    "/api/form11/save-only": {
      "post": {
        "tags": ["Form 11"],
        "summary": "Save Form 11 as draft (no submission)",
        "description": "Calls only the formService Save step — useful for testing that session and data are valid before actually submitting. Returns the integrationId and referenceNumber of the created draft.\n\nBody is identical to `/api/form11/submit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "description": "Same as /api/form11/submit body" }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":        { "type": "boolean" },
                    "userId":         { "type": "string" },
                    "integrationId":  { "type": "string" },
                    "referenceNumber":{ "type": "string" },
                    "formVersion":    { "type": "string" },
                    "formService":    { "type": "object" }
                  }
                }
              }
            }
          }
        }
      }
    },

    "/api/form11/init": {
      "get": {
        "tags": ["Form 11"],
        "summary": "Pre-warm Form 11 AEM page",
        "description": "Visits the Form-11 HTML page on MCA to register server-side form session state. Automatically called by `/api/form11/submit` — use this only if you need to extract the formVersion for advanced use cases.",
        "parameters": [
          { "name": "llpin", "in": "query", "schema": { "type": "string" }, "example": "AAJ-2620" }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":      { "type": "boolean" },
                    "pageStatus":   { "type": "integer", "example": 200 },
                    "formVersion":  { "type": "string",  "example": "1748900123456" },
                    "integrationId":{ "type": "string" },
                    "htmlLength":   { "type": "integer" }
                  }
                }
              }
            }
          }
        }
      }
    },

    "/api/form11/download-pdf": {
      "get": {
        "tags": ["Form 11"],
        "summary": "Download filed Form 11 PDF",
        "description": "Downloads the PDF of a filed Form 11. Provide either `srn` (SRN from submission) or `dmsid` (DMS document ID from submission response).\n\nIf you provide `srn`, the server polls MCA until the PDF is ready (up to 45 seconds) before streaming the file.",
        "parameters": [
          { "name": "dmsid", "in": "query", "schema": { "type": "string" }, "description": "DMS document ID (faster — from submission.dmsid)" },
          { "name": "srn",   "in": "query", "schema": { "type": "string" }, "description": "Service Request Number — server polls for dmsid automatically" }
        ],
        "responses": {
          "200": { "description": "PDF or ZIP file attachment", "content": { "application/zip": {}, "application/pdf": {} } },
          "400": { "description": "Neither dmsid nor srn provided" },
          "502": { "description": "PDF not yet available or MCA error" }
        }
      }
    },

    "/api/form11/dpin/{dpin}": {
      "get": {
        "tags": ["Form 11"],
        "summary": "Resolve DIN / DPIN (Form 11 context)",
        "description": "Identical to `/api/llp/dpin/{dpin}` — kept for backwards compatibility. Prefer `/api/llp/dpin/{dpin}` in new integrations.",
        "deprecated": true,
        "parameters": [
          { "name": "dpin", "in": "path", "required": true, "schema": { "type": "string" }, "example": "01234567" }
        ],
        "responses": {
          "200": { "description": "Person details" }
        }
      }
    },

    "/api/form11/upload-attachment": {
      "post": {
        "tags": ["Form 11"],
        "summary": "Upload an attachment to MCA DMS for Form 11 (standalone)",
        "description": "Standalone DMS upload for Form 11. Same shape as `/api/form8/upload-attachment`.\n\nThe file is uploaded to MCA's DMS using `referenceNumber` as the foldername. SRN is **not** required — DMS upload normally runs before SRN exists. Returns the full `DMSAttachmentResponse` from MCA.\n\n**File constraints:** PDF / DOC / DOCX only, max 2 MB.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file", "integrationId", "referenceNumber"],
                "properties": {
                  "file":            { "type": "string", "format": "binary", "description": "PDF/DOC/DOCX, max 2 MB" },
                  "integrationId":   { "type": "string", "description": "From createFormEntry or a previous /submit / /save-only response" },
                  "referenceNumber": { "type": "string", "description": "Siebel CRM SR number — used as the DMS foldername (required)" },
                  "srn":             { "type": "string", "description": "Optional — usually empty (DMS upload runs before SRN exists)" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":         { "type": "boolean" },
                    "srn":             { "type": "string" },
                    "integrationId":   { "type": "string" },
                    "referenceNumber": { "type": "string" },
                    "fileName":        { "type": "string" },
                    "size":            { "type": "integer" },
                    "result":          { "$ref": "#/components/schemas/DMSAttachmentResponse" }
                  }
                }
              }
            }
          },
          "400": { "description": "No file uploaded or missing integrationId / referenceNumber" },
          "502": { "description": "MCA DMS upload failed" }
        }
      }
    },

    "/api/form8/init": {
      "get": {
        "tags": ["Form 8"],
        "summary": "Pre-warm Form 8 AEM page",
        "description": "Visits the Form-8 HTML page on MCA to register server-side form state. Auto-called by `/api/form8/submit` and `/api/form8/save-only` — call this directly only if you need the formVersion separately.",
        "parameters": [
          { "name": "llpin", "in": "query", "schema": { "type": "string" }, "example": "AAJ-2620" }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":       { "type": "boolean" },
                    "pageStatus":    { "type": "integer", "example": 200 },
                    "formVersion":   { "type": "string", "example": "1748900123456" },
                    "integrationId": { "type": "string" },
                    "htmlLength":    { "type": "integer" }
                  }
                }
              }
            }
          }
        }
      }
    },

    "/api/form8/prefill": {
      "get": {
        "tags": ["Form 8"],
        "summary": "Prefill Form 8 — LLP master + previous-year financials + solvency",
        "description": "Single call that aggregates 5 MCA sources in parallel to populate Form 8:\n\n1. `companyInfo` — registered office address\n2. `form8Prefill` (formService) — saved draft / prefill data\n3. `getLLPAnnualReturnData` — partner DPINs and LLP name\n4. `form8GetStatementDetails` (FDM) — `totalMonetaryObligationContribution`\n5. `form8GetLLPDetails` (FDM) — LLP info + previous-year Balance Sheet + P&L + solvency declarations\n\nThe response can be used to populate a UI form. The user must enter current-year Balance Sheet and P&L themselves — current-year fields are returned as `null`. Previous-year financials are pre-filled from FDM when available (else `null`).",
        "parameters": [
          { "name": "llpin",   "in": "query", "required": true,  "schema": { "type": "string" }, "example": "AAJ-2620" },
          { "name": "fy_from", "in": "query", "required": false, "schema": { "type": "string", "format": "date", "default": "2025-04-01" }, "example": "2025-04-01" },
          { "name": "fy_to",   "in": "query", "required": false, "schema": { "type": "string", "format": "date", "default": "2026-03-31" }, "example": "2026-03-31" }
        ],
        "responses": {
          "200": {
            "description": "Form 8 prefill data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "llpin":                               { "type": "string", "example": "AAJ-2620" },
                    "nameOfLLP":                           { "type": "string", "example": "EXAMPLE CONSULTING LLP" },
                    "llpStatus":                           { "type": "string", "example": "Active" },
                    "address":                             { "type": "string", "example": "Plot 12, Sector 5, New Delhi, Delhi, 110001" },
                    "addressObj":                          { "$ref": "#/components/schemas/Address" },
                    "email":                               { "type": "string", "example": "contact@example.com" },
                    "policeStation":                       { "type": "string", "example": "Connaught Place PS" },
                    "dateOfIncorporation":                 { "type": "string", "example": "2020-01-15" },
                    "financialYearFrom":                   { "type": "string", "example": "2025-04-01" },
                    "financialYearTo":                     { "type": "string", "example": "2026-03-31" },
                    "totalMonetaryObligationContribution": { "type": "string", "example": "200000" },
                    "statementOfSolvency": {
                      "type": "object",
                      "properties": {
                        "canPayDebts":              { "type": "string", "example": "is" },
                        "turnOver":                 { "type": "string", "example": "does not exceed" },
                        "obligationOfContribution": { "type": "string", "example": "does not exceed" },
                        "chargesConfirmation":      { "type": "string", "nullable": true }
                      }
                    },
                    "currentStatementOfAccount":  { "type": "object", "nullable": true, "description": "Always null in prefill — caller must enter current-year BS" },
                    "currentIncomeExpenditure":   { "type": "object", "nullable": true, "description": "Always null in prefill — caller must enter current-year P&L" },
                    "previousStatementOfAccount": { "allOf": [{ "$ref": "#/components/schemas/BalanceSheet" }], "nullable": true, "description": "Pre-filled from FDM when MCA has previous-year data; null otherwise" },
                    "previousIncomeExpenditure":  { "allOf": [{ "$ref": "#/components/schemas/IncomeExpenditure" }], "nullable": true },
                    "dscDetails": {
                      "type": "object",
                      "properties": {
                        "dp1Dpin": { "type": "string", "nullable": true, "example": "01234567" },
                        "dp2Dpin": { "type": "string", "nullable": true, "example": "98765432" }
                      }
                    },
                    "certificate": {
                      "type": "object",
                      "properties": {
                        "certifiedBy":                 { "type": "string", "example": "Designated partner" },
                        "certifiedId":                 { "type": "string", "nullable": true },
                        "certifiedName":               { "type": "string", "nullable": true },
                        "category":                    { "type": "string", "nullable": true },
                        "professionalType":            { "type": "string", "nullable": true },
                        "certificateOfPracticeNumber": { "type": "string", "nullable": true }
                      }
                    },
                    "hasContingentLiabilities": { "type": "string", "enum": ["Y", "N"], "example": "N" },
                    "contingentLiabilities":    { "type": "array", "items": { "type": "object" } },
                    "_debug":                   { "type": "object" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing llpin", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "MCA upstream error" }
        }
      }
    },

    "/api/form8/submit": {
      "post": {
        "tags": ["Form 8"],
        "summary": "Submit Form 8 to MCA",
        "description": "Full Form 8 (LLP Statement of Account & Solvency) submission flow:\n\n1. Pre-warm the AEM Form-8 page\n2. `createForm8Entry` → fresh `integrationId` + `referenceNumber` (Siebel CRM SR)\n3. `formService Save` (operation=Save, placeholder formIntegrationId=861) → returns the real `formIntegrationId`\n4. **(if attachment provided)** Upload the file to MCA's DMS using `referenceNumber` as the foldername\n5. **(if attachment provided)** `formService Save` (Save 2) with `formAttachment[]` populated\n6. `formService Submit` (operation=Submit) → generates SRN\n7. `internalsubmit.jsp` to finalise AEM state (Akamai may 403 — non-fatal)\n8. `AsyncGeneratePdf` → unsigned PDF generated\n9. `form8SubmitConfirmation` → ACK email\n\n## Content types\n\nThis endpoint accepts **either** `application/json` **or** `multipart/form-data`:\n\n- **JSON** — send the `Form8SubmitRequest` body directly (no attachment).\n- **Multipart** — put the JSON-stringified `Form8SubmitRequest` into a form field named `payload`, and (optionally) include a file in the `attachmentFile` field. The attachment must be PDF / DOC / DOCX, max 2 MB.\n\nThe DMS upload happens between Save 1 and Save 2, using `referenceNumber` as the foldername. The returned DMS object becomes one entry in `formAttachment[]` and is committed via Save 2 before Submit.\n\n## Duplicate filing\n\nForm 8 can only be filed once per LLPIN per financial year. Re-submitting for the same period returns `formServiceSubmit.resCode=\"210\"` (\"Technical Error\") with `validationResponse.SubmissionRestricted=\"Y\"` and `srn=null`. To re-file, the user must withdraw the existing SRN on the MCA portal first.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/Form8SubmitRequest" },
              "example": {
                "llpin": "AAJ-2620",
                "llpName": "EXAMPLE CONSULTING LLP",
                "fyFrom": "2025-04-01",
                "fyTo": "2026-03-31",
                "email": "contact@example.com",
                "policeStation": "Connaught Place PS",
                "addressObj": {
                  "line1": "Plot No. 12, Sector 5",
                  "city": "New Delhi",
                  "state": "Delhi",
                  "country": "India",
                  "pincode": "110001"
                },
                "totalMonetaryObligationContribution": "200000",
                "dscDetails": { "dp1Dpin": "01234567", "dp2Dpin": "98765432" },
                "dpCertificate": { "certifiedBy": "Designated partner", "certifiedId": "01234567", "certifiedName": "JOHN DOE" },
                "professionalCertificate": { "category": "Chartered Accountant in whole time practice", "professionalType": "Fellow", "certificateOfPracticeNumber": "123456", "name": "JANE SMITH" },
                "statementOfSolvency": { "canPayDebts": "is", "turnOver": "does not exceed", "obligationOfContribution": "does not exceed" },
                "currentStatementOfAccount":  { "contributionReceived": 200000, "reservesAndSurplus": 50000, "creditorsTradePayablesAdvanceFromCustomers": 25000, "contributionAndLiabilitiesTotal": 275000, "grossFixedAssets": 80000, "lessDepreciationAndAmortization": 5000, "netFixedAssets": 75000, "loansAndAdvances": 10000, "debtorsTradeReceivables": 40000, "cashAndCashEquivalents": 150000, "assestsTotal": 275000 },
                "previousStatementOfAccount": { "contributionReceived": 200000, "contributionAndLiabilitiesTotal": 200000, "cashAndCashEquivalents": 200000, "assestsTotal": 200000 },
                "currentIncomeExpenditure":   { "grossTurnOver": 500000, "netTurnoverDetails": 500000, "totalIncome": 500000, "personnelExpenses": 200000, "administrativeExpenses": 50000, "totalExpenditure": 250000, "netProfitOrNetLoss": 250000, "profitAfterTax": 200000, "provisionForTax": 50000 },
                "previousIncomeExpenditure":  { "grossTurnOver": 0, "totalIncome": 0, "totalExpenditure": 0, "netProfitOrNetLoss": 0, "profitAfterTax": 0 },
                "hasContingentLiabilities": "N",
                "contingentLiabilities": []
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["payload"],
                "properties": {
                  "payload":        { "type": "string", "description": "JSON-serialized `Form8SubmitRequest`" },
                  "attachmentFile": { "type": "string", "format": "binary", "description": "Optional PDF/DOC/DOCX (max 2 MB)" }
                }
              },
              "encoding": {
                "attachmentFile": { "contentType": "application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document" }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Submission result. Note: HTTP 200 does NOT mean success — check `srn` (null on duplicate filing) and `formServiceSubmit.validationResponse.SubmissionRestricted`.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Form8SubmitResponse" }
              }
            }
          },
          "400": { "description": "Missing required fields (llpin, llpName)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No _csrf cookie in injected session — re-inject session" },
          "502": { "description": "MCA submission failed" }
        }
      }
    },

    "/api/form8/save-only": {
      "post": {
        "tags": ["Form 8"],
        "summary": "Save Form 8 as draft (no SRN generated)",
        "description": "Calls only the formService Save step (operation=Save). Useful for testing the payload, validating the session, or saving partial data. **No SRN is generated** — call `/api/form8/submit` for the full flow.\n\nBody is identical to `/api/form8/submit` (JSON only). Set `prefetch: false` to skip the AEM page warm-up.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/Form8SubmitRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":           { "type": "boolean" },
                    "userId":            { "type": "string" },
                    "integrationId":     { "type": "string" },
                    "referenceNumber":   { "type": "string" },
                    "formIntegrationId": { "type": "string" },
                    "srn":               { "type": "string", "nullable": true, "description": "Always null for save-only" },
                    "formVersion":       { "type": "string" },
                    "prefetch":          { "type": "object" },
                    "createEntry":       { "type": "object" },
                    "formService":       { "type": "object" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing llpin/llpName or no _csrf cookie" }
        }
      }
    },

    "/api/form8/upload-attachment": {
      "post": {
        "tags": ["Form 8"],
        "summary": "Upload an attachment to MCA DMS (standalone)",
        "description": "Standalone DMS upload for Form 8. Useful when you want to upload an attachment outside of the `/submit` flow (e.g. you already have an `integrationId` from a prior `createForm8Entry` or `save-only` call).\n\nThe file is uploaded to MCA's DMS using `referenceNumber` as the foldername. SRN is **not** required — DMS upload runs before SRN exists in the normal flow. Returns the full `DMSAttachmentResponse` from MCA.\n\n**File constraints:** PDF / DOC / DOCX only, max 2 MB.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file", "integrationId"],
                "properties": {
                  "file":            { "type": "string", "format": "binary", "description": "PDF/DOC/DOCX, max 2 MB" },
                  "integrationId":   { "type": "string", "description": "From createForm8Entry or a previous /submit / /save-only response" },
                  "referenceNumber": { "type": "string", "description": "Siebel CRM SR number — used as the DMS foldername" },
                  "srn":             { "type": "string", "description": "Optional — usually empty (SRN is generated only at Submit time)" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":       { "type": "boolean" },
                    "srn":           { "type": "string" },
                    "integrationId": { "type": "string" },
                    "fileName":      { "type": "string" },
                    "size":          { "type": "integer" },
                    "result":        { "$ref": "#/components/schemas/DMSAttachmentResponse" }
                  }
                }
              }
            }
          },
          "400": { "description": "No file uploaded or missing integrationId" },
          "502": { "description": "MCA DMS upload failed" }
        }
      }
    },

    "/api/form8/download-pdf": {
      "get": {
        "tags": ["Form 8"],
        "summary": "Download filed Form 8 PDF",
        "description": "Downloads the filed Form 8 PDF (delivered as a ZIP containing the PDF). Provide either `dmsid` (faster, from a submit response) or `srn` (server polls MCA for up to 45 seconds until the PDF is generated).",
        "parameters": [
          { "name": "dmsid", "in": "query", "schema": { "type": "string" }, "description": "DMS document ID — preferred when known" },
          { "name": "srn",   "in": "query", "schema": { "type": "string" }, "description": "Service Request Number — server polls for the dmsid first" }
        ],
        "responses": {
          "200": { "description": "PDF or ZIP file attachment", "content": { "application/zip": {}, "application/pdf": {} } },
          "400": { "description": "Neither dmsid nor srn provided" },
          "502": { "description": "PDF not yet available or MCA error" }
        }
      }
    },

    "/api/aoc4/prefill": {
      "get": {
        "tags": ["Future"],
        "summary": "[PLANNED] Prefill AOC-4 — Company Annual Financial Statement",
        "description": "**Not yet implemented.** AOC-4 is for private/public companies (not LLPs). Will use CIN instead of LLPIN.",
        "parameters": [
          { "name": "cin",     "in": "query", "required": true,  "schema": { "type": "string" }, "description": "Company Identification Number (e.g. U74999DL2020PTC123456)" },
          { "name": "fy_from", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "fy_to",   "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "501": { "description": "Not implemented yet" } }
      }
    },

    "/api/mgt7a/prefill": {
      "get": {
        "tags": ["Future"],
        "summary": "[PLANNED] Prefill MGT-7A — Small Company / OPC Annual Return",
        "description": "**Not yet implemented.** MGT-7A is for small companies and One Person Companies. Will use CIN.",
        "parameters": [
          { "name": "cin",     "in": "query", "required": true,  "schema": { "type": "string" } },
          { "name": "fy_from", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "fy_to",   "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "501": { "description": "Not implemented yet" } }
      }
    },

    "/api/connect/register": {
      "post": {
        "tags": ["Connect"],
        "summary": "Register a new user slot",
        "description": "Called by your backend (CoSec Office) when onboarding a new user. Returns a unique `apiKey` that identifies this user's MCA session slot — store it in your database against the user record.\n\nThe returned `connectUrl` is the page you open in the user's browser so they can connect their MCA account in one click.\n\n**Security:** Requires `X-Connect-Master-Key` header matching the `CONNECT_MASTER_KEY` environment variable. Never expose this to your frontend.",
        "security": [{ "MasterKey": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "appId": { "type": "string", "example": "user_123", "description": "Your internal user ID — for cross-reference only, not used for auth" },
                  "label": { "type": "string", "example": "Priya Sharma", "description": "Human label for the admin /api/connect/users list" }
                }
              },
              "example": { "appId": "user_123", "label": "Priya Sharma" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User slot created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":    { "type": "boolean", "example": true },
                    "apiKey":     { "type": "string",  "example": "a3f9e2b1c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3", "description": "Store this against the user — used to identify their session slot" },
                    "connectUrl": { "type": "string",  "example": "https://mca-api.example.com/connect?apiKey=a3f9e2...", "description": "Open this URL in the user's browser so they can connect their MCA account" },
                    "usage": { "type": "object", "description": "Step-by-step integration guide embedded in the response" }
                  }
                }
              }
            }
          },
          "401": { "description": "Invalid master key" },
          "503": { "description": "CONNECT_MASTER_KEY not configured on server" }
        }
      }
    },

    "/api/connect/sync": {
      "post": {
        "tags": ["Connect"],
        "summary": "Sync MCA cookies for a user (called by Chrome Extension)",
        "description": "Called automatically by the MCA Connector Chrome Extension content script when a user visits the `connectUrl`.\n\nThe extension reads MCA cookies from the browser (requires the user to be logged into mca.gov.in), then POSTs them here. The server stores the cookies encrypted against the user's `apiKey` and resolves the MCA user identity.\n\n**Your backend does not need to call this endpoint.** The Chrome Extension handles it automatically. This is documented for completeness and debugging.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["apiKey", "cookies"],
                "properties": {
                  "apiKey":  { "type": "string", "description": "The apiKey returned by /api/connect/register" },
                  "cookies": { "type": "string", "description": "Raw MCA browser cookie header string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session stored successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":     { "type": "boolean", "example": true },
                    "connected":   { "type": "boolean", "example": true },
                    "mcaUserId":   { "type": "string",  "example": "MCAUSER123456" },
                    "mcaUserName": { "type": "string",  "example": "Priya Sharma" },
                    "mcaEmail":    { "type": "string",  "example": "priya@example.com" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing apiKey or cookies" },
          "404": { "description": "Unknown apiKey — register the user first" }
        }
      }
    },

    "/api/connect/status": {
      "get": {
        "tags": ["Connect"],
        "summary": "Check user connection status (no cookies returned)",
        "description": "Lightweight poll endpoint. Used by the `connect.html` page (which auto-polls every 2 seconds) to detect when the extension has synced cookies successfully.\n\nAlso useful for CoSec Office to display a connection indicator next to each user — no master key required since no sensitive data is returned.",
        "security": [],
        "parameters": [
          {
            "name": "apiKey",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "description": "The apiKey returned by /api/connect/register",
            "example": "a3f9e2b1c4d5e6f7a8b9c0d1e2f3a4b5"
          }
        ],
        "responses": {
          "200": {
            "description": "Connection status (no cookies)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "connected":   { "type": "boolean", "example": true },
                    "mcaUserId":   { "type": "string",  "nullable": true, "example": "MCAUSER123456" },
                    "mcaUserName": { "type": "string",  "nullable": true, "example": "Priya Sharma" },
                    "mcaEmail":    { "type": "string",  "nullable": true, "example": "priya@example.com" },
                    "lastSync":    { "type": "string",  "nullable": true, "format": "date-time" },
                    "label":       { "type": "string",  "nullable": true, "example": "Priya Sharma" },
                    "appId":       { "type": "string",  "nullable": true, "example": "user_123" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing apiKey" },
          "404": { "description": "Unknown apiKey" }
        }
      }
    },

    "/api/connect/session": {
      "get": {
        "tags": ["Connect"],
        "summary": "Retrieve stored MCA cookies for filing (master key required)",
        "description": "Called by your backend (CoSec Office server) just before filing a form on behalf of a user. Returns the raw MCA cookie string that was synced by the extension.\n\n**Typical usage:**\n1. Call this endpoint to get the user's cookies\n2. POST the cookies to `/api/auth/inject-session` to create an active server session\n3. File forms using the returned `sessionId`\n\n**Security:** Requires `X-Connect-Master-Key`. Only call this from your backend — never expose cookies to the browser.",
        "security": [{ "MasterKey": [] }],
        "parameters": [
          {
            "name": "apiKey",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "example": "a3f9e2b1c4d5e6f7a8b9c0d1e2f3a4b5"
          }
        ],
        "responses": {
          "200": {
            "description": "Session cookies and user info",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cookies":     { "type": "string",  "description": "Raw MCA cookie string — pass to POST /api/auth/inject-session" },
                    "mcaUserId":   { "type": "string",  "example": "MCAUSER123456" },
                    "mcaUserName": { "type": "string",  "example": "Priya Sharma" },
                    "mcaEmail":    { "type": "string",  "example": "priya@example.com" },
                    "lastSync":    { "type": "string",  "format": "date-time" }
                  }
                }
              }
            }
          },
          "401": { "description": "Invalid master key" },
          "404": { "description": "Unknown apiKey" },
          "409": { "description": "User has not connected their MCA account yet — show them the connectUrl" }
        }
      },
      "delete": {
        "tags": ["Connect"],
        "summary": "Disconnect a user (clear cookies, keep registration)",
        "description": "Clears the stored MCA cookies for a user without removing their registration slot. The user's `apiKey` remains valid — they can reconnect by visiting the `connectUrl` again.\n\nUse this when a user's MCA session expires and they need to reconnect.",
        "security": [{ "MasterKey": [] }],
        "parameters": [
          {
            "name": "apiKey",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "example": "a3f9e2b1c4d5e6f7a8b9c0d1e2f3a4b5"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": { "type": "object", "properties": {
                  "success": { "type": "boolean", "example": true },
                  "message": { "type": "string",  "example": "MCA session cleared" }
                }}
              }
            }
          },
          "401": { "description": "Invalid master key" },
          "404": { "description": "Unknown apiKey" }
        }
      }
    },

    "/api/connect/user": {
      "delete": {
        "tags": ["Connect"],
        "summary": "Fully remove a user registration",
        "description": "Completely removes a user's registration slot — apiKey, cookies, and all metadata. Use when a user is deleted from CoSec Office.\n\nAfter this call the `apiKey` is invalid and will return 404 on all other connect endpoints.",
        "security": [{ "MasterKey": [] }],
        "parameters": [
          {
            "name": "apiKey",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "example": "a3f9e2b1c4d5e6f7a8b9c0d1e2f3a4b5"
          }
        ],
        "responses": {
          "200": { "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" } } } } } },
          "401": { "description": "Invalid master key" }
        }
      }
    },

    "/api/connect/users": {
      "get": {
        "tags": ["Connect"],
        "summary": "List all registered users (no cookies)",
        "description": "Returns all user registration slots with connection status and MCA identity info. Cookies are never included.\n\nUse this in your admin dashboard to show which users are connected and when they last synced.",
        "security": [{ "MasterKey": [] }],
        "responses": {
          "200": {
            "description": "List of registered users",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/ConnectUser" }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Invalid master key" }
        }
      }
    },

    "/connect": {
      "get": {
        "tags": ["Connect"],
        "summary": "User-facing connect page (open in browser)",
        "description": "This is the HTML page CoSec Office opens in the user's browser when they click 'Connect MCA Account'. It has no UI controls — the Chrome Extension detects it automatically and syncs the cookies in the background.\n\nThe page shows an animated connecting state and transitions to 'Connected as [Name]' once the extension finishes syncing.\n\nIf the extension is not installed, the page shows installation instructions with a download link.\n\n**Do not call this from your backend.** Open it in a browser window or `<iframe>` for the user.",
        "security": [],
        "parameters": [
          {
            "name": "apiKey",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "description": "The apiKey returned by /api/connect/register for this user",
            "example": "a3f9e2b1c4d5e6f7a8b9c0d1e2f3a4b5"
          }
        ],
        "responses": {
          "200": { "description": "HTML connect page (open in browser, not for API calls)", "content": { "text/html": {} } }
        }
      }
    },

    "/api/master/captcha": {
      "get": {
        "tags": ["Master Data"],
        "summary": "Fetch a fresh MDS captcha",
        "description": "Returns a CAPTCHA image (and audio) plus a single-use `preCT` token. The user must solve the captcha and the client must echo `preCT` and the solution to `/api/master/lookup` or `/api/master/search` within a short window.\n\n**An active MCA session must be injected FIRST** — without one, this endpoint returns HTTP 401 immediately and never even hits MCA. MCA's MDSMasterDataServlet rejects server-IP requests due to Akamai bot protection; only requests carrying a real user's MCA session cookies (`__UUID-HASH`, `session-token-md5`, `_csrf`, `sessionID`, etc.) are accepted. Inject these via `POST /api/auth/inject-session` (or have the user connect via the Chrome Extension) before calling this endpoint.\n\nThis is the same MCA session used by `/api/form8/*` and `/api/form11/*`, so users typically only need to inject once per session.\n\nCaptchas are single-use: the frontend must fetch a fresh captcha for every lookup or search.",
        "security": [{ "SessionId": [] }],
        "responses": {
          "200": {
            "description": "Captcha challenge",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MDSCaptchaResponse" }
              }
            }
          },
          "401": {
            "description": "No MCA session injected — request rejected upfront before reaching MCA. Inject MCA cookies via `POST /api/auth/inject-session` first.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": {
                  "error": "MCA session required",
                  "detail": "Master Data Search needs an active MCA session (Akamai bot protection blocks server-IP requests).",
                  "hint": "Inject MCA cookies first via POST /api/auth/inject-session, or have the user connect via the Chrome Extension."
                }
              }
            }
          },
          "403": {
            "description": "Session was injected but MCA's Akamai still rejected the request — typically the injected cookies have expired or were never valid. Re-inject a fresh MCA session. (Distinct from 401, which means no session was injected at all.)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": {
                  "error": "MCA Akamai blocked the request",
                  "detail": "MDS captcha HTTP 403",
                  "hint": "Inject MCA cookies via POST /api/auth/inject-session first. MCA blocks server-IP requests; an active browser session is required."
                }
              }
            }
          },
          "502": {
            "description": "Upstream MCA failure",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },

    "/api/master/lookup": {
      "post": {
        "tags": ["Master Data"],
        "summary": "Fetch master data for a CIN or LLPIN",
        "description": "Validates the captcha (MCA rotates `preCT` server-side on success), then immediately fetches full master data using the rotated token.\n\n**An active MCA session must be injected FIRST** — without one, this endpoint returns HTTP 401 immediately and never even hits MCA. MCA's MDSMasterDataServlet only accepts requests carrying a real user's MCA session cookies (Akamai bot protection blocks server-IP requests). Inject via `POST /api/auth/inject-session` first, or connect via the Chrome Extension. This is the same session used by `/api/form8/*` and `/api/form11/*`, so users typically only inject once.\n\n**Captcha is single-use** — on a 409 response the frontend must call `GET /api/master/captcha` again before retrying.",
        "security": [{ "SessionId": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/MDSLookupRequest" },
              "examples": {
                "cin": {
                  "summary": "Company lookup by CIN",
                  "value": {
                    "id": "U74999RJ2018PTC060472",
                    "type": "cin",
                    "userInput": "1DbF0q",
                    "preCT": "rejr7Sh76S38nQK6yYwAfFQqXn6f..."
                  }
                },
                "llpin": {
                  "summary": "LLP lookup by LLPIN",
                  "value": {
                    "id": "AAJ-2620",
                    "type": "llpin",
                    "userInput": "1DbF0q",
                    "preCT": "rejr7Sh76S38nQK6yYwAfFQqXn6f..."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Master data record from MCA",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MDSMasterDataResponse" },
                "example": {
                  "error": null,
                  "message": "Success",
                  "data": {
                    "companyData": {
                      "CIN": "U74999RJ2018PTC060472",
                      "company": "FASTLEGAL TECHNOLOGIES PRIVATE LIMITED",
                      "companyType": "Company limited by shares",
                      "dateOfIncorporation": "2018-04-12",
                      "llpStatus": "Active",
                      "authorisedCapital": "100000",
                      "paidUpCapital": "100000",
                      "rocName": "RoC-Jaipur",
                      "MCAMDSCompanyAddress": [
                        {
                          "streetAddress": "SHOP NO. K-50, LGF, REVERA",
                          "streetAddress2": "PLOT NO 1-8, RAM CHANDRAPURA JAGATPURA",
                          "addressType": "Registered",
                          "locality": "Sitapura Industrial Area",
                          "district": "Jaipur",
                          "city": "Jaipur",
                          "state": "Rajasthan",
                          "country": "India",
                          "postalCode": "302022",
                          "activeStatus": "Y"
                        }
                      ],
                      "balanceSheet3years": [],
                      "annualReturns3years": []
                    },
                    "directorData": [
                      {
                        "DIN": "07591685",
                        "PAN": "ABCDE1234F",
                        "dateOfAppointment": "2018-04-12",
                        "DirectorDisqualified": "N",
                        "FirstName": "AMIT",
                        "MiddleName": "",
                        "LastName": "SHARMA",
                        "MCAUserRole": []
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing required field",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          },
          "401": {
            "description": "No MCA session injected — request rejected upfront before reaching MCA. Inject MCA cookies via `POST /api/auth/inject-session` first.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": {
                  "error": "MCA session required",
                  "detail": "Master Data Search needs an active MCA session (Akamai bot protection blocks server-IP requests).",
                  "hint": "Inject MCA cookies first via POST /api/auth/inject-session, or have the user connect via the Chrome Extension."
                }
              }
            }
          },
          "409": {
            "description": "Captcha validation failed — fetch a fresh captcha and retry",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": {
                  "error": "Captcha validation failed",
                  "detail": "MDS validateCaptcha rejected the submitted captcha",
                  "hint": "Fetch a fresh captcha from GET /api/master/captcha and retry"
                }
              }
            }
          },
          "502": {
            "description": "Upstream MCA failure",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },

    "/api/master/search": {
      "post": {
        "tags": ["Master Data"],
        "summary": "Autocomplete search by company / LLP name",
        "description": "Returns MCA's autocomplete payload — `data.result[]` contains matching entities with `cnNmbr` (the CIN/LLPIN), `cmpnyNm`, `cmpnySts`, `state`, etc. Like `/lookup`, this requires a fresh captcha for every call.\n\n**An active MCA session must be injected FIRST** — without one, this endpoint returns HTTP 401 immediately and never even hits MCA. MCA's MDSMasterDataServlet only accepts requests carrying a real user's MCA session cookies (Akamai bot protection blocks server-IP requests). Inject via `POST /api/auth/inject-session` first, or connect via the Chrome Extension. This is the same session used by `/api/form8/*` and `/api/form11/*`, so users typically only inject once.",
        "security": [{ "SessionId": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/MDSSearchRequest" },
              "example": {
                "query": "fastlegal",
                "type": "company",
                "userInput": "1DbF0q",
                "preCT": "rejr7Sh76S38nQK6yYwAfFQqXn6f..."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "MCA commonSearch payload",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "result": [
                      {
                        "cnNmbr": "U74999RJ2018PTC060472",
                        "cmpnyNm": "FASTLEGAL TECHNOLOGIES PRIVATE LIMITED",
                        "cmpnySts": "Active",
                        "state": "Rajasthan"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing required field",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          },
          "401": {
            "description": "No MCA session injected — request rejected upfront before reaching MCA. Inject MCA cookies via `POST /api/auth/inject-session` first.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": {
                  "error": "MCA session required",
                  "detail": "Master Data Search needs an active MCA session (Akamai bot protection blocks server-IP requests).",
                  "hint": "Inject MCA cookies first via POST /api/auth/inject-session, or have the user connect via the Chrome Extension."
                }
              }
            }
          },
          "409": {
            "description": "Captcha validation failed — fetch a fresh captcha and retry",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": {
                  "error": "Captcha validation failed",
                  "detail": "MDS validateCaptcha rejected the submitted captcha",
                  "hint": "Fetch a fresh captcha from GET /api/master/captcha and retry"
                }
              }
            }
          },
          "502": {
            "description": "Upstream MCA failure",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },

    "/api/dashboard/tabs": {
      "get": {
        "tags": ["Dashboard"],
        "summary": "List available dashboard tabs",
        "description": "Returns the catalogue of all 8 dashboard tab codes with human labels and descriptions. Static metadata — no upstream MCA call, no session required.",
        "security": [],
        "responses": {
          "200": {
            "description": "Tab catalogue",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tabs": { "type": "array", "items": { "$ref": "#/components/schemas/DashboardTab" } }
                  }
                },
                "example": {
                  "tabs": [
                    { "code": "CR", "label": "Receipts",          "description": "Challan receipts for all filings (purpose:\"Receipt\")" },
                    { "code": "UP", "label": "Under Processing",  "description": "MCA is processing — Under Processing, Strike-off Examination" },
                    { "code": "PS", "label": "Payment Status",    "description": "Filings tracked by payment status" },
                    { "code": "AR", "label": "Approved",          "description": "Approved / Registered filings" },
                    { "code": "CL", "label": "Certificates",      "description": "Certificates issued by MCA (incorporation, change-of-name, charge filings, etc. — purpose:\"Certificates\")" },
                    { "code": "NO", "label": "Letters / Notices", "description": "Letters and notices issued by MCA" },
                    { "code": "RN", "label": "Rejected",          "description": "Rejected, Rejected for refund, Invalid not taken on record" },
                    { "code": "CX", "label": "Cancelled",         "description": "User-cancelled or auto-cancelled SRNs" }
                  ]
                }
              }
            }
          }
        }
      }
    },

    "/api/dashboard": {
      "get": {
        "tags": ["Dashboard"],
        "summary": "List MCA filings (My Applications)",
        "description": "Mirrors MCA's My Applications page (`/bin/mca/applicationHistory`). Returns the user's filings filtered by tab, with optional CIN / LLPIN / SRN / date-range filters.\n\nThe tab code controls which subset of filings is returned — see GET /api/dashboard/tabs for the full list. Default is `CR` (Receipts).\n\nDates use DD/MM/YYYY format (MCA's native format).",
        "parameters": [
          { "name": "tab",      "in": "query", "required": false, "schema": { "type": "string", "enum": ["FO", "UP", "AR", "RN", "CX", "PS", "CL", "CR", "NO"], "default": "CR" }, "description": "Tab code. `FO` Pending for Action, `UP` Under Processing, `AR` Approved, `RN` NTBR/Rejected, `CX` Cancelled, `PS` Payment Status, `CL` Certificates/Letters, `CR` Challans/Receipts, `NO` Notices/Orders. Defaults to CR." },
          { "name": "cin",      "in": "query", "required": false, "schema": { "type": "string" }, "example": "U74999RJ2018PTC060472", "description": "Filter by CIN (companies) or LLPIN (LLPs, e.g. AAJ-2620)." },
          { "name": "srn",      "in": "query", "required": false, "schema": { "type": "string" }, "example": "M30858649", "description": "Filter by Service Request Number." },
          { "name": "fromDate", "in": "query", "required": false, "schema": { "type": "string" }, "example": "01/04/2026", "description": "Start date (DD/MM/YYYY)" },
          { "name": "toDate",   "in": "query", "required": false, "schema": { "type": "string" }, "example": "10/05/2026", "description": "End date (DD/MM/YYYY)" },
          { "name": "profUser", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Optional MCA professional-user filter (rarely needed)" },
          { "name": "excludeDrafts", "in": "query", "required": false, "schema": { "type": "boolean", "default": false }, "description": "When `true`, strips draft-reference rows (IDs like `1-25529263159`) from the response — keeps only real SRNs (alphanumeric like `AC3420990`, `M31091669`). Useful on the `FO` (Pending for Action) tab where MCA accumulates abandoned drafts indefinitely. Response also includes `totalBeforeFilter` so you can show \"showing X of Y\"." }
        ],
        "responses": {
          "200": {
            "description": "List of filings for the requested tab",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/DashboardListResponse" },
                "example": {
                  "tab": "CR",
                  "tabLabel": "Receipts",
                  "count": 1,
                  "data": [
                    {
                      "srn": "M30858649",
                      "srNumber": "1-25371230946",
                      "integrationId": "1-25371230946",
                      "dmsId": "647181288",
                      "formName": "Form 11",
                      "entityName": "FASTLEGAL TECHNOLOGIES PRIVATE LIMITED",
                      "identificationNumber": "U74999RJ2018PTC060472",
                      "srStatus": "Approved",
                      "srLastUpdated": "10/05/2026",
                      "transactionDate": "01/05/2026",
                      "expiryDate": "31/05/2026",
                      "paymentAmount": "100",
                      "purpose": "Receipt",
                      "submittedBy": "MCAUSER123456"
                    }
                  ],
                  "message": "Data fetched Successfully"
                }
              }
            }
          },
          "400": { "description": "Invalid tab code", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "MCA session required or expired", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure",            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/dashboard/download": {
      "get": {
        "tags": ["Dashboard"],
        "summary": "Download a single filing PDF",
        "description": "Downloads one MCA document by `dmsid` (preferred) or `srn` (server resolves dmsId via MCA polling). MCA's DMS endpoint always returns a ZIP wrapping the PDF — this server unzips it transparently and serves a real `application/pdf` so the user gets a `.pdf` file, not a nested ZIP.\n\n**Filename convention** (used by the official frontend, recommended for API consumers too):\n- Receipts (`purpose:\"Receipt\"`): `ack_<FormName>_<Year>_<SRN>.pdf`\n- Other forms: `<FormName>_<Year>_<SRN>.pdf`\n\nThe `sessionId` query parameter is supported as a fallback to the `X-Session-Id` header — useful for plain `<a href>` clicks where the browser cannot attach custom headers.",
        "parameters": [
          { "name": "dmsid",     "in": "query", "required": false, "schema": { "type": "string" }, "example": "647181288", "description": "DMS ID from a DashboardRow. Preferred over `srn` — skips the resolution round-trip." },
          { "name": "srn",       "in": "query", "required": false, "schema": { "type": "string" }, "example": "M30858649", "description": "Service Request Number — used to resolve dmsId if `dmsid` is absent." },
          { "name": "filename",  "in": "query", "required": false, "schema": { "type": "string" }, "example": "ack_Form_11_2026_M30858649", "description": "Suggested base filename (no extension). Defaults to `mca_<dmsid>`." },
          { "name": "sessionId", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Fallback for `X-Session-Id` header — required when triggering the download from a plain `<a>` link." }
        ],
        "responses": {
          "200": {
            "description": "The PDF file",
            "content": {
              "application/pdf": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": { "description": "No downloadable document (missing params, or dmsid=0 meaning MCA hasn't generated the doc yet)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "MCA session required or expired",  "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA DMS failed",          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/dashboard/bulk-download": {
      "post": {
        "tags": ["Dashboard"],
        "summary": "Bulk-download multiple filings as a ZIP",
        "description": "Fetches up to **50** documents in one call and streams back a single flat ZIP containing the extracted PDFs (no nested ZIPs).\n\nFor each item, supply `dmsid` (preferred) or `srn` (server resolves dmsId via MCA polling). Failed items are skipped — the response is always a valid ZIP. If any items fail, a `_failed.json` manifest is appended at the root of the ZIP with `{ failures: [{srn, dmsid, error}, …], requestedAt }` so callers can detect partial success.\n\nFilenames inside the archive default to `<srn>.pdf`; collisions get `__2`, `__3`, … suffixes automatically. Use the `filename` field per item to control naming (recommended convention: `ack_<FormName>_<Year>_<SRN>` for receipts, `<FormName>_<Year>_<SRN>` for other forms).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/BulkDownloadRequest" },
              "example": {
                "items": [
                  { "dmsid": "647181288", "srn": "M30858649", "filename": "ack_Form_11_2026_M30858649" },
                  { "srn": "1-25371230946", "filename": "Form_8_2026_1-25371230946" }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ZIP archive containing one PDF per successfully-fetched filing. If any items failed, a `_failed.json` manifest is included at the archive root.",
            "content": {
              "application/zip": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": { "description": "items array missing, empty, or > 50", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "MCA session required or expired",     "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure",                 "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/dpt3/categories": {
      "get": {
        "tags": ["Form DPT-3"],
        "summary": "List DPT-3 purposes and receipt categories",
        "description": "Returns the static catalogue used to populate DPT-3 UI dropdowns: the 4 statutory purposes (with section-visibility flags), the 49 official `amountRecievedType` receipt categories, and 5 quick-pick most-common categories. **Public — no MCA session required.**",
        "security": [],
        "responses": {
          "200": {
            "description": "Catalogue",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3CategoriesResponse" } } }
          }
        }
      }
    },

    "/api/dpt3/companies": {
      "get": {
        "tags": ["Form DPT-3"],
        "summary": "List the logged-in user's companies",
        "description": "Returns the CINs the active MCA user is associated with — mirrors the company dropdown on MCA's DPT-3 page. Requires an injected MCA session.",
        "responses": {
          "200": { "description": "Companies", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3CompaniesResponse" } } } },
          "401": { "description": "No MCA session", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/dpt3/prefill": {
      "get": {
        "tags": ["Form DPT-3"],
        "summary": "Prefill DPT-3 from CIN master data",
        "description": "Fetches MCA master data for a CIN, shaped for DPT-3's company section. Internally uses `/bin/commongetapi` (same endpoint as Form 11 prefill).",
        "parameters": [
          { "name": "cin", "in": "query", "required": true, "schema": { "type": "string" }, "example": "U74999RJ2018PTC060472", "description": "Company Identification Number" }
        ],
        "responses": {
          "200": { "description": "Master data", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3PrefillResponse" } } } },
          "400": { "description": "Missing cin", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No MCA session", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/dpt3/save-only": {
      "post": {
        "tags": ["Form DPT-3"],
        "summary": "Save DPT-3 as draft",
        "description": "Save the form as a draft. Returns `referenceNumber`, `integrationId`, and `formintegrationid` for use in subsequent `/upload-attachment` and `/submit` calls (resume the same draft). No SRN is generated.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3SubmitRequest" } } }
        },
        "responses": {
          "200": { "description": "Save result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3SubmitResponse" } } } },
          "400": { "description": "Missing required fields", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No MCA session", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/dpt3/submit": {
      "post": {
        "tags": ["Form DPT-3"],
        "summary": "Submit DPT-3 and return SRN",
        "description": "Full filing flow: createFormEntry -> DMS upload(s) -> Submit -> SRN.\n\nAccepts EITHER `application/json` (when files were already uploaded via `/upload-attachment` and their filenames are echoed via `attachmentFilenames`) OR `multipart/form-data` with up to 3 PDF files in fields `copyOfMinutesOfDecision`, `copyOfMinutesOfDecision1`, `copyOfMinutesOfDecision2` plus a `payload` field containing the JSON body.\n\nA successful Submit returns `srn` (e.g. `AC3417914`) and `srnStatus` (typically `Pending for DSC Upload and Payment`). MCA's per-field errors land in `saveResult.validationResponse.validationResponseBody[]`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3SubmitRequest" } },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "payload":                  { "type": "string", "description": "JSON-stringified `Dpt3SubmitRequest` body" },
                  "copyOfMinutesOfDecision":  { "type": "string", "format": "binary", "description": "Optional PDF, max 2 MB" },
                  "copyOfMinutesOfDecision1": { "type": "string", "format": "binary", "description": "Optional PDF, max 2 MB" },
                  "copyOfMinutesOfDecision2": { "type": "string", "format": "binary", "description": "Optional PDF, max 2 MB" }
                },
                "required": ["payload"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Submit result — `srn` populated on success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3SubmitResponse" } } } },
          "400": { "description": "Missing required fields OR non-ASCII characters in declaration block (resolutionNumber/declarationID/designation). Response includes `field` + `fix` pinpointing the problem.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3ErrorResponse" } } } },
          "401": { "description": "No MCA session", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "MCA rejected the submit. Common cases: duplicate filing for this CIN + FY (look for `error: \"Duplicate filing — ...\"` and ER16/ER17_DPT3 codes in `validationErrors[]`), or per-field validation failure (specific alerts in `validationErrors[]`). See Dpt3ErrorResponse schema.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Dpt3ErrorResponse" } } } }
        }
      }
    },

    "/api/dpt3/upload-attachment": {
      "post": {
        "tags": ["Form DPT-3"],
        "summary": "Upload a single DPT-3 attachment to MCA DMS",
        "description": "Standalone DMS upload — useful for uploading attachments incrementally as the user fills the form. Returns the DMS metadata; pass the resulting filename back in `attachmentFilenames` on the final `/submit` call. `referenceNumber` must come from a prior `/save-only`.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file", "referenceNumber"],
                "properties": {
                  "file":            { "type": "string", "format": "binary", "description": "PDF, max 2 MB" },
                  "referenceNumber": { "type": "string", "example": "1-25490013194" },
                  "integrationId":   { "type": "string", "example": "1-BPK3G22" },
                  "slot":            { "type": "string", "enum": ["1","2","3"], "default": "3", "description": "DPT-3 attachment slot (1 = Auditor cert, 2 = List of depositors, 3 = Optional). Maps to MCA's per-slot `attachmentLabel` (DPT3_attachment_1/2/3)." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload result. Pass `filename` back in `attachmentFilenames` AND pass the entire `result` object back in `formAttachmentMeta[]` on the final `/submit` call — MCA needs both to link the file to the SRN.",
            "content": { "application/json": { "schema": { "type": "object", "properties": {
              "success":         { "type": "boolean" },
              "filename":        { "type": "string", "example": "board-resolution.pdf" },
              "size":            { "type": "integer", "example": 51234 },
              "integrationId":   { "type": "string" },
              "referenceNumber": { "type": "string" },
              "result":          { "type": "object", "description": "Verbatim DMS response — pass into `formAttachmentMeta[]` on `/submit`", "properties": {
                "attachmentLabel":     { "type": "string", "example": "DPT3_attachment_3" },
                "attachmentDMSId":     { "type": "string", "example": "648541551" },
                "folderId":            { "type": "string", "example": "275412596" },
                "folderName":          { "type": "string", "example": "1-25491493576" },
                "activityFileName":    { "type": "string" },
                "activityFileSrcPath": { "type": "string" },
                "activityFileSize":    { "type": "string" },
                "activityFileExt":     { "type": "string" }
              } }
            } } } }
          },
          "400": { "description": "Missing file or referenceNumber", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No MCA session", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/dpt3/download-pdf": {
      "get": {
        "tags": ["Form DPT-3"],
        "summary": "Download the filed DPT-3 PDF",
        "description": "Downloads the filed DPT-3 PDF after MCA has generated it. By default (`format=pdf`) the server extracts the PDF from the ZIP MCA serves and streams it back as `application/pdf` — set `format=zip` to get the raw ZIP archive. MCA's PDF builder is asynchronous: this endpoint returns 404 until the PDF is ready (usually 2–10 min, occasionally up to 1 hour). Poll on a 30–60 s cadence.",
        "parameters": [
          { "name": "srn",    "in": "query", "schema": { "type": "string" }, "example": "AC3417914", "description": "SRN returned by `/submit` — used to resolve the DMS ID" },
          { "name": "dmsid",  "in": "query", "schema": { "type": "string" }, "description": "Direct DMS ID (skips the SRN lookup)" },
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["pdf","zip"], "default": "pdf" }, "description": "`pdf` (default): server extracts the inner PDF from MCA's ZIP and streams as `application/pdf`. `zip`: raw ZIP archive as MCA serves it." }
        ],
        "responses": {
          "200": { "description": "PDF (default) or ZIP (when `format=zip`)", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } }, "application/zip": { "schema": { "type": "string", "format": "binary" } } } },
          "400": { "description": "Missing srn/dmsid",                "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No MCA session",                   "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "PDF not yet generated",            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure",             "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/mgt7a/share-capital": {
      "get": {
        "tags": ["Form MGT-7A"],
        "summary": "Prior-year Share Capital snapshot",
        "description": "Fetches the previous-FY Share Capital / annual return snapshot for a CIN from MCA's `lastFYDetails` lookup. Used to pre-populate the Share Capital + Shareholding sections of a new MGT-7A draft so the user doesn't re-enter opening balances.\n\nDefault FY is the *previous* financial year relative to today (if current month >= April, returns last completed FY; otherwise the one before).\n\nDates accept both `MM/DD/YYYY` (MCA's wire format) and `YYYY-MM-DD` (HTML5 date input) — server normalises before encrypting.",
        "parameters": [
          { "name": "cin",    "in": "query", "required": true,  "schema": { "type": "string" }, "example": "U01100HR2020PTC086074" },
          { "name": "fyFrom", "in": "query", "required": false, "schema": { "type": "string" }, "example": "04/01/2024", "description": "FY start date. Default = previous-FY start (e.g. 04/01/YYYY-1)." },
          { "name": "fyTo",   "in": "query", "required": false, "schema": { "type": "string" }, "example": "03/31/2025", "description": "FY end date. Default = previous-FY end (e.g. 03/31/YYYY)." }
        ],
        "responses": {
          "200": {
            "description": "Pass-through of MCA's lastFYDetails payload (share capital, shareholder counts, etc. from the most recently filed annual return)",
            "content": { "application/json": { "schema": { "type": "object", "properties": {
              "cin": { "type": "string" },
              "financialYearFromDate": { "type": "string" },
              "financialYearToDate":   { "type": "string" },
              "data": { "type": "object", "description": "Raw decoded MCA response — fields include paid-up capital, authorised capital, shareholder counts, share distribution" }
            } } } }
          },
          "400": { "description": "Missing cin", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No MCA session", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "post": {
        "tags": ["Form MGT-7A"],
        "summary": "Prior-year Share Capital snapshot (POST variant)",
        "description": "Same as the GET — accepts `{ cin, fyFrom?, fyTo? }` in the JSON body. Convenience for callers that prefer POST.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["cin"],
                "properties": {
                  "cin":    { "type": "string", "example": "U01100HR2020PTC086074" },
                  "fyFrom": { "type": "string", "example": "04/01/2024" },
                  "fyTo":   { "type": "string", "example": "03/31/2025" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Same as GET" },
          "400": { "description": "Missing cin", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No MCA session", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "502": { "description": "Upstream MCA failure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/aoc4/catalogue": {
      "get": {
        "tags": ["Form AOC-4"],
        "summary": "List AOC-4 sub-forms + every top-level field",
        "description": "Returns the three composite sub-forms (main / auditor / directors) and the every top-level `formData` key each one accepts. Useful for Cursor to enumerate fields when building a UI dynamically. **No auth.**",
        "security": [],
        "responses": {
          "200": { "description": "Catalogue", "content": { "application/json": { "schema": { "type": "object", "properties": {
            "subForms": { "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string" }, "formName": { "type": "string" }, "description": { "type": "string" } } } },
            "fields":   { "type": "object", "description": "{ main:[fieldName,...], auditor:[...], directors:[...] }" },
            "flow":     { "type": "array", "items": { "type": "string" } }
          } } } } }
        }
      }
    },

    "/api/aoc4/template": {
      "get": {
        "tags": ["Form AOC-4"],
        "summary": "Get HAR-verified working payload template for a sub-form",
        "description": "Returns the verbatim payload template extracted from a real successful AOC-4 filing (CIN U66190RJ2023PTC087545). Use as a starting point: deep-merge your overrides on top.",
        "security": [],
        "parameters": [
          { "name": "form", "in": "query", "required": true, "schema": { "type": "string", "enum": ["main","auditor","directors"] }, "description": "Which sub-form's template to fetch" }
        ],
        "responses": {
          "200": { "description": "Template", "content": { "application/json": { "schema": { "type": "object", "properties": { "form": { "type": "string" }, "template": { "type": "object", "description": "Full requestBody — formData has ~75 keys for main, ~30 for auditor, ~50 for directors" } } } } } }
        }
      }
    },

    "/api/aoc4/prefill": {
      "get": {
        "tags": ["Form AOC-4"],
        "summary": "One-shot prefill — company info, ADT-1, last AOC-4 SRN",
        "description": "Runs four MCA lookups in parallel and merges them:\n- `inc12` — company master\n- `fetchAOC4SRN` — last filed AOC-4 SRN\n- `aoc4cfsFetchOldSrn` — last filed AOC-4 CFS SRN\n- `adt1_onload` — auditor info from latest ADT-1 (optional via `&adt1=false`)\n\nAny individual failure returns `null` for that field plus `<key>_err` with the error.",
        "parameters": [
          { "name": "cin",     "in": "query", "required": true,  "schema": { "type": "string" }, "example": "U66190RJ2023PTC087545" },
          { "name": "fy_from", "in": "query", "required": false, "schema": { "type": "string" }, "example": "2024-04-01", "description": "Used only for the ADT-1 lookup." },
          { "name": "fy_to",   "in": "query", "required": false, "schema": { "type": "string" }, "example": "2025-03-31" },
          { "name": "adt1",    "in": "query", "required": false, "schema": { "type": "boolean", "default": true } }
        ],
        "responses": {
          "200": { "description": "Combined prefill" },
          "400": { "description": "Missing cin",      "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "No MCA session",   "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },

    "/api/aoc4/director": {
      "get": {
        "tags": ["Form AOC-4"],
        "summary": "Director master via mgt7getDinDetails",
        "description": "Wraps MCA's `mgt7getDinDetails` lookup — returns the director's full master (name, father's name, designation, DOB, PAN, etc.) for populating `signatoryDetails` / `auditorDetails` rows.",
        "parameters": [
          { "name": "din", "in": "query", "required": true, "schema": { "type": "string" }, "example": "07789887" }
        ],
        "responses": {
          "200": { "description": "Director details" },
          "400": { "description": "Missing din" },
          "401": { "description": "No MCA session" },
          "502": { "description": "Upstream MCA failure" }
        }
      }
    },

    "/api/aoc4/save-only": {
      "post": {
        "tags": ["Form AOC-4"],
        "summary": "Save AOC-4 main draft",
        "description": "Saves the AOC-4 main form draft. Pass `{ cin, formData: {...overrides}, integrationId?, referenceNumber? }`. First Save (no integrationId) creates a new SR and returns IDs.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["cin"], "properties": {
          "cin":             { "type": "string", "example": "U66190RJ2023PTC087545" },
          "formData":        { "type": "object", "description": "Field overrides — merged onto the AOC-4 main template" },
          "integrationId":   { "type": "string", "nullable": true, "description": "From a prior Save — pass to resume the same draft" },
          "referenceNumber": { "type": "string", "nullable": true }
        } } } } },
        "responses": {
          "200": { "description": "Save result with integrationId / referenceNumber / formIntegrationId" },
          "400": { "description": "Missing cin" }, "401": { "description": "No MCA session" }, "502": { "description": "MCA rejection" }
        }
      }
    },

    "/api/aoc4/auditor/save-only": {
      "post": {
        "tags": ["Form AOC-4"],
        "summary": "Save Auditor's Report (EAUDITOR Standalone) draft",
        "description": "Same shape as `/api/aoc4/save-only` but for the auditor sub-form. Typically called with `integrationId` / `referenceNumber` / `formIntegrationId` from the AOC-4 main Proceed response.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "cin": { "type": "string" }, "formData": { "type": "object" }, "integrationId": { "type": "string" }, "referenceNumber": { "type": "string" }, "formIntegrationId": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Save result" }, "400": { "description": "Missing cin" }, "401": { "description": "No MCA session" }, "502": { "description": "MCA rejection" } }
      }
    },

    "/api/aoc4/directors/save-only": {
      "post": {
        "tags": ["Form AOC-4"],
        "summary": "Save Director's Report (e-Director's Report) draft",
        "description": "Same shape as `/api/aoc4/save-only` but for the director's report sub-form.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "cin": { "type": "string" }, "formData": { "type": "object" }, "integrationId": { "type": "string" }, "referenceNumber": { "type": "string" }, "formIntegrationId": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Save result" }, "400": { "description": "Missing cin" }, "401": { "description": "No MCA session" }, "502": { "description": "MCA rejection" } }
      }
    },

    "/api/aoc4/submit": {
      "post": {
        "tags": ["Form AOC-4"],
        "summary": "Orchestrated 6-step AOC-4 submit → returns SRN",
        "description": "Single call that runs the full filing chain:\n1. Save AOC-4 main → real IDs\n2. Proceed AOC-4 main → linked sub-form IDs\n3. Save EAUDITOR with linked IDs\n4. Proceed EAUDITOR\n5. Save e-Director's Report\n6. **Submit e-Director's Report → SRN**\n\nResponse includes a `trail[]` audit of each step so callers can resume mid-flow if anything fails.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["cin"], "properties": {
          "cin":       { "type": "string", "example": "U66190RJ2023PTC087545" },
          "main":      { "type": "object", "properties": { "formData": { "type": "object" } }, "description": "AOC-4 main overrides — see /api/aoc4/template?form=main" },
          "auditor":   { "type": "object", "properties": { "formData": { "type": "object" } } },
          "directors": { "type": "object", "properties": { "formData": { "type": "object" } } },
          "integrationId":   { "type": "string", "nullable": true, "description": "Resume an existing draft" },
          "referenceNumber": { "type": "string", "nullable": true }
        } } } } },
        "responses": {
          "200": { "description": "Filing complete", "content": { "application/json": { "schema": { "type": "object", "properties": {
            "success":   { "type": "boolean" },
            "srn":       { "type": "string", "example": "AC3497687" },
            "srnStatus": { "type": "string", "example": "Pending for DSC Upload and Payment" },
            "main":      { "type": "object" },
            "auditor":   { "type": "object" },
            "directors": { "type": "object" },
            "trail":     { "type": "array", "items": { "type": "object", "properties": { "step": { "type": "string" }, "ok": { "type": "boolean" }, "resCode": { "type": "string" }, "message": { "type": "string" }, "data": { "type": "object" } } } }
          } } } } },
          "400": { "description": "Missing cin" }, "401": { "description": "No MCA session" }, "502": { "description": "MCA rejected one of the 6 steps — see trail[]" }
        }
      }
    },

    "/api/aoc4/upload-attachment": {
      "post": {
        "tags": ["Form AOC-4"],
        "summary": "Upload an AOC-4 attachment to MCA DMS",
        "description": "Same shape as `/api/dpt3/upload-attachment` — pass `file` (PDF, ≤6 MB) + `referenceNumber` from a prior save.",
        "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "required": ["file","referenceNumber"], "properties": { "file": { "type": "string", "format": "binary" }, "referenceNumber": { "type": "string" }, "integrationId": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Upload result with DMS metadata" }, "400": { "description": "Missing file or reference" }, "401": { "description": "No MCA session" }, "502": { "description": "Upload failed" } }
      }
    },

    "/api/aoc4/download-pdf": {
      "get": {
        "tags": ["Form AOC-4"],
        "summary": "Download filed AOC-4 PDF",
        "description": "Polls MCA for the dmsid (async generation — usually 2–10 min after Submit) and streams the inner PDF unwrapped from MCA's ZIP. Pass `?format=zip` to get the raw archive.",
        "parameters": [
          { "name": "srn",    "in": "query", "schema": { "type": "string" }, "example": "AC3497687" },
          { "name": "dmsid",  "in": "query", "schema": { "type": "string" } },
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["pdf","zip"], "default": "pdf" } }
        ],
        "responses": {
          "200": { "description": "PDF (default) or ZIP", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } }, "application/zip": { "schema": { "type": "string", "format": "binary" } } } },
          "404": { "description": "PDF not yet generated" },
          "502": { "description": "Download failed" }
        }
      }
    },

    "/health": {
      "get": {
        "tags": ["Auth"],
        "summary": "Health check",
        "description": "Returns 200 OK with server timestamp. Use to confirm the API is running.",
        "security": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": { "type": "object", "properties": {
                  "status":    { "type": "string", "example": "ok" },
                  "timestamp": { "type": "string", "format": "date-time" }
                }}
              }
            }
          }
        }
      }
    }
  }
}
