Complete implementation of the Goa Government e-Licensing platform with: Backend: - NestJS API with JWT authentication - PostgreSQL database with Knex ORM - Redis caching and session management - MinIO document storage - Hyperledger Besu blockchain integration - Multi-department workflow system - Comprehensive API tests (266/282 passing) Frontend: - Angular 21 with standalone components - Angular Material + TailwindCSS UI - Visual workflow builder - Document upload with progress tracking - Blockchain explorer integration - Role-based dashboards (Admin, Department, Citizen) - E2E tests with Playwright (37 tests) Infrastructure: - Docker Compose orchestration - Blockscout blockchain explorer - Development and production configurations
2284 lines
58 KiB
YAML
2284 lines
58 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Goa GEL - Blockchain Document Verification Platform API
|
|
description: |
|
|
## Overview
|
|
REST API for the Government of Goa's Blockchain-based Document Verification Platform (GEL).
|
|
This platform enables multi-department approval workflows for various licenses and permits,
|
|
with blockchain-backed verification using Hyperledger Besu and ERC-721 Soulbound NFTs.
|
|
|
|
## Authentication
|
|
- **Department APIs**: Use `X-API-Key` and `X-Department-Code` headers
|
|
- **Applicant APIs**: Use Bearer token from DigiLocker authentication (mock for POC)
|
|
- **Admin APIs**: Use Bearer token with admin role
|
|
|
|
## Blockchain Integration
|
|
All critical operations (request creation, approvals, document updates) are recorded on-chain.
|
|
Response includes `transactionHash` for blockchain verification.
|
|
|
|
## Webhooks
|
|
Departments can register webhooks to receive real-time notifications for:
|
|
- `APPROVAL_REQUIRED` - New request pending approval
|
|
- `DOCUMENT_UPDATED` - Applicant updated a document
|
|
- `REQUEST_APPROVED` - Request fully approved
|
|
- `REQUEST_REJECTED` - Request rejected
|
|
|
|
version: 1.0.0
|
|
contact:
|
|
name: Goa GEL Platform Support
|
|
email: support@goagel.gov.in
|
|
license:
|
|
name: Government of Goa
|
|
url: https://www.goa.gov.in
|
|
|
|
servers:
|
|
- url: https://api.goagel.gov.in/api/v1
|
|
description: Production server
|
|
- url: https://staging-api.goagel.gov.in/api/v1
|
|
description: Staging server
|
|
- url: http://localhost:3001/api/v1
|
|
description: Local development
|
|
|
|
tags:
|
|
- name: Requests
|
|
description: License request operations
|
|
- name: Documents
|
|
description: Document upload and retrieval
|
|
- name: Approvals
|
|
description: Department approval actions
|
|
- name: Departments
|
|
description: Department management
|
|
- name: Workflows
|
|
description: Workflow configuration
|
|
- name: Webhooks
|
|
description: Webhook management
|
|
- name: Admin
|
|
description: Platform administration
|
|
- name: Verification
|
|
description: Public verification endpoints
|
|
|
|
paths:
|
|
# ==================== REQUESTS ====================
|
|
/requests:
|
|
post:
|
|
tags:
|
|
- Requests
|
|
summary: Create new license request
|
|
description: |
|
|
Creates a new license request and mints a draft NFT on the blockchain.
|
|
The request starts in DRAFT status until submitted.
|
|
operationId: createRequest
|
|
security:
|
|
- BearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateRequestInput'
|
|
example:
|
|
applicantId: "DL-GOA-123456789"
|
|
requestType: "RESORT_LICENSE"
|
|
metadata:
|
|
resortName: "Paradise Beach Resort"
|
|
location: "Calangute, North Goa"
|
|
plotArea: 5000
|
|
builtUpArea: 3500
|
|
numberOfRooms: 50
|
|
responses:
|
|
'201':
|
|
description: Request created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RequestResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
|
|
get:
|
|
tags:
|
|
- Requests
|
|
summary: List requests
|
|
description: Get list of requests with optional filters
|
|
operationId: listRequests
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
$ref: '#/components/schemas/RequestStatus'
|
|
- name: requestType
|
|
in: query
|
|
schema:
|
|
type: string
|
|
example: "RESORT_LICENSE"
|
|
- name: applicantId
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
minimum: 1
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
minimum: 1
|
|
maximum: 100
|
|
- name: sortBy
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [createdAt, updatedAt, status]
|
|
default: createdAt
|
|
- name: sortOrder
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [asc, desc]
|
|
default: desc
|
|
responses:
|
|
'200':
|
|
description: List of requests
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RequestListResponse'
|
|
|
|
/requests/pending:
|
|
get:
|
|
tags:
|
|
- Requests
|
|
summary: Get requests pending for department
|
|
description: Returns all requests that are pending approval from the specified department
|
|
operationId: getPendingRequests
|
|
security:
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: department
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
example: "FIRE_DEPT"
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
responses:
|
|
'200':
|
|
description: List of pending requests
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RequestListResponse'
|
|
|
|
/requests/{requestId}:
|
|
get:
|
|
tags:
|
|
- Requests
|
|
summary: Get request details
|
|
description: |
|
|
Returns complete request details including documents, approvals,
|
|
current workflow stage, and full timeline of events.
|
|
operationId: getRequest
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
responses:
|
|
'200':
|
|
description: Request details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RequestDetailResponse'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/requests/{requestId}/submit:
|
|
post:
|
|
tags:
|
|
- Requests
|
|
summary: Submit request for approval
|
|
description: |
|
|
Submits the request for departmental approval workflow.
|
|
Validates that all required documents are uploaded before submission.
|
|
Records submission on blockchain and notifies relevant departments.
|
|
operationId: submitRequest
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
responses:
|
|
'200':
|
|
description: Request submitted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
format: uuid
|
|
status:
|
|
type: string
|
|
example: "SUBMITTED"
|
|
currentStage:
|
|
$ref: '#/components/schemas/WorkflowStage'
|
|
pendingDepartments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: ["FIRE_DEPT", "TOURISM_DEPT"]
|
|
transactionHash:
|
|
type: string
|
|
example: "0x1234567890abcdef..."
|
|
'400':
|
|
description: Missing required documents
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
example:
|
|
code: "MISSING_DOCUMENTS"
|
|
message: "Required documents not uploaded"
|
|
details:
|
|
missingDocuments: ["FIRE_SAFETY_CERTIFICATE", "BUILDING_PLAN"]
|
|
|
|
/requests/{requestId}/cancel:
|
|
post:
|
|
tags:
|
|
- Requests
|
|
summary: Cancel request
|
|
description: Cancels a request that is in DRAFT or PENDING_RESUBMISSION status
|
|
operationId: cancelRequest
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
reason:
|
|
type: string
|
|
example: "No longer needed"
|
|
responses:
|
|
'200':
|
|
description: Request cancelled
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
status:
|
|
type: string
|
|
example: "CANCELLED"
|
|
transactionHash:
|
|
type: string
|
|
|
|
/requests/{requestId}/timeline:
|
|
get:
|
|
tags:
|
|
- Requests
|
|
summary: Get request timeline
|
|
description: Returns chronological list of all events for this request
|
|
operationId: getRequestTimeline
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
responses:
|
|
'200':
|
|
description: Request timeline
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
events:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/TimelineEvent'
|
|
|
|
# ==================== DOCUMENTS ====================
|
|
/requests/{requestId}/documents:
|
|
post:
|
|
tags:
|
|
- Documents
|
|
summary: Upload document
|
|
description: |
|
|
Uploads a document for the request. The document is:
|
|
1. Stored in MinIO with versioning
|
|
2. Hash generated using SHA-256
|
|
3. Hash recorded on blockchain
|
|
4. Linked to the request NFT
|
|
operationId: uploadDocument
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- file
|
|
- docType
|
|
properties:
|
|
file:
|
|
type: string
|
|
format: binary
|
|
description: Document file (PDF, JPG, PNG)
|
|
docType:
|
|
type: string
|
|
description: Document type code
|
|
example: "FIRE_SAFETY_CERTIFICATE"
|
|
description:
|
|
type: string
|
|
description: Optional description
|
|
example: "Fire safety certificate from Fire Department"
|
|
responses:
|
|
'201':
|
|
description: Document uploaded successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DocumentResponse'
|
|
'400':
|
|
description: Invalid file or document type
|
|
'413':
|
|
description: File too large (max 10MB)
|
|
|
|
get:
|
|
tags:
|
|
- Documents
|
|
summary: List request documents
|
|
description: Returns all documents associated with the request
|
|
operationId: listRequestDocuments
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
responses:
|
|
'200':
|
|
description: List of documents
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
documents:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Document'
|
|
|
|
/documents/{documentId}:
|
|
get:
|
|
tags:
|
|
- Documents
|
|
summary: Get document details
|
|
description: Returns document metadata and all versions
|
|
operationId: getDocument
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: documentId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Document details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DocumentDetailResponse'
|
|
|
|
/documents/{documentId}/download:
|
|
get:
|
|
tags:
|
|
- Documents
|
|
summary: Download document
|
|
description: Returns a signed URL for downloading the document
|
|
operationId: downloadDocument
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: documentId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
- name: version
|
|
in: query
|
|
description: Specific version to download (defaults to latest)
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Download URL
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
downloadUrl:
|
|
type: string
|
|
format: uri
|
|
description: Signed URL (expires in 1 hour)
|
|
expiresAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
/requests/{requestId}/documents/{documentId}:
|
|
put:
|
|
tags:
|
|
- Documents
|
|
summary: Update document (new version)
|
|
description: |
|
|
Uploads a new version of an existing document.
|
|
This will:
|
|
1. Create new version in MinIO
|
|
2. Generate new hash
|
|
3. Record new hash on blockchain
|
|
4. Mark affected approvals as "REVIEW_REQUIRED"
|
|
5. Notify affected departments via webhook
|
|
operationId: updateDocument
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
- name: documentId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- file
|
|
properties:
|
|
file:
|
|
type: string
|
|
format: binary
|
|
description:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Document updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
documentId:
|
|
type: string
|
|
newVersion:
|
|
type: integer
|
|
newHash:
|
|
type: string
|
|
invalidatedApprovals:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Department codes that need re-review
|
|
transactionHash:
|
|
type: string
|
|
|
|
# ==================== APPROVALS ====================
|
|
/requests/{requestId}/approve:
|
|
post:
|
|
tags:
|
|
- Approvals
|
|
summary: Approve request
|
|
description: |
|
|
Records department approval on the blockchain.
|
|
If all required approvals for the current stage are complete,
|
|
automatically advances to the next stage or finalizes the request.
|
|
operationId: approveRequest
|
|
security:
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- remarks
|
|
- reviewedDocuments
|
|
properties:
|
|
remarks:
|
|
type: string
|
|
example: "All fire safety requirements met"
|
|
reviewedDocuments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
description: Document IDs that were reviewed
|
|
responses:
|
|
'200':
|
|
description: Approval recorded
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApprovalResponse'
|
|
|
|
/requests/{requestId}/reject:
|
|
post:
|
|
tags:
|
|
- Approvals
|
|
summary: Reject request
|
|
description: Records department rejection. This permanently rejects the request.
|
|
operationId: rejectRequest
|
|
security:
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- remarks
|
|
- reason
|
|
properties:
|
|
remarks:
|
|
type: string
|
|
example: "Fire safety standards not met"
|
|
reason:
|
|
type: string
|
|
enum:
|
|
- SAFETY_VIOLATION
|
|
- INCOMPLETE_DOCUMENTS
|
|
- POLICY_VIOLATION
|
|
- FRAUDULENT_APPLICATION
|
|
- OTHER
|
|
responses:
|
|
'200':
|
|
description: Rejection recorded
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApprovalResponse'
|
|
|
|
/requests/{requestId}/request-changes:
|
|
post:
|
|
tags:
|
|
- Approvals
|
|
summary: Request changes
|
|
description: |
|
|
Requests additional information or document updates from the applicant.
|
|
The request status changes to PENDING_RESUBMISSION.
|
|
operationId: requestChanges
|
|
security:
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- remarks
|
|
properties:
|
|
remarks:
|
|
type: string
|
|
example: "Please provide updated fire safety certificate with recent inspection"
|
|
requiredDocuments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Additional document types needed
|
|
example: ["FIRE_SAFETY_CERTIFICATE", "INSPECTION_REPORT"]
|
|
responses:
|
|
'200':
|
|
description: Changes requested
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: "CHANGES_REQUESTED"
|
|
transactionHash:
|
|
type: string
|
|
|
|
/requests/{requestId}/approvals:
|
|
get:
|
|
tags:
|
|
- Approvals
|
|
summary: Get all approvals for request
|
|
description: Returns all approval records including historical/invalidated ones
|
|
operationId: getRequestApprovals
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/RequestId'
|
|
- name: includeInvalidated
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
default: false
|
|
responses:
|
|
'200':
|
|
description: List of approvals
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
approvals:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Approval'
|
|
|
|
# ==================== DEPARTMENTS ====================
|
|
/departments:
|
|
get:
|
|
tags:
|
|
- Departments
|
|
summary: List all departments
|
|
description: Returns all registered departments
|
|
operationId: listDepartments
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: List of departments
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
departments:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Department'
|
|
|
|
post:
|
|
tags:
|
|
- Departments
|
|
summary: Register new department
|
|
description: Registers a new department and creates blockchain wallet
|
|
operationId: createDepartment
|
|
security:
|
|
- AdminAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateDepartmentInput'
|
|
responses:
|
|
'201':
|
|
description: Department created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DepartmentResponse'
|
|
|
|
/departments/{departmentCode}:
|
|
get:
|
|
tags:
|
|
- Departments
|
|
summary: Get department details
|
|
operationId: getDepartment
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: departmentCode
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
example: "FIRE_DEPT"
|
|
responses:
|
|
'200':
|
|
description: Department details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Department'
|
|
|
|
patch:
|
|
tags:
|
|
- Departments
|
|
summary: Update department
|
|
operationId: updateDepartment
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: departmentCode
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
webhookUrl:
|
|
type: string
|
|
format: uri
|
|
isActive:
|
|
type: boolean
|
|
responses:
|
|
'200':
|
|
description: Department updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Department'
|
|
|
|
/departments/{departmentCode}/regenerate-api-key:
|
|
post:
|
|
tags:
|
|
- Departments
|
|
summary: Regenerate API key
|
|
description: Generates a new API key for the department (invalidates the old key)
|
|
operationId: regenerateApiKey
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: departmentCode
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: New API key generated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
description: New API key (shown only once)
|
|
apiSecret:
|
|
type: string
|
|
description: New API secret (shown only once)
|
|
|
|
/departments/{departmentCode}/stats:
|
|
get:
|
|
tags:
|
|
- Departments
|
|
summary: Get department statistics
|
|
operationId: getDepartmentStats
|
|
security:
|
|
- ApiKeyAuth: []
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: departmentCode
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: startDate
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date
|
|
- name: endDate
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date
|
|
responses:
|
|
'200':
|
|
description: Department statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
departmentCode:
|
|
type: string
|
|
period:
|
|
type: object
|
|
properties:
|
|
start:
|
|
type: string
|
|
format: date
|
|
end:
|
|
type: string
|
|
format: date
|
|
stats:
|
|
type: object
|
|
properties:
|
|
totalReceived:
|
|
type: integer
|
|
approved:
|
|
type: integer
|
|
rejected:
|
|
type: integer
|
|
pending:
|
|
type: integer
|
|
avgProcessingTimeDays:
|
|
type: number
|
|
|
|
# ==================== WORKFLOWS ====================
|
|
/workflows:
|
|
get:
|
|
tags:
|
|
- Workflows
|
|
summary: List workflow definitions
|
|
operationId: listWorkflows
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: isActive
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
responses:
|
|
'200':
|
|
description: List of workflows
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
workflows:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Workflow'
|
|
|
|
post:
|
|
tags:
|
|
- Workflows
|
|
summary: Create workflow definition
|
|
operationId: createWorkflow
|
|
security:
|
|
- AdminAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateWorkflowInput'
|
|
responses:
|
|
'201':
|
|
description: Workflow created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Workflow'
|
|
|
|
/workflows/{workflowId}:
|
|
get:
|
|
tags:
|
|
- Workflows
|
|
summary: Get workflow details
|
|
operationId: getWorkflow
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: workflowId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Workflow details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Workflow'
|
|
|
|
put:
|
|
tags:
|
|
- Workflows
|
|
summary: Update workflow
|
|
description: |
|
|
Updates a workflow definition. Creates a new version.
|
|
In-progress requests continue with their original workflow version.
|
|
operationId: updateWorkflow
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: workflowId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateWorkflowInput'
|
|
responses:
|
|
'200':
|
|
description: Workflow updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Workflow'
|
|
|
|
delete:
|
|
tags:
|
|
- Workflows
|
|
summary: Deactivate workflow
|
|
description: Deactivates the workflow. Cannot be used for new requests.
|
|
operationId: deactivateWorkflow
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: workflowId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Workflow deactivated
|
|
|
|
/workflows/{workflowId}/validate:
|
|
post:
|
|
tags:
|
|
- Workflows
|
|
summary: Validate workflow definition
|
|
description: Validates workflow for circular dependencies, missing departments, etc.
|
|
operationId: validateWorkflow
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: workflowId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Validation result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
isValid:
|
|
type: boolean
|
|
errors:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
message:
|
|
type: string
|
|
path:
|
|
type: string
|
|
|
|
# ==================== WEBHOOKS ====================
|
|
/webhooks:
|
|
get:
|
|
tags:
|
|
- Webhooks
|
|
summary: List registered webhooks
|
|
operationId: listWebhooks
|
|
security:
|
|
- ApiKeyAuth: []
|
|
- AdminAuth: []
|
|
responses:
|
|
'200':
|
|
description: List of webhooks
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
webhooks:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Webhook'
|
|
|
|
post:
|
|
tags:
|
|
- Webhooks
|
|
summary: Register webhook
|
|
operationId: createWebhook
|
|
security:
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateWebhookInput'
|
|
responses:
|
|
'201':
|
|
description: Webhook registered
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Webhook'
|
|
|
|
/webhooks/{webhookId}:
|
|
delete:
|
|
tags:
|
|
- Webhooks
|
|
summary: Delete webhook
|
|
operationId: deleteWebhook
|
|
security:
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: webhookId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'204':
|
|
description: Webhook deleted
|
|
|
|
/webhooks/{webhookId}/test:
|
|
post:
|
|
tags:
|
|
- Webhooks
|
|
summary: Test webhook
|
|
description: Sends a test payload to the webhook URL
|
|
operationId: testWebhook
|
|
security:
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: webhookId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Test result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
statusCode:
|
|
type: integer
|
|
responseTime:
|
|
type: integer
|
|
description: Response time in ms
|
|
|
|
/webhooks/logs:
|
|
get:
|
|
tags:
|
|
- Webhooks
|
|
summary: Get webhook delivery logs
|
|
operationId: getWebhookLogs
|
|
security:
|
|
- ApiKeyAuth: []
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: webhookId
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [success, failed, pending]
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
responses:
|
|
'200':
|
|
description: Webhook logs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
logs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WebhookLog'
|
|
|
|
# ==================== ADMIN ====================
|
|
/admin/stats:
|
|
get:
|
|
tags:
|
|
- Admin
|
|
summary: Get platform statistics
|
|
operationId: getPlatformStats
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: startDate
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date
|
|
- name: endDate
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date
|
|
responses:
|
|
'200':
|
|
description: Platform statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
period:
|
|
type: object
|
|
properties:
|
|
start:
|
|
type: string
|
|
format: date
|
|
end:
|
|
type: string
|
|
format: date
|
|
requests:
|
|
type: object
|
|
properties:
|
|
total:
|
|
type: integer
|
|
byStatus:
|
|
type: object
|
|
additionalProperties:
|
|
type: integer
|
|
byType:
|
|
type: object
|
|
additionalProperties:
|
|
type: integer
|
|
blockchain:
|
|
type: object
|
|
properties:
|
|
totalTransactions:
|
|
type: integer
|
|
nftsMinted:
|
|
type: integer
|
|
avgGasUsed:
|
|
type: number
|
|
performance:
|
|
type: object
|
|
properties:
|
|
avgProcessingTimeDays:
|
|
type: number
|
|
requestsPerDay:
|
|
type: number
|
|
|
|
/admin/audit-logs:
|
|
get:
|
|
tags:
|
|
- Admin
|
|
summary: Get audit logs
|
|
operationId: getAuditLogs
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: entityType
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [REQUEST, APPROVAL, DOCUMENT, DEPARTMENT, WORKFLOW]
|
|
- name: entityId
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
- name: action
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: actorId
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
- name: startDate
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date-time
|
|
- name: endDate
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date-time
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
responses:
|
|
'200':
|
|
description: Audit logs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
logs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AuditLog'
|
|
pagination:
|
|
$ref: '#/components/schemas/Pagination'
|
|
|
|
/admin/blockchain/status:
|
|
get:
|
|
tags:
|
|
- Admin
|
|
summary: Get blockchain network status
|
|
operationId: getBlockchainStatus
|
|
security:
|
|
- AdminAuth: []
|
|
responses:
|
|
'200':
|
|
description: Blockchain status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
network:
|
|
type: object
|
|
properties:
|
|
chainId:
|
|
type: integer
|
|
networkId:
|
|
type: integer
|
|
consensus:
|
|
type: string
|
|
example: "QBFT"
|
|
nodes:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
nodeId:
|
|
type: string
|
|
isValidator:
|
|
type: boolean
|
|
isHealthy:
|
|
type: boolean
|
|
peers:
|
|
type: integer
|
|
latestBlock:
|
|
type: integer
|
|
latestBlock:
|
|
type: object
|
|
properties:
|
|
number:
|
|
type: integer
|
|
hash:
|
|
type: string
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
|
|
/admin/blockchain/transactions:
|
|
get:
|
|
tags:
|
|
- Admin
|
|
summary: Get blockchain transactions
|
|
operationId: getBlockchainTransactions
|
|
security:
|
|
- AdminAuth: []
|
|
parameters:
|
|
- name: txType
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [MINT_NFT, APPROVAL, DOC_UPDATE, REJECT, REVOKE]
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [PENDING, CONFIRMED, FAILED]
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
responses:
|
|
'200':
|
|
description: Blockchain transactions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
transactions:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/BlockchainTransaction'
|
|
pagination:
|
|
$ref: '#/components/schemas/Pagination'
|
|
|
|
# ==================== VERIFICATION ====================
|
|
/verify/{tokenId}:
|
|
get:
|
|
tags:
|
|
- Verification
|
|
summary: Verify license by token ID
|
|
description: |
|
|
Public endpoint for verifying a license using its NFT token ID.
|
|
No authentication required.
|
|
operationId: verifyByTokenId
|
|
parameters:
|
|
- name: tokenId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
example: 12345
|
|
responses:
|
|
'200':
|
|
description: Verification result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/VerificationResponse'
|
|
'404':
|
|
description: Token not found
|
|
|
|
/verify/qr/{qrCode}:
|
|
get:
|
|
tags:
|
|
- Verification
|
|
summary: Verify license by QR code
|
|
description: Public endpoint for verifying a license using QR code data
|
|
operationId: verifyByQrCode
|
|
parameters:
|
|
- name: qrCode
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Verification result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/VerificationResponse'
|
|
|
|
/verify/document/{hash}:
|
|
get:
|
|
tags:
|
|
- Verification
|
|
summary: Verify document by hash
|
|
description: Public endpoint for verifying a document using its hash
|
|
operationId: verifyDocumentByHash
|
|
parameters:
|
|
- name: hash
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
example: "0x1234567890abcdef..."
|
|
responses:
|
|
'200':
|
|
description: Document verification result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
isValid:
|
|
type: boolean
|
|
documentId:
|
|
type: string
|
|
requestId:
|
|
type: string
|
|
docType:
|
|
type: string
|
|
version:
|
|
type: integer
|
|
uploadedAt:
|
|
type: string
|
|
format: date-time
|
|
blockchainRecord:
|
|
type: object
|
|
properties:
|
|
transactionHash:
|
|
type: string
|
|
blockNumber:
|
|
type: integer
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
|
|
# ==================== COMPONENTS ====================
|
|
components:
|
|
securitySchemes:
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
description: JWT token from DigiLocker authentication
|
|
|
|
ApiKeyAuth:
|
|
type: apiKey
|
|
in: header
|
|
name: X-API-Key
|
|
description: |
|
|
Department API key. Must be used with X-Department-Code header.
|
|
|
|
AdminAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
description: Admin JWT token
|
|
|
|
parameters:
|
|
RequestId:
|
|
name: requestId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
description: Unique request identifier
|
|
|
|
responses:
|
|
BadRequest:
|
|
description: Bad request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
Unauthorized:
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
example:
|
|
code: "UNAUTHORIZED"
|
|
message: "Invalid or missing authentication"
|
|
|
|
NotFound:
|
|
description: Resource not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
example:
|
|
code: "NOT_FOUND"
|
|
message: "Request not found"
|
|
|
|
schemas:
|
|
# ===== Input Schemas =====
|
|
CreateRequestInput:
|
|
type: object
|
|
required:
|
|
- applicantId
|
|
- requestType
|
|
properties:
|
|
applicantId:
|
|
type: string
|
|
description: DigiLocker ID
|
|
example: "DL-GOA-123456789"
|
|
requestType:
|
|
type: string
|
|
description: Type of license/permit
|
|
enum:
|
|
- RESORT_LICENSE
|
|
- TRADE_LICENSE
|
|
- BUILDING_PERMIT
|
|
example: "RESORT_LICENSE"
|
|
metadata:
|
|
type: object
|
|
description: Request-specific data
|
|
additionalProperties: true
|
|
|
|
CreateDepartmentInput:
|
|
type: object
|
|
required:
|
|
- code
|
|
- name
|
|
properties:
|
|
code:
|
|
type: string
|
|
pattern: "^[A-Z_]+$"
|
|
example: "FIRE_DEPT"
|
|
name:
|
|
type: string
|
|
example: "Fire & Emergency Services Department"
|
|
webhookUrl:
|
|
type: string
|
|
format: uri
|
|
|
|
CreateWorkflowInput:
|
|
type: object
|
|
required:
|
|
- workflowType
|
|
- name
|
|
- stages
|
|
properties:
|
|
workflowType:
|
|
type: string
|
|
example: "RESORT_LICENSE"
|
|
name:
|
|
type: string
|
|
example: "Resort License Approval Workflow"
|
|
description:
|
|
type: string
|
|
stages:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WorkflowStageInput'
|
|
|
|
WorkflowStageInput:
|
|
type: object
|
|
required:
|
|
- stageId
|
|
- stageName
|
|
- stageOrder
|
|
- executionType
|
|
- requiredApprovals
|
|
properties:
|
|
stageId:
|
|
type: string
|
|
stageName:
|
|
type: string
|
|
stageOrder:
|
|
type: integer
|
|
executionType:
|
|
type: string
|
|
enum: [SEQUENTIAL, PARALLEL]
|
|
requiredApprovals:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
departmentCode:
|
|
type: string
|
|
requiredDocuments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
isMandatory:
|
|
type: boolean
|
|
completionCriteria:
|
|
type: string
|
|
enum: [ALL, ANY, THRESHOLD]
|
|
default: ALL
|
|
threshold:
|
|
type: integer
|
|
timeoutDays:
|
|
type: integer
|
|
onTimeout:
|
|
type: string
|
|
enum: [NOTIFY, ESCALATE, AUTO_REJECT]
|
|
onRejection:
|
|
type: string
|
|
enum: [FAIL_REQUEST, RETRY_STAGE, ESCALATE]
|
|
|
|
CreateWebhookInput:
|
|
type: object
|
|
required:
|
|
- url
|
|
- events
|
|
- secret
|
|
properties:
|
|
departmentCode:
|
|
type: string
|
|
url:
|
|
type: string
|
|
format: uri
|
|
events:
|
|
type: array
|
|
items:
|
|
type: string
|
|
enum:
|
|
- APPROVAL_REQUIRED
|
|
- DOCUMENT_UPDATED
|
|
- REQUEST_APPROVED
|
|
- REQUEST_REJECTED
|
|
- CHANGES_REQUESTED
|
|
secret:
|
|
type: string
|
|
description: Secret for HMAC signature verification
|
|
|
|
# ===== Response Schemas =====
|
|
RequestResponse:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
format: uuid
|
|
requestNumber:
|
|
type: string
|
|
example: "RL-2024-001234"
|
|
status:
|
|
$ref: '#/components/schemas/RequestStatus'
|
|
transactionHash:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
RequestListResponse:
|
|
type: object
|
|
properties:
|
|
requests:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RequestSummary'
|
|
pagination:
|
|
$ref: '#/components/schemas/Pagination'
|
|
|
|
RequestSummary:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
format: uuid
|
|
requestNumber:
|
|
type: string
|
|
requestType:
|
|
type: string
|
|
status:
|
|
$ref: '#/components/schemas/RequestStatus'
|
|
applicantName:
|
|
type: string
|
|
currentStage:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
RequestDetailResponse:
|
|
type: object
|
|
properties:
|
|
requestId:
|
|
type: string
|
|
format: uuid
|
|
requestNumber:
|
|
type: string
|
|
tokenId:
|
|
type: integer
|
|
requestType:
|
|
type: string
|
|
status:
|
|
$ref: '#/components/schemas/RequestStatus'
|
|
applicant:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
email:
|
|
type: string
|
|
metadata:
|
|
type: object
|
|
documents:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Document'
|
|
approvals:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Approval'
|
|
currentStage:
|
|
$ref: '#/components/schemas/WorkflowStage'
|
|
timeline:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/TimelineEvent'
|
|
blockchainData:
|
|
type: object
|
|
properties:
|
|
tokenId:
|
|
type: integer
|
|
contractAddress:
|
|
type: string
|
|
creationTxHash:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
submittedAt:
|
|
type: string
|
|
format: date-time
|
|
approvedAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
DocumentResponse:
|
|
type: object
|
|
properties:
|
|
documentId:
|
|
type: string
|
|
format: uuid
|
|
docType:
|
|
type: string
|
|
hash:
|
|
type: string
|
|
version:
|
|
type: integer
|
|
transactionHash:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
DocumentDetailResponse:
|
|
type: object
|
|
properties:
|
|
documentId:
|
|
type: string
|
|
format: uuid
|
|
docType:
|
|
type: string
|
|
originalFilename:
|
|
type: string
|
|
currentVersion:
|
|
type: integer
|
|
currentHash:
|
|
type: string
|
|
versions:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/DocumentVersion'
|
|
downloadUrl:
|
|
type: string
|
|
format: uri
|
|
|
|
ApprovalResponse:
|
|
type: object
|
|
properties:
|
|
approvalId:
|
|
type: string
|
|
format: uuid
|
|
status:
|
|
$ref: '#/components/schemas/ApprovalStatus'
|
|
transactionHash:
|
|
type: string
|
|
workflowStatus:
|
|
type: object
|
|
properties:
|
|
currentStage:
|
|
type: string
|
|
isComplete:
|
|
type: boolean
|
|
nextPendingDepartments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
|
|
DepartmentResponse:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
name:
|
|
type: string
|
|
walletAddress:
|
|
type: string
|
|
apiKey:
|
|
type: string
|
|
description: Shown only on creation
|
|
apiSecret:
|
|
type: string
|
|
description: Shown only on creation
|
|
isActive:
|
|
type: boolean
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
VerificationResponse:
|
|
type: object
|
|
properties:
|
|
isValid:
|
|
type: boolean
|
|
tokenId:
|
|
type: integer
|
|
requestNumber:
|
|
type: string
|
|
requestType:
|
|
type: string
|
|
status:
|
|
$ref: '#/components/schemas/RequestStatus'
|
|
applicantName:
|
|
type: string
|
|
issuedAt:
|
|
type: string
|
|
format: date-time
|
|
expiresAt:
|
|
type: string
|
|
format: date-time
|
|
approvals:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
departmentName:
|
|
type: string
|
|
approvedAt:
|
|
type: string
|
|
format: date-time
|
|
blockchainProof:
|
|
type: object
|
|
properties:
|
|
contractAddress:
|
|
type: string
|
|
tokenId:
|
|
type: integer
|
|
ownerAddress:
|
|
type: string
|
|
transactionHash:
|
|
type: string
|
|
|
|
# ===== Entity Schemas =====
|
|
Document:
|
|
type: object
|
|
properties:
|
|
documentId:
|
|
type: string
|
|
format: uuid
|
|
docType:
|
|
type: string
|
|
originalFilename:
|
|
type: string
|
|
currentVersion:
|
|
type: integer
|
|
currentHash:
|
|
type: string
|
|
uploadedAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
DocumentVersion:
|
|
type: object
|
|
properties:
|
|
version:
|
|
type: integer
|
|
hash:
|
|
type: string
|
|
fileSize:
|
|
type: integer
|
|
mimeType:
|
|
type: string
|
|
uploadedBy:
|
|
type: string
|
|
transactionHash:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
Approval:
|
|
type: object
|
|
properties:
|
|
approvalId:
|
|
type: string
|
|
format: uuid
|
|
departmentCode:
|
|
type: string
|
|
departmentName:
|
|
type: string
|
|
status:
|
|
$ref: '#/components/schemas/ApprovalStatus'
|
|
remarks:
|
|
type: string
|
|
reviewedDocuments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
isActive:
|
|
type: boolean
|
|
transactionHash:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
invalidatedAt:
|
|
type: string
|
|
format: date-time
|
|
invalidationReason:
|
|
type: string
|
|
|
|
Department:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
name:
|
|
type: string
|
|
walletAddress:
|
|
type: string
|
|
webhookUrl:
|
|
type: string
|
|
isActive:
|
|
type: boolean
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
Workflow:
|
|
type: object
|
|
properties:
|
|
workflowId:
|
|
type: string
|
|
format: uuid
|
|
workflowType:
|
|
type: string
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
version:
|
|
type: integer
|
|
isActive:
|
|
type: boolean
|
|
stages:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WorkflowStage'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
WorkflowStage:
|
|
type: object
|
|
properties:
|
|
stageId:
|
|
type: string
|
|
stageName:
|
|
type: string
|
|
stageOrder:
|
|
type: integer
|
|
executionType:
|
|
type: string
|
|
enum: [SEQUENTIAL, PARALLEL]
|
|
requiredApprovals:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
departmentCode:
|
|
type: string
|
|
departmentName:
|
|
type: string
|
|
requiredDocuments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
isMandatory:
|
|
type: boolean
|
|
completionCriteria:
|
|
type: string
|
|
enum: [ALL, ANY, THRESHOLD]
|
|
threshold:
|
|
type: integer
|
|
timeoutDays:
|
|
type: integer
|
|
onTimeout:
|
|
type: string
|
|
onRejection:
|
|
type: string
|
|
|
|
Webhook:
|
|
type: object
|
|
properties:
|
|
webhookId:
|
|
type: string
|
|
format: uuid
|
|
departmentCode:
|
|
type: string
|
|
url:
|
|
type: string
|
|
format: uri
|
|
events:
|
|
type: array
|
|
items:
|
|
type: string
|
|
isActive:
|
|
type: boolean
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
WebhookLog:
|
|
type: object
|
|
properties:
|
|
logId:
|
|
type: string
|
|
format: uuid
|
|
webhookId:
|
|
type: string
|
|
format: uuid
|
|
eventType:
|
|
type: string
|
|
payload:
|
|
type: object
|
|
responseStatus:
|
|
type: integer
|
|
responseTime:
|
|
type: integer
|
|
retryCount:
|
|
type: integer
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
TimelineEvent:
|
|
type: object
|
|
properties:
|
|
eventId:
|
|
type: string
|
|
format: uuid
|
|
eventType:
|
|
type: string
|
|
enum:
|
|
- REQUEST_CREATED
|
|
- REQUEST_SUBMITTED
|
|
- DOCUMENT_UPLOADED
|
|
- DOCUMENT_UPDATED
|
|
- APPROVAL_RECEIVED
|
|
- REJECTION_RECEIVED
|
|
- CHANGES_REQUESTED
|
|
- REQUEST_APPROVED
|
|
- REQUEST_REJECTED
|
|
- NFT_MINTED
|
|
description:
|
|
type: string
|
|
actor:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [APPLICANT, DEPARTMENT, SYSTEM]
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
metadata:
|
|
type: object
|
|
transactionHash:
|
|
type: string
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
|
|
AuditLog:
|
|
type: object
|
|
properties:
|
|
logId:
|
|
type: string
|
|
format: uuid
|
|
entityType:
|
|
type: string
|
|
entityId:
|
|
type: string
|
|
format: uuid
|
|
action:
|
|
type: string
|
|
actorType:
|
|
type: string
|
|
actorId:
|
|
type: string
|
|
format: uuid
|
|
oldValue:
|
|
type: object
|
|
newValue:
|
|
type: object
|
|
ipAddress:
|
|
type: string
|
|
userAgent:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
BlockchainTransaction:
|
|
type: object
|
|
properties:
|
|
txId:
|
|
type: string
|
|
format: uuid
|
|
txHash:
|
|
type: string
|
|
txType:
|
|
type: string
|
|
enum: [MINT_NFT, APPROVAL, DOC_UPDATE, REJECT, REVOKE]
|
|
relatedEntityType:
|
|
type: string
|
|
relatedEntityId:
|
|
type: string
|
|
format: uuid
|
|
fromAddress:
|
|
type: string
|
|
toAddress:
|
|
type: string
|
|
status:
|
|
type: string
|
|
enum: [PENDING, CONFIRMED, FAILED]
|
|
blockNumber:
|
|
type: integer
|
|
gasUsed:
|
|
type: integer
|
|
errorMessage:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
confirmedAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
# ===== Enums =====
|
|
RequestStatus:
|
|
type: string
|
|
enum:
|
|
- DRAFT
|
|
- SUBMITTED
|
|
- IN_REVIEW
|
|
- PENDING_RESUBMISSION
|
|
- APPROVED
|
|
- REJECTED
|
|
- REVOKED
|
|
- CANCELLED
|
|
|
|
ApprovalStatus:
|
|
type: string
|
|
enum:
|
|
- PENDING
|
|
- APPROVED
|
|
- REJECTED
|
|
- CHANGES_REQUESTED
|
|
- REVIEW_REQUIRED
|
|
|
|
# ===== Common Schemas =====
|
|
Pagination:
|
|
type: object
|
|
properties:
|
|
page:
|
|
type: integer
|
|
limit:
|
|
type: integer
|
|
total:
|
|
type: integer
|
|
totalPages:
|
|
type: integer
|
|
hasNext:
|
|
type: boolean
|
|
hasPrev:
|
|
type: boolean
|
|
|
|
Error:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
message:
|
|
type: string
|
|
details:
|
|
type: object
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
path:
|
|
type: string
|