This guide provides comprehensive instructions for developers and contributors to understand, test, and integrate with the Nyay Setu APIs. The platform consists of multiple microservices exposing 100+ API endpoints across different domains.
- Getting Started
- API Architecture
- Authentication
- Testing with Postman
- Testing with cURL
- Testing with Code
- API Endpoint Categories
- Common Workflows
- Troubleshooting
- Best Practices
- Node.js (v20+) for signaling server
- Java 17 for backend
- Python 3.12+ for microservices
- Docker & Docker Compose (optional but recommended)
- Postman (optional) for API testing
- cURL or similar HTTP client
# Start all services
docker-compose up -d
# Verify services are running
docker-compose ps
# View logs
docker-compose logs -fcd backend/nyaysetu-backend
mvn clean install
mvn spring-boot:run
# Runs on http://localhost:8080Note: Depending on your branch,
lawgpt-servicemay be integrated intonlp-orchestrator/. Checkdocker-compose.ymlto confirm which services run separately before starting.
cd lawgpt-service
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
python main.py
# Runs on http://localhost:8000cd nlp-orchestrator
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python main.py
# Runs on http://localhost:8001cd signaling-server
npm install
npm start
# Runs on http://localhost:3001┌─────────────────────────────────────────────────────────────┐
│ Frontend (React/Vite) │
│ http://localhost:3000 │
└────────────┬────────────┬─────────────────┬──────────────────┘
│ │ │
┌────────▼────┐ ┌────▼─────┐ ┌──────▼────────┐
│ Backend │ │ LawGPT │ │ NLP Orchestrator│
│ (Port 8080)│ │(Port 8000)│ │ (Port 8001) │
└────────┬────┘ └────┬─────┘ └──────┬────────┘
│ │ │
└────────────┼─────────────────┘
│
┌────────────────▼─────────────────┐
│ External Services │
│ - Groq AI │
│ - Google Gemini │
│ - Ollama (Local LLM) │
│ - Kanoon.org (Legal Research) │
└────────────────────────────────┘
┌──────────────────────────────────┐
│ Signaling Server (Port 3001) │
│ WebSocket for Video Calls │
└──────────────────────────────────┘
| Service | Purpose | Key Features |
|---|---|---|
| Backend | Core business logic | Auth, Cases, Documents, Evidence, Hearings, Orders |
| LawGPT | Document generation | Affidavits, RTI, Complaints, Notices, Petitions |
| NLP Orchestrator | Legal reasoning | 5-layer analysis, Forensics, Modi OCR, Streaming |
| Signaling Server | Real-time communication | WebRTC, Video calls, Peer-to-peer |
All API requests require authentication using JWT tokens.
curl -X POST http://localhost:8080/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123",
"role": "LAWYER",
"firstName": "John",
"lastName": "Doe",
"phone": "+919876543210"
}'curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123"
}'Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 86400,
"user": {
"id": "uuid-here",
"email": "user@example.com",
"role": "LAWYER"
}
}curl -X GET http://localhost:8080/api/v1/cases \
-H "Authorization: Bearer YOUR_TOKEN_HERE"When a token expires (24 hours), use the refresh token:
curl -X POST http://localhost:8080/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "YOUR_REFRESH_TOKEN"
}'| Role | Permissions | Endpoints |
|---|---|---|
| USER | View own cases | Case listing, document viewing |
| LAWYER | Create/manage cases | All case operations, draft generation |
| JUDGE | Case assignment, orders | Case cognizance, summons, orders |
| POLICE | FIR management | FIR operations, investigation |
| ADMIN | Full system access | All endpoints |
-
Import Collection
- Open Postman
- Click "Import" → Select
Nyay_Setu_API_Collection.postman_collection.json - Collection is automatically imported with all endpoints
-
Create Environment
- Click "Environments" → "Create New"
- Add variables:
baseUrl: http://localhost:8080 authToken: (auto-filled after login) refreshToken: (auto-filled after login) caseId: (auto-filled after case creation) documentId: (auto-filled after document upload)
-
Run Login Request First
- Go to "Authentication" → "Login"
- Click "Send"
- Token automatically sets in environment
-
Use Auto-populated Variables
- All subsequent requests use stored
authToken - IDs are auto-populated from previous responses
- All subsequent requests use stored
Step 1: Login
1. Open "Authentication" folder
2. Click "Login" request
3. Click "Send"
4. Check response - token is auto-saved
Step 2: Create a Case
1. Open "Cases" folder
2. Click "Create Case"
3. Update body with your details
4. Click "Send"
5. Case ID is auto-saved to environment
Step 3: Upload Document
1. Open "Documents" folder
2. Click "Upload Document"
3. Select file to upload
4. Click "Send"
5. Document ID is auto-saved
Step 4: Analyze Document
1. Click "Analyze Document"
2. Click "Send"
3. View AI analysis results
# Install Newman
npm install -g newman
# Run collection with environment
newman run Nyay_Setu_API_Collection.postman_collection.json \
-e postman_environment.json \
--reporter cli# Output JSON report
newman run Nyay_Setu_API_Collection.postman_collection.json \
-e postman_environment.json \
--reporter json --reporter-json-export results.json# Login
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"SecurePassword123"}' \
| jq -r '.token')
echo "Token: $TOKEN"curl -X POST http://localhost:8080/api/v1/cases \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Smith vs. Johnson - Property Dispute",
"description": "Civil dispute regarding property ownership",
"court": "District Court, Delhi",
"caseType": "CIVIL",
"parties": [
{"name": "John Smith", "role": "PLAINTIFF"},
{"name": "Jane Johnson", "role": "DEFENDANT"}
]
}' | jq '.'curl -X GET "http://localhost:8080/api/v1/cases?page=0&size=20&sort=createdAt,desc" \
-H "Authorization: Bearer $TOKEN" | jq '.'CASE_ID="uuid-of-your-case"
curl -X POST http://localhost:8080/api/v1/documents/upload \
-H "Authorization: Bearer $TOKEN" \
-F "caseId=$CASE_ID" \
-F "documentType=COMPLAINT" \
-F "file=@/path/to/document.pdf"curl -X POST http://localhost:8000/api/v1/lawgpt/generate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"documentType": "AFFIDAVIT",
"caseId": "'$CASE_ID'",
"context": {
"deponentName": "John Smith",
"deponentRole": "PLAINTIFF",
"statements": ["I own the property since 2020"]
},
"language": "EN"
}' | jq '.'curl -X POST http://localhost:8001/api/v1/nlp/analyze \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"caseId": "'$CASE_ID'",
"query": "What are the legal implications?",
"analysisDepth": "STANDARD"
}' \
--rawcurl -X POST http://localhost:8001/api/v1/research/deep \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"query": "What are legal remedies for property dispute in India?",
"caseId": "'$CASE_ID'"
}' \
--no-bufferJavaScript EventSource example:
const source = new EventSource(
`http://localhost:8001/api/v1/research/deep`
);
source.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(`[${data.stage}]`, data.content);
if (data.stage === 'done') source.close();
};
source.onerror = (err) => {
console.error('SSE error:', err);
source.close();
};
Stages returned: understanding → sub_questions → kanoon_results → reasoning → final → done
import requests
import json
from typing import Dict, Optional
class NyaySetuClient:
def __init__(self, base_url="http://localhost:8080"):
self.base_url = base_url
self.token = None
self.session = requests.Session()
def login(self, email: str, password: str) -> bool:
"""Login and store token"""
response = self.session.post(
f"{self.base_url}/api/v1/auth/login",
json={"email": email, "password": password},
timeout=30,
)
if response.status_code == 200:
data = response.json()
self.token = data['token']
self.session.headers.update({
'Authorization': f'Bearer {self.token}'
})
return True
return False
def create_case(self, case_data: Dict) -> Optional[Dict]:
"""Create a new case"""
response = self.session.post(
f"{self.base_url}/api/v1/cases",
json=case_data,
timeout=30,
)
if response.status_code == 201:
return response.json()
raise Exception(f"Error: {response.status_code} - {response.text}")
def upload_document(self, case_id: str, file_path: str,
doc_type: str = "COMPLAINT") -> Optional[Dict]:
"""Upload a document"""
with open(file_path, 'rb') as f:
files = {'file': f}
data = {
'caseId': case_id,
'documentType': doc_type
}
response = self.session.post(
f"{self.base_url}/api/v1/documents/upload",
files=files,
data=data
)
if response.status_code == 201:
return response.json()
raise Exception(f"Error: {response.status_code} - {response.text}")
def list_cases(self, page: int = 0, size: int = 20) -> Dict:
"""List all cases"""
response = self.session.get(
f"{self.base_url}/api/v1/cases",
params={'page': page, 'size': size, 'sort': 'createdAt,desc'},
timeout=30
)
return response.json()
def get_case(self, case_id: str) -> Dict:
"""Get case details"""
response = self.session.get(f"{self.base_url}/api/v1/cases/{case_id}", timeout=30)
if response.status_code == 200:
return response.json()
raise Exception(f"Case not found: {case_id}")
def generate_legal_document(self, case_id: str, doc_type: str,
context: Dict, language: str = "EN") -> Dict:
"""Generate AI-powered legal document"""
response = self.session.post(
"http://localhost:8000/api/v1/lawgpt/generate",
json={
"documentType": doc_type,
"caseId": case_id,
"context": context,
"language": language
}
)
if response.status_code == 200:
return response.json()
raise Exception(f"Generation failed: {response.status_code}")
# Usage Example
if __name__ == "__main__":
client = NyaySetuClient()
# Login
if client.login("user@example.com", "SecurePassword123"):
print("✓ Logged in successfully")
else:
print("✗ Login failed")
exit(1)
# Create case
case_data = {
"title": "Smith vs. Johnson - Property Dispute",
"description": "Property boundary dispute",
"court": "District Court, Delhi",
"caseType": "CIVIL",
"parties": [
{"name": "John Smith", "role": "PLAINTIFF"},
{"name": "Jane Johnson", "role": "DEFENDANT"}
]
}
case = client.create_case(case_data)
case_id = case['id']
print(f"✓ Case created: {case_id}")
# Upload document
# doc = client.upload_document(case_id, "path/to/document.pdf")
# print(f"✓ Document uploaded: {doc['id']}")
# List cases
cases = client.list_cases()
print(f"✓ Found {cases['totalElements']} cases")
# Generate legal document
# affidavit = client.generate_legal_document(
# case_id,
# "AFFIDAVIT",
# {
# "deponentName": "John Smith",
# "deponentRole": "PLAINTIFF",
# "statements": ["I own the property since 2020"]
# }
# )
# print(f"✓ Affidavit generated")const axios = require('axios');
class NyaySetuClient {
constructor(baseUrl = 'http://localhost:8080') {
this.baseUrl = baseUrl;
this.token = null;
this.client = axios.create({ timeout: 30000 });
}
async login(email, password) {
try {
const response = await this.client.post(`${this.baseUrl}/api/v1/auth/login`, {
email,
password
});
this.token = response.data.token;
this.client.defaults.headers.common['Authorization'] = `Bearer ${this.token}`;
return response.data;
} catch (error) {
console.error('Login failed:', error.response?.data);
throw error;
}
}
async createCase(caseData) {
try {
const response = await this.client.post(`${this.baseUrl}/api/v1/cases`, caseData);
return response.data;
} catch (error) {
console.error('Case creation failed:', error.response?.data);
throw error;
}
}
async listCases(page = 0, size = 20) {
try {
const response = await this.client.get(`${this.baseUrl}/api/v1/cases`, {
params: { page, size, sort: 'createdAt,desc' }
});
return response.data;
} catch (error) {
console.error('Failed to list cases:', error.response?.data);
throw error;
}
}
async generateDocument(documentType, caseId, context, language = 'EN') {
try {
const response = await axios.post(`http://localhost:8000/api/v1/lawgpt/generate`, {
documentType,
caseId,
context,
language
}, {
headers: { Authorization: `Bearer ${this.token}` }
});
return response.data;
} catch (error) {
console.error('Document generation failed:', error.response?.data);
throw error;
}
}
}
// Usage Example
(async () => {
const client = new NyaySetuClient();
// Login
await client.login('user@example.com', 'SecurePassword123');
console.log('✓ Logged in successfully');
// Create case
const case_ = await client.createCase({
title: 'Smith vs. Johnson - Property Dispute',
description: 'Property boundary dispute',
court: 'District Court, Delhi',
caseType: 'CIVIL',
parties: [
{ name: 'John Smith', role: 'PLAINTIFF' },
{ name: 'Jane Johnson', role: 'DEFENDANT' }
]
});
console.log('✓ Case created:', case_.id);
// List cases
const cases = await client.listCases();
console.log(`✓ Found ${cases.totalElements} cases`);
})();POST /api/v1/auth/register- Register new userPOST /api/v1/auth/login- Login userPOST /api/v1/auth/refresh- Refresh tokenPOST /api/v1/auth/logout- LogoutPOST /api/v1/auth/forgot-password- Password reset
GET /api/v1/cases- List casesPOST /api/v1/cases- Create caseGET /api/v1/cases/{caseId}- Get case detailsPUT /api/v1/cases/{caseId}- Update caseDELETE /api/v1/cases/{caseId}- Archive casePOST /api/v1/cases/{caseId}/status- Change case status
POST /api/v1/documents/upload- Upload documentGET /api/v1/documents- List documentsGET /api/v1/documents/{documentId}- Get document detailsPOST /api/v1/documents/{documentId}/analyze- AI analysisGET /api/v1/documents/{documentId}/download- Download document
POST /api/v1/evidence- Add evidenceGET /api/v1/evidence- List evidenceGET /api/v1/evidence/{evidenceId}- Get evidence detailsPOST /api/v1/evidence/{evidenceId}/verify- Blockchain verification
POST /api/v1/hearings- Schedule hearingGET /api/v1/hearings- List hearingsPUT /api/v1/hearings/{hearingId}- Update hearingPOST /api/v1/hearings/{hearingId}/record- Record hearing outcome
POST /api/v1/orders- Issue orderGET /api/v1/orders- List ordersPUT /api/v1/orders/{orderId}- Update order
POST /api/v1/lawgpt/generate- Generate documentGET /api/v1/lawgpt/templates- List templates
POST /api/v1/nlp/analyze- Analyze case (with streaming)POST /api/v1/research/deep- Deep legal research (SSE streaming)POST /api/v1/forensics/analyze- Forensic analysisPOST /api/v1/modi/ocr- Modi script OCR
# 1. Login
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"lawyer@example.com","password":"Pass123"}' \
| jq -r '.token')
# 2. Create case
CASE=$(curl -s -X POST http://localhost:8080/api/v1/cases \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Smith vs Johnson",
"court": "District Court",
"caseType": "CIVIL",
"parties": [
{"name": "John Smith", "role": "PLAINTIFF"},
{"name": "Jane Johnson", "role": "DEFENDANT"}
]
}')
CASE_ID=$(echo $CASE | jq -r '.id')
# 3. Upload document
curl -X POST http://localhost:8080/api/v1/documents/upload \
-H "Authorization: Bearer $TOKEN" \
-F "caseId=$CASE_ID" \
-F "documentType=COMPLAINT" \
-F "file=@complaint.pdf"
# 4. Schedule hearing
curl -X POST http://localhost:8080/api/v1/hearings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"caseId": "'$CASE_ID'",
"scheduledDate": "2026-07-15T10:00:00Z",
"courtroom": "Room 301",
"hearingType": "PHYSICAL"
}'# 1. Generate affidavit
AFFIDAVIT=$(curl -s -X POST http://localhost:8000/api/v1/lawgpt/generate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"documentType": "AFFIDAVIT",
"caseId": "'$CASE_ID'",
"context": {
"deponentName": "John Smith",
"deponentRole": "PLAINTIFF",
"statements": ["I own the property", "Dispute started in 2023"]
},
"language": "EN"
}')
# 2. Analyze case with legal reasoning
curl -X POST http://localhost:8001/api/v1/nlp/analyze \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"caseId": "'$CASE_ID'",
"query": "What are legal remedies for property dispute?",
"analysisDepth": "DEEP"
}'# 1. Add evidence with chain of custody
EVIDENCE=$(curl -s -X POST http://localhost:8080/api/v1/evidence \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"caseId": "'$CASE_ID'",
"title": "Property Deed",
"description": "Original property deed with stamps",
"evidenceType": "DOCUMENT",
"chainOfCustody": {
"collectedBy": "John Smith",
"collectionDate": "2026-06-01T10:30:00Z",
"location": "Registry Office"
}
}')
EVIDENCE_ID=$(echo $EVIDENCE | jq -r '.evidenceId')
HASH=$(echo $EVIDENCE | jq -r '.blockchainHash')
echo "Evidence stored with blockchain hash: $HASH"
# 2. Verify evidence integrity
curl -X POST http://localhost:8080/api/v1/evidence/$EVIDENCE_ID/verify \
-H "Authorization: Bearer $TOKEN"Error: 401 Unauthorized
Solutions:
# Check if token is expired
# Solution 1: Re-login to get new token
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"Pass123"}' \
| jq -r '.token')
# Solution 2: Refresh token
curl -X POST http://localhost:8080/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refreshToken":"YOUR_REFRESH_TOKEN"}'Error: Connection refused
Solutions:
# Check if services are running
docker-compose ps
# Start services
docker-compose up -d
# Check specific service port
netstat -an | grep 8080 # For backendError: 413 Payload Too Large
Solutions:
- Maximum file size is 10MB
- Compress PDF or reduce resolution
- Split large documents
Error: No streaming response from /nlp/analyze
Solutions:
# Ensure Accept header is set
curl -X POST http://localhost:8001/api/v1/nlp/analyze \
-H "Accept: text/event-stream" \
...Error: Access to XMLHttpRequest blocked by CORS
Solutions:
- Check backend CORS configuration
- Frontend should use same base URL or proxy
Enable debug logging:
# Backend (Spring Boot)
export LOG_LEVEL=DEBUG
mvn spring-boot:run
# Python services
export LOG_LEVEL=DEBUG
python main.py# Backend health
curl http://localhost:8080/actuator/health
# LawGPT health
curl http://localhost:8000/health
# NLP Orchestrator health
curl http://localhost:8001/health
# Signaling server (if available)
curl http://localhost:3001/health✅ DO:
- Always authenticate before API calls
- Use appropriate HTTP methods (GET, POST, PUT, DELETE)
- Include descriptive error handling
- Set reasonable timeouts
- Validate input data before sending
❌ DON'T:
- Hardcode tokens in code
- Make synchronous blocking calls in UI
- Ignore error responses
- Send sensitive data in GET parameters
- Make unlimited parallel requests
✅ DO:
- Store tokens securely (httpOnly cookies for web)
- Use HTTPS in production
- Implement rate limiting
- Validate file uploads
- Log security events
❌ DON'T:
- Expose tokens in logs
- Store passwords in code
- Trust client-side validation only
- Allow arbitrary file uploads
- Use default credentials
✅ DO:
- Cache responses appropriately
- Use pagination for large lists
- Implement connection pooling
- Monitor API response times
- Use pagination filters
❌ DON'T:
- Load all data at once
- Make duplicate API calls
- Ignore timeouts
- Create new connections per request
✅ DO:
- Test all CRUD operations
- Test error scenarios
- Test with actual data
- Test concurrent requests
- Document test cases
❌ DON'T:
- Only test happy paths
- Test in production
- Skip authorization tests
- Forget edge cases
✅ DO:
- Document API requirements
- Provide code examples
- Explain error codes
- List required headers
- Include sample requests/responses
❌ DON'T:
- Use vague descriptions
- Assume knowledge
- Omit authentication details
- Forget error cases
Implement proper error handling:
try:
response = client.create_case(case_data)
except requests.exceptions.ConnectionError:
print("Backend service is not running")
except requests.exceptions.Timeout:
print("Request timed out")
except requests.exceptions.HTTPError as e:
print(f"HTTP Error: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"Unexpected error: {e}")- OpenAPI Documentation: See
openapi.yaml - Postman Collection: Import
Nyay_Setu_API_Collection.postman_collection.json - API Quick Reference: See
API_QUICK_REFERENCE.md - Full Endpoint List: See
API_ENDPOINTS_COMPREHENSIVE.md - Contributing Guide: See
CONTRIBUTING.md
For issues or questions:
- Check troubleshooting section above
- Review comprehensive endpoint documentation
- Check service logs:
docker-compose logs -f [service-name] - Create GitHub issue with details
- Contact team at support@nyaysetu.in