{"openapi":"3.0.3","info":{"title":"qn-platform API","version":"1.0.0","description":"Certificate/license platform API: plans, orders, payments, admin, and certificate templates. Admin endpoints require login via POST /api/v1/auth/login; session is maintained via Cookie."},"components":{"schemas":{}},"paths":{"/healthz":{"get":{"summary":"Health Check","tags":["System"],"responses":{"200":{"description":"Service healthy","content":{"application/json":{"schema":{"description":"Service healthy","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"status":{"type":"string"},"db":{"type":"string"}}}}}}}}}}},"/api/v1/plans":{"get":{"summary":"Get Public Plan List","tags":["Public Plans"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"locale","required":false,"description":"Locale for translatable fields (zh|en)"}],"responses":{"200":{"description":"Active plan list","content":{"application/json":{"schema":{"description":"Active plan list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}}},"/api/v1/pricing/config":{"get":{"summary":"Get Pricing Config","tags":["Public Plans"],"parameters":[{"schema":{"type":"string"},"in":"query","name":"locale","required":false,"description":"Locale for translatable fields (zh|en)"}],"responses":{"200":{"description":"Pricing card and purchase dialog configuration","content":{"application/json":{"schema":{"description":"Pricing card and purchase dialog configuration","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}}}},"/api/v1/orders":{"post":{"summary":"Create Order","tags":["Public Orders"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["planId"],"properties":{"planId":{"type":"integer","description":"Plan ID"}},"additionalProperties":true}}}},"responses":{"200":{"description":"Order created","content":{"application/json":{"schema":{"description":"Order created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Parameter or business validation failed","content":{"application/json":{"schema":{"description":"Parameter or business validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/orders/{id}/status":{"get":{"summary":"Order & Certificate Delivery Status","tags":["Public Orders"],"description":"Certificate generation and email delivery run asynchronously after payment. Poll this endpoint to display live progress. Status values: pending_payment, processing (paid, certificate being generated/emailed), delivered, failed.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Current status","content":{"application/json":{"schema":{"description":"Current status","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"status":{"type":"string","enum":["pending_payment","processing","delivered","failed"]},"certNo":{"type":"string"},"deliveredTo":{"type":"string","description":"Masked recipient email"},"deliveredAt":{"type":"string"}}}}}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"description":"Order not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/query-plans":{"get":{"summary":"List Public Query Plans","tags":["Public Query"],"description":"List active query plans for public query pages.","parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"locale","required":false,"description":"Locale for name/description (e.g. zh, en)"}],"responses":{"200":{"description":"Active query plans","content":{"application/json":{"schema":{"description":"Active query plans","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","required":["slug","name","primaryLocale","supportedLocales","translations","queryableFields"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["null","string"]},"primaryLocale":{"type":"string"},"supportedLocales":{"type":"array","items":{"type":"string"}},"translations":{"type":"object","additionalProperties":true,"description":"Per-locale name and description (same shape as admin API)"},"queryableFields":{"type":"array","items":{"type":"object","required":["field","label","allowMultiple"],"properties":{"field":{"type":"string"},"label":{"type":"string"},"allowMultiple":{"type":"boolean"},"required":{"type":"boolean"}}}}}}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}}},"/api/v1/query/{slug}":{"get":{"summary":"Query Licenses by Plan","tags":["Public Query"],"description":"Query licenses using a query plan. Query params are dynamic based on the plan's queryableFields (e.g. company, productName, certNo). Use page and limit for pagination. For multi-value fields, use repeated params (company=A&company=B) or comma-separated (company=A,B).","parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"path","name":"slug","required":true,"description":"Query plan slug"}],"responses":{"200":{"description":"License data (fields depend on plan's returnFields)","content":{"application/json":{"schema":{"description":"License data (fields depend on plan's returnFields)","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}},"400":{"description":"At least one query parameter is required","content":{"application/json":{"schema":{"description":"At least one query parameter is required","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Plan not found or inactive","content":{"application/json":{"schema":{"description":"Plan not found or inactive","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/plugins":{"get":{"summary":"Get Official Plugin Catalog","tags":["Public Plugins"],"description":"In-memory snapshot of QuantumNous/new-api-plugins. Does not refresh GitHub on request.","responses":{"200":{"description":"Official plugin catalog","content":{"application/json":{"schema":{"description":"Official plugin catalog","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":false,"required":["source","fetchedAt","plugins"],"properties":{"source":{"type":"object","additionalProperties":false,"required":["owner","repo","url","indexUrl"],"properties":{"owner":{"type":"string"},"repo":{"type":"string"},"url":{"type":"string"},"indexUrl":{"type":"string"}}},"fetchedAt":{"type":"string"},"plugins":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["key","name","kind","latest","icon","description","models","channelTypes","sourceUrl","installUrl"],"properties":{"key":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"},"latest":{"type":"string"},"icon":{"type":["null","string"]},"description":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"LocalizedText map (always includes en), or null"},"models":{"type":"array","items":{"type":"string"}},"channelTypes":{"type":"array","items":{"type":"integer"}},"sourceUrl":{"type":"string"},"installUrl":{"type":"string"}}}}}}}}}}}}}},"/api/v1/plugins/index.json":{"get":{"summary":"Marketplace index.json","tags":["Public Plugins"],"description":"pluginindex v1 document with site-relative pinned paths. Not wrapped in the API envelope.","responses":{"200":{"description":"Marketplace index v1","content":{"application/json":{"schema":{"description":"Marketplace index v1","type":"string"}}}},"304":{"description":"Not modified"}}}},"/api/v1/plugins/{key}/plugin.js":{"get":{"summary":"Download latest plugin source","tags":["Public Plugins"],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9._-]+$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Raw plugin.js source","content":{"application/json":{"schema":{"description":"Raw plugin.js source","type":"string"}}}}}}},"/api/v1/plugins/{key}/{version}/plugin.js":{"get":{"summary":"Download a pinned plugin source","tags":["Public Plugins"],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9._-]+$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._-]+$"},"in":"path","name":"version","required":true}],"responses":{"200":{"description":"Raw plugin.js source","content":{"application/json":{"schema":{"description":"Raw plugin.js source","type":"string"}}}}}}},"/api/v1/plugins/{key}":{"get":{"summary":"Get one official plugin","tags":["Public Plugins"],"description":"Catalog entry plus usageSchema/usageExamples/routes/protocols parsed from the latest cached plugin.js.","parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9._-]+$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Official plugin detail","content":{"application/json":{"schema":{"description":"Official plugin detail","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":false,"required":["key","name","kind","latest","icon","description","models","channelTypes","sourceUrl","installUrl","usageSchema","usageExamples","routes","protocols"],"properties":{"key":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"},"latest":{"type":"string"},"icon":{"type":["null","string"]},"description":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"LocalizedText map (always includes en), or null"},"models":{"type":"array","items":{"type":"string"}},"channelTypes":{"type":"array","items":{"type":"integer"}},"sourceUrl":{"type":"string"},"installUrl":{"type":"string"},"usageSchema":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["key","kind","description"],"properties":{"key":{"type":"string"},"kind":{"type":"string","enum":["number","boolean","enum"]},"unit":{"type":"string","enum":["second","count","token","credit"]},"values":{"type":"array","items":{"type":"string"}},"description":{"type":["null","object"],"additionalProperties":{"type":"string"}}}}},"usageExamples":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["label","facts"],"properties":{"label":{"type":"string"},"facts":{"type":"object","additionalProperties":{"type":["string","number","boolean"]}}}}},"routes":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["method","path","type","action"],"properties":{"method":{"type":"string"},"path":{"type":"string"},"type":{"type":"string","enum":["submit","query","dynamic"]},"action":{"type":["null","string"]}}}},"protocols":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["name","supports","models","operations"],"properties":{"name":{"type":"string"},"supports":{"type":"array","items":{"type":"string"}},"models":{"type":"array","items":{"type":"string"}},"operations":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["operation","method","path","modes"],"properties":{"operation":{"type":"string"},"method":{"type":"string"},"path":{"type":"string"},"modes":{"type":"boolean"}}}}}}}}}}}}}}}}},"/api/v1/payments/webhook":{"post":{"summary":"Payment Success Callback","tags":["Public Payments"],"description":"Payment channel callback, requires signature and timestamp validation","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Processed successfully","content":{"application/json":{"schema":{"description":"Processed successfully","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"licenseId":{"type":"string"},"deliveredTo":{"type":"string"},"deduped":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid signature or parameters","content":{"application/json":{"schema":{"description":"Invalid signature or parameters","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"401":{"description":"Invalid signature or timestamp","content":{"application/json":{"schema":{"description":"Invalid signature or timestamp","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"description":"Order not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Order status not allowed","content":{"application/json":{"schema":{"description":"Order status not allowed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"503":{"description":"Payment webhook secret not configured","content":{"application/json":{"schema":{"description":"Payment webhook secret not configured","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/payments/epay/config":{"get":{"summary":"Epay config status","tags":["Public Payments"],"description":"Returns whether epay is configured and which payment methods are available","responses":{"200":{"description":"Epay availability and supported methods","content":{"application/json":{"schema":{"description":"Epay availability and supported methods","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"available":{"type":"boolean"},"methods":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}}}}}}}}}}}}}},"/api/v1/payments/epay/pay":{"post":{"summary":"Create epay payment","tags":["Public Payments"],"description":"Generate epay form params for the given order. Frontend should POST the params to the returned URL.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["orderId","paymentMethod"],"properties":{"orderId":{"type":"string","description":"Order ID (UUID)"},"paymentMethod":{"type":"string","description":"Payment method, e.g. \"alipay\" or \"wxpay\""}}}}}},"responses":{"200":{"description":"Payment URL and form params","content":{"application/json":{"schema":{"description":"Payment URL and form params","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"url":{"type":"string"},"params":{"type":"object","additionalProperties":{"type":"string"}}}}}}}}},"400":{"description":"Invalid order or payment params","content":{"application/json":{"schema":{"description":"Invalid order or payment params","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"503":{"description":"Epay not configured","content":{"application/json":{"schema":{"description":"Epay not configured","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/auth/login":{"post":{"summary":"Admin Login","tags":["Auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string"},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"Login successful, sets httpOnly cookie","content":{"application/json":{"schema":{"description":"Login successful, sets httpOnly cookie","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"username":{"type":"string"},"displayName":{"type":"string","nullable":true},"role":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"isSystem":{"type":"boolean"}}},"permissions":{"type":"array","items":{"type":"string"}}}}}}}}},"401":{"description":"Invalid username or password","content":{"application/json":{"schema":{"description":"Invalid username or password","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"429":{"description":"Too many failed attempts — IP temporarily locked","content":{"application/json":{"schema":{"description":"Too many failed attempts — IP temporarily locked","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/auth/logout":{"post":{"summary":"Admin Logout","tags":["Auth"],"responses":{"200":{"description":"Session revoked and cookie cleared","content":{"application/json":{"schema":{"description":"Session revoked and cookie cleared","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}}}}},"/api/v1/auth/me":{"get":{"summary":"Check Auth Status","tags":["Auth"],"responses":{"200":{"description":"Authenticated","content":{"application/json":{"schema":{"description":"Authenticated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"username":{"type":"string"},"displayName":{"type":"string","nullable":true},"role":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"isSystem":{"type":"boolean"}}},"permissions":{"type":"array","items":{"type":"string"}}}}}}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"description":"Not authenticated","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/auth/change-password":{"post":{"summary":"Change Own Password","tags":["Auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["currentPassword","newPassword"],"properties":{"currentPassword":{"type":"string"},"newPassword":{"type":"string"}}}}}},"responses":{"200":{"description":"Password changed","content":{"application/json":{"schema":{"description":"Password changed","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"400":{"description":"Validation failed or current password incorrect","content":{"application/json":{"schema":{"description":"Validation failed or current password incorrect","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"description":"Not authenticated","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/form-fields":{"get":{"summary":"Form Field List","tags":["Form Fields"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"locale","required":false,"description":"Locale for translatable fields (zh|en)"},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (label, key, type, placeholder)"}],"responses":{"200":{"description":"Field list","content":{"application/json":{"schema":{"description":"Field list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}},"post":{"summary":"Create Form Field","tags":["Form Fields"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["text","email","date","textarea"]},"required":{"type":"boolean"},"placeholder":{"type":"string"},"helpText":{"type":"string"},"translations":{"type":"object","additionalProperties":true},"colSpan":{"type":"integer"},"sortOrder":{"type":"integer"}}}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"description":"Created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed or key already exists","content":{"application/json":{"schema":{"description":"Validation failed or key already exists","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/form-fields/{id}":{"patch":{"summary":"Update Form Field","tags":["Form Fields"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string"},"type":{"type":"string"},"required":{"type":"boolean"},"placeholder":{"type":"string"},"helpText":{"type":"string"},"translations":{"type":"object","additionalProperties":true}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"System fields only allow partial modifications","content":{"application/json":{"schema":{"description":"System fields only allow partial modifications","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Field not found","content":{"application/json":{"schema":{"description":"Field not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Form Field","tags":["Form Fields"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"403":{"description":"System required fields cannot be deleted","content":{"application/json":{"schema":{"description":"System required fields cannot be deleted","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Field not found","content":{"application/json":{"schema":{"description":"Field not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Field is referenced by plans","content":{"application/json":{"schema":{"description":"Field is referenced by plans","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/plans":{"get":{"summary":"Plan List","tags":["Plans"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (slug, currency, billingCycle, name/description)"}],"responses":{"200":{"description":"Plan list","content":{"application/json":{"schema":{"description":"Plan list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"primaryLocale":{"type":"string"},"supportedLocales":{"type":"array","items":{"type":"string"}},"translations":{"type":"object","additionalProperties":{"type":"object","required":["name","description","licenseTitle","defaultScope","features"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"licenseTitle":{"type":"string"},"defaultScope":{"type":"string"},"features":{"type":"object","required":["tierFeatures"],"properties":{"tierFeatures":{"type":"array","items":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"negative":{"type":"boolean"},"tooltip":{"type":"string"}}}},"buttonText":{"type":"string"},"extraTopLine":{"type":"string"},"extraSubLine":{"type":"string"},"priceLabel":{"type":"string"}}}}}},"currency":{"type":"string"},"priceCents":{"type":"integer"},"billingCycle":{"type":"string"},"status":{"type":"string","enum":["on_shelf","off_shelf"],"description":"on_shelf=上架, off_shelf=下架"},"hasBeenOrdered":{"type":"boolean","description":"Whether this plan has been ordered"},"features":{"type":"object","additionalProperties":true},"highlight":{"type":"boolean","description":"Whether this plan is highlighted as default on the pricing page"},"purchaseFormFields":{"type":"array","items":{"type":"object","additionalProperties":true}},"purchaseFormFieldIds":{"type":"array","items":{"type":"integer"}},"certificateTemplateId":{"type":["null","integer"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}},"post":{"summary":"Create Plan","tags":["Plans"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["translations","priceCents","purchaseFormFieldIds"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]+$","description":"URL-friendly identifier (lowercase alphanumeric and hyphens)"},"primaryLocale":{"type":"string","enum":["zh","en"],"default":"zh","description":"Primary locale (market selector: zh = domestic pricing page, en = international)"},"supportedLocales":{"type":"array","items":{"type":"string"},"default":["zh","en"],"description":"Supported locale codes"},"translations":{"type":"object","additionalProperties":{"type":"object","required":["name","description","licenseTitle","defaultScope","features"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"licenseTitle":{"type":"string"},"defaultScope":{"type":"string"},"features":{"type":"object","required":["tierFeatures"],"properties":{"tierFeatures":{"type":"array","items":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"negative":{"type":"boolean"},"tooltip":{"type":"string"}}}},"buttonText":{"type":"string"},"extraTopLine":{"type":"string"},"extraSubLine":{"type":"string"},"priceLabel":{"type":"string"}}}}},"minProperties":1,"description":"Translations by locale key (e.g. { zh: {...}, en: {...} })"},"currency":{"type":"string","default":"CNY"},"priceCents":{"type":"integer","minimum":0},"billingCycle":{"type":"string","default":"year"},"features":{"type":"object","additionalProperties":true,"default":{}},"purchaseFormFieldIds":{"type":"array","items":{"type":"integer","minimum":1},"minItems":1,"description":"At least one form field must be selected"},"certificateTemplateId":{"type":["integer","null"],"minimum":1,"description":"Optional certificate template override (must match plan's primaryLocale)"}}}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"description":"Created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"primaryLocale":{"type":"string"},"supportedLocales":{"type":"array","items":{"type":"string"}},"translations":{"type":"object","additionalProperties":{"type":"object","required":["name","description","licenseTitle","defaultScope","features"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"licenseTitle":{"type":"string"},"defaultScope":{"type":"string"},"features":{"type":"object","required":["tierFeatures"],"properties":{"tierFeatures":{"type":"array","items":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"negative":{"type":"boolean"},"tooltip":{"type":"string"}}}},"buttonText":{"type":"string"},"extraTopLine":{"type":"string"},"extraSubLine":{"type":"string"},"priceLabel":{"type":"string"}}}}}},"currency":{"type":"string"},"priceCents":{"type":"integer"},"billingCycle":{"type":"string"},"status":{"type":"string","enum":["on_shelf","off_shelf"],"description":"on_shelf=上架, off_shelf=下架"},"hasBeenOrdered":{"type":"boolean","description":"Whether this plan has been ordered"},"features":{"type":"object","additionalProperties":true},"highlight":{"type":"boolean","description":"Whether this plan is highlighted as default on the pricing page"},"purchaseFormFields":{"type":"array","items":{"type":"object","additionalProperties":true}},"purchaseFormFieldIds":{"type":"array","items":{"type":"integer"}},"certificateTemplateId":{"type":["null","integer"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/plans/{id}":{"patch":{"summary":"Update Plan","tags":["Plans"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","minProperties":1,"properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]+$"},"primaryLocale":{"type":"string","enum":["zh","en"]},"supportedLocales":{"type":"array","items":{"type":"string"}},"translations":{"type":"object","additionalProperties":{"type":"object","required":["name","description","licenseTitle","defaultScope","features"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"licenseTitle":{"type":"string"},"defaultScope":{"type":"string"},"features":{"type":"object","required":["tierFeatures"],"properties":{"tierFeatures":{"type":"array","items":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"negative":{"type":"boolean"},"tooltip":{"type":"string"}}}},"buttonText":{"type":"string"},"extraTopLine":{"type":"string"},"extraSubLine":{"type":"string"},"priceLabel":{"type":"string"}}}}},"minProperties":1,"description":"Translations by locale key (e.g. { zh: {...}, en: {...} })"},"currency":{"type":"string"},"priceCents":{"type":"integer","minimum":0},"billingCycle":{"type":"string"},"features":{"type":"object","additionalProperties":true},"purchaseFormFieldIds":{"type":"array","items":{"type":"integer","minimum":1},"minItems":1},"certificateTemplateId":{"type":["integer","null"],"minimum":1}}},{"type":"string","description":"JSON string of update object"}]}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"primaryLocale":{"type":"string"},"supportedLocales":{"type":"array","items":{"type":"string"}},"translations":{"type":"object","additionalProperties":{"type":"object","required":["name","description","licenseTitle","defaultScope","features"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"licenseTitle":{"type":"string"},"defaultScope":{"type":"string"},"features":{"type":"object","required":["tierFeatures"],"properties":{"tierFeatures":{"type":"array","items":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"negative":{"type":"boolean"},"tooltip":{"type":"string"}}}},"buttonText":{"type":"string"},"extraTopLine":{"type":"string"},"extraSubLine":{"type":"string"},"priceLabel":{"type":"string"}}}}}},"currency":{"type":"string"},"priceCents":{"type":"integer"},"billingCycle":{"type":"string"},"status":{"type":"string","enum":["on_shelf","off_shelf"],"description":"on_shelf=上架, off_shelf=下架"},"hasBeenOrdered":{"type":"boolean","description":"Whether this plan has been ordered"},"features":{"type":"object","additionalProperties":true},"highlight":{"type":"boolean","description":"Whether this plan is highlighted as default on the pricing page"},"purchaseFormFields":{"type":"array","items":{"type":"object","additionalProperties":true}},"purchaseFormFieldIds":{"type":"array","items":{"type":"integer"}},"certificateTemplateId":{"type":["null","integer"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Plan not found","content":{"application/json":{"schema":{"description":"Plan not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Plan","tags":["Plans"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"404":{"description":"Plan not found","content":{"application/json":{"schema":{"description":"Plan not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Plan has been ordered (use off-shelf instead) or has licenses","content":{"application/json":{"schema":{"description":"Plan has been ordered (use off-shelf instead) or has licenses","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/plans/{id}/status":{"patch":{"summary":"Update Plan Shelf Status","tags":["Plans"],"description":"on_shelf=上架, off_shelf=下架","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["on_shelf","off_shelf"]}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Status updated","content":{"application/json":{"schema":{"description":"Status updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"primaryLocale":{"type":"string"},"supportedLocales":{"type":"array","items":{"type":"string"}},"translations":{"type":"object","additionalProperties":{"type":"object","required":["name","description","licenseTitle","defaultScope","features"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"licenseTitle":{"type":"string"},"defaultScope":{"type":"string"},"features":{"type":"object","required":["tierFeatures"],"properties":{"tierFeatures":{"type":"array","items":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"negative":{"type":"boolean"},"tooltip":{"type":"string"}}}},"buttonText":{"type":"string"},"extraTopLine":{"type":"string"},"extraSubLine":{"type":"string"},"priceLabel":{"type":"string"}}}}}},"currency":{"type":"string"},"priceCents":{"type":"integer"},"billingCycle":{"type":"string"},"status":{"type":"string","enum":["on_shelf","off_shelf"],"description":"on_shelf=上架, off_shelf=下架"},"hasBeenOrdered":{"type":"boolean","description":"Whether this plan has been ordered"},"features":{"type":"object","additionalProperties":true},"highlight":{"type":"boolean","description":"Whether this plan is highlighted as default on the pricing page"},"purchaseFormFields":{"type":"array","items":{"type":"object","additionalProperties":true}},"purchaseFormFieldIds":{"type":"array","items":{"type":"integer"}},"certificateTemplateId":{"type":["null","integer"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Plan not found","content":{"application/json":{"schema":{"description":"Plan not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/licenses":{"get":{"summary":"License List","tags":["Licenses"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (cert no, company, product, license title, fingerprint, email)"}],"responses":{"200":{"description":"License list","content":{"application/json":{"schema":{"description":"License list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}},"post":{"summary":"Create License (Manual Entry)","tags":["Licenses"],"description":"Manually issue a license without an order. Cert number, fingerprint short code and certificate are generated exactly like the paid flow. With sendEmail=true the certificate is rendered and emailed asynchronously (status: issuing); otherwise the license is recorded with status \"issued\" and the certificate PNG is rendered in the background without sending email.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["planId"],"properties":{"planId":{"type":"integer","minimum":1,"description":"Owning plan ID"},"issueDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Defaults to today"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Defaults to issueDate + plan billing cycle"},"sendEmail":{"type":"boolean","default":false,"description":"Send certificate email after creation (requires buyerEmail)"},"formData":{"type":"object","additionalProperties":true,"description":"Purchase-form field values (company, buyerEmail, buyerName, …)"}}}}}},"responses":{"201":{"description":"Created license","content":{"application/json":{"schema":{"description":"Created license","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed / plan not found","content":{"application/json":{"schema":{"description":"Validation failed / plan not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/licenses/{id}":{"patch":{"summary":"Update License","tags":["Licenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"formData":{"type":"object"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"License not found","content":{"application/json":{"schema":{"description":"License not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete License","tags":["Licenses"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"404":{"description":"License not found","content":{"application/json":{"schema":{"description":"License not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/licenses/{id}/resend":{"post":{"summary":"Resend Certificate Email","tags":["Licenses"],"description":"Queues the license for asynchronous redelivery and returns immediately. The background worker reuses the already-rendered certificate artifact when available (re-rendering only if it is missing) and emails it with automatic retries. Track progress via the license status (issuing → delivered / failed).","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Resend queued","content":{"application/json":{"schema":{"description":"Resend queued","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"400":{"description":"No email or missing info","content":{"application/json":{"schema":{"description":"No email or missing info","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"License not found","content":{"application/json":{"schema":{"description":"License not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/licenses/{id}/file":{"get":{"summary":"Download Certificate Image","tags":["Licenses"],"description":"Returns the rendered certificate artifact (PNG). Re-renders from the license row when the on-disk file is missing. 409 while the certificate is still being generated.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"404":{"description":"License not found","content":{"application/json":{"schema":{"description":"License not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Certificate not generated yet","content":{"application/json":{"schema":{"description":"Certificate not generated yet","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/licenses/{id}/versions":{"get":{"summary":"License Version History","tags":["Licenses"],"description":"All content revisions of a license, newest first (v1 = creation, +1 per admin edit). Each entry includes the immutable content snapshot for field-level diffing.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Version list","content":{"application/json":{"schema":{"description":"Version list","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"404":{"description":"License not found","content":{"application/json":{"schema":{"description":"License not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/licenses/{id}/versions/{versionNo}/file":{"get":{"summary":"Download Certificate Version Image","tags":["Licenses"],"description":"Returns one historical version's certificate artifact. Re-renders it from the version's immutable snapshot when the on-disk file is missing.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"versionNo","required":true}],"responses":{"404":{"description":"License or version not found","content":{"application/json":{"schema":{"description":"License or version not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/orders":{"get":{"summary":"List Orders (Paginated)","tags":["Orders"],"parameters":[{"schema":{"type":"string"},"in":"query","name":"page","required":false},{"schema":{"type":"string"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (id, buyer name/email, company, product, license title)"}],"responses":{"200":{"description":"Order list","content":{"application/json":{"schema":{"description":"Order list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}}},"/api/v1/admin/orders/{id}/mark-paid":{"post":{"summary":"Manually Mark Order as Paid","tags":["Orders"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Marked successfully","content":{"application/json":{"schema":{"description":"Marked successfully","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"licenseId":{"type":"string"},"deliveredTo":{"type":"string"},"deduped":{"type":"boolean"}}}}}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"description":"Order not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Order status not allowed","content":{"application/json":{"schema":{"description":"Order status not allowed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/certificate-templates":{"get":{"summary":"Certificate Template List","tags":["Certificate Templates"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","enum":["zh","en"]},"in":"query","name":"locale","required":false},{"schema":{"type":"string"},"in":"query","name":"q","required":false}],"responses":{"200":{"description":"Template list","content":{"application/json":{"schema":{"description":"Template list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}},"post":{"summary":"Create Certificate Template","tags":["Certificate Templates"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"locale":{"type":"string","enum":["zh","en"]},"canvasWidth":{"type":"number"},"canvasHeight":{"type":"number"},"elements":{"type":"array"},"isDefault":{"type":"boolean"},"isActive":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Created successfully","content":{"application/json":{"schema":{"description":"Created successfully","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/certificate-templates/variables":{"get":{"summary":"Certificate Template Available Variables","tags":["Certificate Templates"],"responses":{"200":{"description":"Variable list","content":{"application/json":{"schema":{"description":"Variable list","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"array"}}}}}}}}},"/api/v1/admin/certificate-templates/{id}":{"get":{"summary":"Get Single Certificate Template","tags":["Certificate Templates"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Template details","content":{"application/json":{"schema":{"description":"Template details","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"description":"Invalid parameters","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"description":"Template not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"patch":{"summary":"Update Certificate Template","tags":["Certificate Templates"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"locale":{"type":"string","enum":["zh","en"]},"elements":{"type":"array"},"isDefault":{"type":"boolean"},"isActive":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated successfully","content":{"application/json":{"schema":{"description":"Updated successfully","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"description":"Invalid parameters","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"description":"Template not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Certificate Template","tags":["Certificate Templates"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted successfully","content":{"application/json":{"schema":{"description":"Deleted successfully","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"400":{"description":"Default template cannot be deleted","content":{"application/json":{"schema":{"description":"Default template cannot be deleted","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"description":"Template not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/certificate-templates/{id}/duplicate":{"post":{"summary":"Duplicate Certificate Template","tags":["Certificate Templates"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"201":{"description":"Duplicated successfully","content":{"application/json":{"schema":{"description":"Duplicated successfully","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"description":"Template not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/certificate-templates/{id}/set-default":{"post":{"summary":"Set Default Certificate Template","tags":["Certificate Templates"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Set successfully","content":{"application/json":{"schema":{"description":"Set successfully","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"description":"Template not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/translate/batch-from-primary":{"post":{"summary":"Batch translate from primary (zh)","tags":["Translation"],"description":"Translate plan content from primary language (zh) to multiple target locales using AI.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["content","targetLocales"],"properties":{"content":{"type":"object","description":"Primary (zh) plan content to translate","properties":{"name":{"type":"string"},"description":{"type":"string"},"licenseTitle":{"type":"string"},"defaultScope":{"type":"string"},"features":{"type":"object","properties":{"tierFeatures":{"type":"array","items":{"type":"object"}},"buttonText":{"type":"string"},"extraTopLine":{"type":"string"},"extraSubLine":{"type":"string"}}}}},"targetLocales":{"type":"array","items":{"type":"string"},"description":"Target locale codes (e.g. ['en'])"}}}}}},"responses":{"200":{"description":"Translations by locale","content":{"application/json":{"schema":{"description":"Translations by locale","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true,"description":"Map of locale -> PlanI18nFields"}}}}}},"400":{"description":"Validation or configuration error","content":{"application/json":{"schema":{"description":"Validation or configuration error","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/translate/to-locale":{"post":{"summary":"Translate to single locale","tags":["Translation"],"description":"Translate plan content to a target locale. Used for re-translation from any source language.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["content","targetLocale"],"properties":{"content":{"type":"object","description":"Source plan content"},"targetLocale":{"type":"string","description":"Target locale (e.g. en)"},"sourceLocale":{"type":"string","description":"Optional source locale hint"}}}}}},"responses":{"200":{"description":"Translated content","content":{"application/json":{"schema":{"description":"Translated content","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true,"description":"PlanI18nFields for target locale"}}}}}},"400":{"description":"Validation or configuration error","content":{"application/json":{"schema":{"description":"Validation or configuration error","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/translate/field":{"post":{"summary":"Translate single field (batch)","tags":["Translation"],"description":"Translate one field from primary (zh) to multiple locales. Simple API.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fieldKey","primaryValue","targetLocales"],"properties":{"fieldKey":{"type":"string","enum":["name","description","licenseTitle","defaultScope","tierFeature","buttonText","extraTopLine","extraSubLine","fieldLabel","fieldPlaceholder","fieldHelpText"]},"primaryValue":{"oneOf":[{"type":"string"},{"type":"object","properties":{"text":{"type":"string"},"tooltip":{"type":"string"},"negative":{"type":"boolean"}}}]},"targetLocales":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"Translations by locale","content":{"application/json":{"schema":{"description":"Translations by locale","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}}}}},"/api/v1/admin/translate/field/to-locale":{"post":{"summary":"Translate single field to one locale","tags":["Translation"],"description":"Translate one field from primary (zh) to target locale. Simple API.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fieldKey","primaryValue","targetLocale"],"properties":{"fieldKey":{"type":"string","enum":["name","description","licenseTitle","defaultScope","tierFeature","buttonText","extraTopLine","extraSubLine","fieldLabel","fieldPlaceholder","fieldHelpText"]},"primaryValue":{"oneOf":[{"type":"string"},{"type":"object","properties":{"text":{"type":"string"},"tooltip":{"type":"string"},"negative":{"type":"boolean"}}}]},"targetLocale":{"type":"string"}}}}}},"responses":{"200":{"description":"Translated value","content":{"application/json":{"schema":{"description":"Translated value","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{}}}}}}}}},"/api/v1/admin/stats":{"get":{"summary":"Get Dashboard Stats","tags":["Orders"],"responses":{"200":{"description":"Dashboard stats","content":{"application/json":{"schema":{"description":"Dashboard stats","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"totalRevenueCents":{"type":"number"},"totalOrders":{"type":"number"},"pendingOrders":{"type":"number"},"paidOrders":{"type":"number"},"totalLicenses":{"type":"number"},"deliveredLicenses":{"type":"number"},"activePlans":{"type":"number"},"totalRevenueByDay":{"type":"array"},"ordersByDay":{"type":"array"},"ordersByPlan":{"type":"array"}}}}}}}}}}},"/api/v1/admin/query-plans":{"get":{"summary":"Query Plan List","tags":["Query Plans"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (name, slug, description)"}],"responses":{"200":{"description":"Query plan list","content":{"application/json":{"schema":{"description":"Query plan list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}},"post":{"summary":"Create Query Plan","tags":["Query Plans"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["translations","queryableFields","returnFields"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]+$","description":"Optional; auto-generated if omitted"},"primaryLocale":{"type":"string","description":"Primary locale (e.g. zh)"},"supportedLocales":{"type":"array","items":{"type":"string"},"description":"Supported locales"},"translations":{"type":"object","description":"Locale-keyed { name, description? } (e.g. { zh: {...}, en: {...} })","additionalProperties":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"}}}},"queryableFields":{"type":"array","items":{"type":"object","required":["field","label","allowMultiple"],"properties":{"field":{"type":"string"},"label":{"type":"string"},"allowMultiple":{"type":"boolean"},"required":{"type":"boolean"}}}},"returnFields":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","inactive"]}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"description":"Created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/query-plans/field-catalog":{"get":{"summary":"Query Plan Field Catalog","tags":["Query Plans"],"description":"License fields usable in query plans. `field` is the config value (e.g. certNo, extra.domain); `i18nKey` is the frontend label key.","responses":{"200":{"description":"Field catalog","content":{"application/json":{"schema":{"description":"Field catalog","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"filterable":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"i18nKey":{"type":"string"}}}},"returnable":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"i18nKey":{"type":"string"}}}}}}}}}}}}}},"/api/v1/admin/query-plans/{id}":{"get":{"summary":"Get Query Plan","tags":["Query Plans"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Query plan","content":{"application/json":{"schema":{"description":"Query plan","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"patch":{"summary":"Update Query Plan","tags":["Query Plans"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Query Plan","tags":["Query Plans"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/query-plans/{id}/test":{"post":{"summary":"Test Query Plan","tags":["Query Plans"],"description":"Execute query with given params and return results for manual verification","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["params"],"properties":{"params":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}},"page":{"type":"integer"},"limit":{"type":"integer"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Query results","content":{"application/json":{"schema":{"description":"Query results","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contract-templates":{"get":{"summary":"Contract Template List","tags":["Contract Templates"],"responses":{"200":{"description":"Contract template catalog","content":{"application/json":{"schema":{"description":"Contract template catalog","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}}},"/api/v1/admin/contract-templates/{key}":{"get":{"summary":"Get Contract Template","tags":["Contract Templates"],"description":"Template metadata including the form field definitions","parameters":[{"schema":{"type":"string"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Contract template detail","content":{"application/json":{"schema":{"description":"Contract template detail","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contract-templates/{key}/file":{"get":{"summary":"Download Blank Template","tags":["Contract Templates"],"description":"DOCX with our default signing entity pre-filled and all business blanks printable","parameters":[{"schema":{"type":"string"},"in":"query","name":"variant","required":false,"description":"Template variant id"},{"schema":{"type":"string"},"in":"path","name":"key","required":true}],"responses":{"400":{"description":"Invalid variant","content":{"application/json":{"schema":{"description":"Invalid variant","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contracts":{"get":{"summary":"Contract List","tags":["Contracts"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (contract no, title, party names)"},{"schema":{"type":"string","enum":["draft","sent","signed","voided"]},"in":"query","name":"status","required":false},{"schema":{"type":"string","maxLength":64},"in":"query","name":"templateKey","required":false}],"responses":{"200":{"description":"Contract list","content":{"application/json":{"schema":{"description":"Contract list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}},"post":{"summary":"Create Contract","tags":["Contracts"],"description":"Assigns a contract number, renders the DOCX artifact and stores the ledger row (status: draft)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["templateKey"],"properties":{"templateKey":{"type":"string"},"variant":{"type":"string"},"counterpartyId":{"type":["integer","null"]},"partyA":{"type":"object","additionalProperties":true},"partyB":{"type":"object","additionalProperties":true},"values":{"type":"object","additionalProperties":true},"remark":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"description":"Created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"description":"Template not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contracts/preview":{"post":{"summary":"Preview Contract DOCX","tags":["Contracts"],"description":"Builds the DOCX from the given data without persisting anything","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["templateKey"],"properties":{"templateKey":{"type":"string"},"variant":{"type":"string"},"contractNo":{"type":"string"},"partyA":{"type":"object","additionalProperties":true},"partyB":{"type":"object","additionalProperties":true},"values":{"type":"object","additionalProperties":true}}}}}},"responses":{"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"description":"Template not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contracts/{id}":{"get":{"summary":"Get Contract","tags":["Contracts"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Contract","content":{"application/json":{"schema":{"description":"Contract","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"patch":{"summary":"Update Contract (draft only)","tags":["Contracts"],"description":"Updates parties/field values and regenerates the DOCX artifact","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Contract is not a draft","content":{"application/json":{"schema":{"description":"Contract is not a draft","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Contract (draft only)","tags":["Contracts"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Contract is not a draft","content":{"application/json":{"schema":{"description":"Contract is not a draft","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contracts/{id}/status":{"patch":{"summary":"Transition Contract Status","tags":["Contracts"],"description":"draft → sent → signed | voided; signing requires signDate","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["draft","sent","signed","voided"]},"signDate":{"type":"string","description":"yyyy-mm-dd, required for signed"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Invalid status transition","content":{"application/json":{"schema":{"description":"Invalid status transition","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contracts/{id}/file":{"get":{"summary":"Download Contract DOCX","tags":["Contracts"],"description":"Rebuilds the artifact from the stored snapshot when the file is missing","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contracts/{id}/versions":{"get":{"summary":"Contract Version History","tags":["Contracts"],"description":"All content revisions of a contract, newest first (v1 = creation, +1 per draft edit). Each entry includes the immutable content snapshot for field-level diffing.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Version list","content":{"application/json":{"schema":{"description":"Version list","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contracts/{id}/versions/{versionNo}/file":{"get":{"summary":"Download Contract Version DOCX","tags":["Contracts"],"description":"The DOCX of one historical version. Rebuilds the file from the version's immutable snapshot when it is missing on disk.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"versionNo","required":true}],"responses":{"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contract-parties":{"get":{"summary":"Contract Party List","tags":["Contract Parties"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (name, English name, USCC, contact)"},{"schema":{"type":"string","enum":["internal","external"]},"in":"query","name":"kind","required":false}],"responses":{"200":{"description":"Contract party list","content":{"application/json":{"schema":{"description":"Contract party list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}}}},"post":{"summary":"Create Contract Party","tags":["Contract Parties"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"kind":{"type":"string","enum":["internal","external"]},"name":{"type":"string"},"nameEn":{"type":"string"},"uscc":{"type":"string"},"address":{"type":"string"},"addressEn":{"type":"string"},"contactName":{"type":"string"},"contactNameEn":{"type":"string"},"contactPhone":{"type":"string"},"contactEmail":{"type":"string"},"bankAccounts":{"type":"array","items":{"type":"object","additionalProperties":true}},"notes":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"description":"Created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/contract-parties/{id}":{"get":{"summary":"Get Contract Party","tags":["Contract Parties"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Contract party","content":{"application/json":{"schema":{"description":"Contract party","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"patch":{"summary":"Update Contract Party","tags":["Contract Parties"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Contract Party","tags":["Contract Parties"],"description":"Safe to delete: contract instances keep their own party snapshots (soft link is nulled)","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"description":"Not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/users":{"get":{"summary":"Admin User List","tags":["Admin Users"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (username, display name)"}],"responses":{"200":{"description":"User list","content":{"application/json":{"schema":{"description":"User list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"post":{"summary":"Create Admin User","tags":["Admin Users"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username","password","roleId"],"properties":{"username":{"type":"string"},"displayName":{"type":"string","nullable":true},"password":{"type":"string"},"roleId":{"type":"integer"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"description":"Created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed or username already exists","content":{"application/json":{"schema":{"description":"Validation failed or username already exists","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/users/{id}":{"patch":{"summary":"Update Admin User","tags":["Admin Users"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"displayName":{"type":"string","nullable":true},"password":{"type":"string","description":"Set to reset the user's password"},"roleId":{"type":"integer"},"isActive":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed or last super admin protection","content":{"application/json":{"schema":{"description":"Validation failed or last super admin protection","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Insufficient permissions or self-deactivation attempt","content":{"application/json":{"schema":{"description":"Insufficient permissions or self-deactivation attempt","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"description":"User not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Admin User","tags":["Admin Users"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"400":{"description":"Last super admin protection","content":{"application/json":{"schema":{"description":"Last super admin protection","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Insufficient permissions or self-deletion attempt","content":{"application/json":{"schema":{"description":"Insufficient permissions or self-deletion attempt","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"description":"User not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/roles/permission-catalog":{"get":{"summary":"Permission Catalog","tags":["Admin Roles"],"responses":{"200":{"description":"Grouped permission keys defined in code","content":{"application/json":{"schema":{"description":"Grouped permission keys defined in code","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}}}}}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/roles/all":{"get":{"summary":"All Roles (for pickers)","tags":["Admin Roles"],"responses":{"200":{"description":"Flat list of all roles","content":{"application/json":{"schema":{"description":"Flat list of all roles","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/roles":{"get":{"summary":"Admin Role List","tags":["Admin Roles"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (name, description)"}],"responses":{"200":{"description":"Role list","content":{"application/json":{"schema":{"description":"Role list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"post":{"summary":"Create Admin Role","tags":["Admin Roles"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","permissions"],"properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"permissions":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"description":"Created","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed or role name already exists","content":{"application/json":{"schema":{"description":"Validation failed or role name already exists","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/roles/{id}":{"patch":{"summary":"Update Admin Role","tags":["Admin Roles"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"permissions":{"type":"array","items":{"type":"string"}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"description":"Updated","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Validation failed or role name already exists","content":{"application/json":{"schema":{"description":"Validation failed or role name already exists","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Insufficient permissions or system role","content":{"application/json":{"schema":{"description":"Insufficient permissions or system role","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Role not found","content":{"application/json":{"schema":{"description":"Role not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"delete":{"summary":"Delete Admin Role","tags":["Admin Roles"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"description":"Deleted","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"null"}}}}}},"403":{"description":"Insufficient permissions or system role","content":{"application/json":{"schema":{"description":"Insufficient permissions or system role","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Role not found","content":{"application/json":{"schema":{"description":"Role not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"409":{"description":"Role is assigned to users","content":{"application/json":{"schema":{"description":"Role is assigned to users","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/settings":{"get":{"summary":"List System Settings","tags":["System Settings"],"description":"Catalog of runtime settings with resolved values and their source (database / environment / default). Secret values are never returned.","responses":{"200":{"description":"Settings catalog","content":{"application/json":{"schema":{"description":"Settings catalog","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","required":["settings"],"properties":{"settings":{"type":"array","items":{"type":"object","required":["key","group","kind","secret","source","isSet"],"properties":{"key":{"type":"string"},"group":{"type":"string"},"kind":{"type":"string","enum":["string","number","boolean"]},"secret":{"type":"boolean"},"source":{"type":"string","enum":["database","environment","default"]},"value":{},"isSet":{"type":"boolean"}}}}}}}}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"description":"Not authenticated","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}},"put":{"summary":"Update System Settings","tags":["System Settings"],"description":"Partial update: keys absent from `values` stay untouched; null or empty string reverts a key to its environment/default fallback. Changes take effect immediately without a restart.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["values"],"properties":{"values":{"type":"object","additionalProperties":{"type":["string","null"]}}}}}}},"responses":{"200":{"description":"Updated settings catalog","content":{"application/json":{"schema":{"description":"Updated settings catalog","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","required":["settings"],"properties":{"settings":{"type":"array","items":{"type":"object","required":["key","group","kind","secret","source","isSet"],"properties":{"key":{"type":"string"},"group":{"type":"string"},"kind":{"type":"string","enum":["string","number","boolean"]},"secret":{"type":"boolean"},"source":{"type":"string","enum":["database","environment","default"]},"value":{},"isSet":{"type":"boolean"}}}}}}}}}}},"400":{"description":"Unknown setting key or invalid value","content":{"application/json":{"schema":{"description":"Unknown setting key or invalid value","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"description":"Not authenticated","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/audit-logs":{"get":{"summary":"Audit Log List","tags":["Audit Logs"],"parameters":[{"schema":{"type":"integer"},"in":"query","name":"page","required":false},{"schema":{"type":"integer"},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"q","required":false,"description":"Search keyword (username, entity id, path, IP)"},{"schema":{"type":"string","enum":["plan.create","plan.update","plan.updateStatus","plan.delete","formField.create","formField.update","formField.delete","order.markPaid","license.create","license.update","license.resend","license.download","license.delete","certificateTemplate.create","certificateTemplate.update","certificateTemplate.duplicate","certificateTemplate.setDefault","certificateTemplate.delete","queryPlan.create","queryPlan.update","queryPlan.delete","contract.create","contract.update","contract.updateStatus","contract.delete","contractParty.create","contractParty.update","contractParty.delete","user.create","user.update","user.delete","role.create","role.update","role.delete","settings.update","translation.batchFromPrimary","translation.toLocale","translation.field","translation.fieldToLocale","auth.login","auth.loginFailed","auth.logout","auth.changePassword"]},"in":"query","name":"action","required":false},{"schema":{"type":"string","enum":["plan","formField","order","license","certificateTemplate","queryPlan","contract","contractParty","user","role","settings","translation"]},"in":"query","name":"entityType","required":false},{"schema":{"type":"string","maxLength":64},"in":"query","name":"entityId","required":false},{"schema":{"type":"integer"},"in":"query","name":"userId","required":false},{"schema":{"type":"string"},"in":"query","name":"from","required":false,"description":"ISO date-time lower bound (inclusive)"},{"schema":{"type":"string"},"in":"query","name":"to","required":false,"description":"ISO date-time upper bound (inclusive)"}],"responses":{"200":{"description":"Audit log list","content":{"application/json":{"schema":{"description":"Audit log list","type":"object","required":["success","data","meta"],"properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"userId":{"type":["null","integer"]},"username":{"type":["null","string"]},"roleName":{"type":["null","string"]},"action":{"type":"string"},"entityType":{"type":"string"},"entityId":{"type":["null","string"]},"requestId":{"type":["null","string"]},"ip":{"type":["null","string"]},"userAgent":{"type":["null","string"]},"method":{"type":"string"},"path":{"type":"string"},"statusCode":{"type":"integer"},"hasSnapshot":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}}},"meta":{"type":"object","properties":{"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/audit-logs/{id}":{"get":{"summary":"Audit Log Detail","tags":["Audit Logs"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Audit log entry","content":{"application/json":{"schema":{"description":"Audit log entry","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"userId":{"type":["null","integer"]},"username":{"type":["null","string"]},"roleName":{"type":["null","string"]},"action":{"type":"string"},"entityType":{"type":"string"},"entityId":{"type":["null","string"]},"requestId":{"type":["null","string"]},"ip":{"type":["null","string"]},"userAgent":{"type":["null","string"]},"method":{"type":"string"},"path":{"type":"string"},"statusCode":{"type":"integer"},"hasSnapshot":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"beforeData":{},"afterData":{},"metadata":{}}}}}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"description":"Insufficient permissions","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"404":{"description":"Audit log entry not found","content":{"application/json":{"schema":{"description":"Audit log entry not found","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}},"/api/v1/admin/licenses/fingerprint":{"post":{"summary":"Generate License Short Code (admin)","tags":["Public Fingerprint"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["company","licenseType","startDate","endDate"],"properties":{"company":{"type":"string","description":"Company / entity"},"licenseType":{"type":"string","description":"License type"},"startDate":{"type":"string","description":"Start date"},"endDate":{"type":"string","description":"End date"},"length":{"type":"integer","minimum":8,"maximum":64,"description":"Code length (optional)"}}}}}},"responses":{"200":{"description":"Short verification code","content":{"application/json":{"schema":{"description":"Short verification code","type":"object","required":["success","data"],"properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"fingerprintShort":{"type":"string"}}}}}}}},"400":{"description":"Parameter validation failed","content":{"application/json":{"schema":{"description":"Parameter validation failed","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"description":"Not authenticated","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}},"403":{"description":"Missing permission","content":{"application/json":{"schema":{"description":"Missing permission","type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"requestId":{"type":"string"}}}}}}}}}},"servers":[{"url":"http://backend","description":"API Server"}],"tags":[{"name":"System","description":"Health check, etc."},{"name":"Public Plans","description":"Public plans and pricing"},{"name":"Public Orders","description":"Public order creation and queries"},{"name":"Public Payments","description":"Payment callbacks"},{"name":"Public Fingerprint","description":"License fingerprint generation"},{"name":"Auth","description":"Admin login/logout/auth status"},{"name":"Form Fields","description":"Form field CRUD"},{"name":"Plans","description":"Plan CRUD"},{"name":"Licenses","description":"License management"},{"name":"Orders","description":"Order management"},{"name":"Certificate Templates","description":"Certificate template CRUD"},{"name":"Translation","description":"AI translation for plan i18n"},{"name":"Query Plans","description":"License query plan CRUD"},{"name":"Public Query","description":"Public license query by plan slug"},{"name":"Public Plugins","description":"Official plugin marketplace catalog"},{"name":"Contract Templates","description":"Code-defined contract template catalog"},{"name":"Contracts","description":"Contract instance ledger (numbering, DOCX, status)"},{"name":"Contract Parties","description":"Contract signing party registry"},{"name":"Admin Users","description":"Admin user management (RBAC)"},{"name":"Admin Roles","description":"Admin role & permission management (RBAC)"},{"name":"System Settings","description":"Database-backed runtime configuration"},{"name":"Audit Logs","description":"Append-only audit trail of admin operations"}],"x-tagGroups":[{"name":"System","tags":["System"]},{"name":"Public","tags":["Public Plans","Public Orders","Public Payments","Public Fingerprint","Public Plugins"]},{"name":"Auth","tags":["Auth"]},{"name":"Admin","tags":["Form Fields","Plans","Licenses","Orders","Certificate Templates","Translation","Query Plans","Contract Templates","Contracts","Contract Parties","Admin Users","Admin Roles","System Settings","Audit Logs"]},{"name":"Public Query","tags":["Public Query"]}]}