Files
Goa-gel-fullstack/api/openapi.yaml

2284 lines
58 KiB
YAML
Raw Normal View History

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