📚 API Documentation

Integrate civic complaint management into your applications with our simple, powerful REST API

Version 1.0 | Updated January 2026

Overview

The Corporations of Greater Bengaluru API enables developers to integrate civic complaint management into their applications. Submit complaints, track status, and access municipal corporation data programmatically.

🌐 Base URL: https://notf-cms.vercel.app/api

Key Features

  • ✅ Submit complaints to 12 Indian cities
  • ✅ Auto-route complaints to correct municipal corporation
  • ✅ Support for base64 photo uploads and GPS location data
  • ✅ Real-time ticket number generation
  • ✅ Automatic issue categorization (304 categories)
  • ✅ Category code to UUID auto-conversion
  • ✅ No authentication required for public endpoints

Authentication

Currently, the API is publicly accessible with no authentication required. Future versions may include API keys for advanced features.

⚠️ Rate Limiting: While no API key is required, please be mindful of request volume. We reserve the right to implement rate limits in the future.

Endpoints

POST /submit-complaint

Submit a new civic complaint to a municipal corporation.

Request Format

Required Headers

Header Value Description
Content-Type application/json Request body format

Request Parameters

Parameter Type Required Description
description string Required Detailed description of the issue (min 10 characters)
address string Required Full address where the issue exists
citizen_phone string Required* 10-digit Indian mobile number (starts with 6-9)
citizen_email string Required* Valid email address
latitude number Optional GPS latitude coordinate
longitude number Optional GPS longitude coordinate
corporation_id string Optional Corporation code (e.g., "chennai", "north") or UUID
category_id string Optional Issue category code (e.g., "garbage_not_collected") or UUID
citizen_name string Optional Name of complainant (can be anonymous)
photo string Optional Base64-encoded image with data URL prefix (e.g., "data:image/jpeg;base64,...")
photo_filename string Optional Original filename of the photo (used with photo parameter)
photo_size number Optional File size in bytes (used with photo parameter)
* Contact Requirement: At least one of citizen_phone or citizen_email must be provided.
📸 Photo Upload: Photos must be sent as base64-encoded strings in JSON format. FormData/multipart requests are not supported. Use the FileReader API to convert images to base64 before sending.

Supported Cities

Use these corporation codes for the corporation_id parameter:

Code City State
bengaluru or north/south/east/west/centralBengaluruKarnataka
ahmedabadAhmedabadGujarat
bhubaneswarBhubaneswarOdisha
chennaiChennaiTamil Nadu
gurugramGurugramHaryana
hyderabadHyderabadTelangana
jaipurJaipurRajasthan
kolkataKolkataWest Bengal
mumbaiMumbaiMaharashtra
punePuneMaharashtra
thaneThaneMaharashtra
visakhapatnamVisakhapatnamAndhra Pradesh

Example Request (Without Photo)

{
  "description": "Streetlight not working on MG Road near City Center",
  "address": "MG Road, Bengaluru North, Karnataka 560001",
  "latitude": 12.9716,
  "longitude": 77.5946,
  "citizen_phone": "9876543210",
  "citizen_name": "Ramesh Kumar",
  "corporation_id": "north",
  "category_id": "streetlight_not_working"
}

Example Request (With Photo)

{
  "description": "Broken pavement causing safety hazard",
  "address": "MG Road, Bengaluru North, Karnataka 560001",
  "latitude": 12.9716,
  "longitude": 77.5946,
  "citizen_phone": "9876543210",
  "citizen_name": "Ramesh Kumar",
  "corporation_id": "north",
  "category_id": "pavement_broken",
  "photo": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...",
  "photo_filename": "broken-pavement.jpg",
  "photo_size": 245678
}

Response Format

Success Response (200 OK)

{
  "success": true,
  "complaint": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "complaint_number": "NOR-26-000123",
    "corporation_id": "123e4567-e89b-12d3-a456-426614174000",
    "category_id": "789e4567-e89b-12d3-a456-426614174000",
    "description": "Streetlight not working on MG Road near City Center",
    "address": "MG Road, Bengaluru North, Karnataka 560001",
    "latitude": 12.9716,
    "longitude": 77.5946,
    "citizen_name": "Ramesh Kumar",
    "citizen_phone": "9876543210",
    "status": "new",
    "created_at": "2026-01-18T12:30:45.123Z"
  },
  "complaint_number": "NOR-26-000123",
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "photo_url": "https://abblyaukkoxmgzwretvm.supabase.co/storage/v1/object/public/notf-cms/550e8400-e29b-41d4-a716-446655440000/1737203445123.jpg",
  "message": "Complaint submitted successfully. Ticket: NOR-26-000123"
}
📸 Photo URL: If a photo was uploaded, the photo_url field contains the public URL to the uploaded image in Supabase Storage. This field is null if no photo was provided.
✅ Ticket Numbers: Format is {CORP_CODE}-{YEAR}-{NUMBER}. Example: NOR-26-000123 (Bengaluru North, 2026, complaint #123)

Error Handling

Error Response Format

{
  "error": "Description must be at least 10 characters long."
}

HTTP Status Codes

Status Code Meaning Description
200 OK Complaint submitted successfully
400 Bad Request Invalid parameters or missing required fields
405 Method Not Allowed HTTP method not supported (use POST)
500 Internal Server Error Server-side error occurred

Common Error Messages

  • "Description must be at least 10 characters long."
  • "Please provide either a phone number or email address."
  • "Invalid phone number. Must be 10 digits starting with 6-9."
  • "Invalid email address format."
  • "Invalid corporation code: {code}"

Code Examples

JavaScript (Fetch API)

// Without photo
const response = await fetch('https://notf-cms.vercel.app/api/submit-complaint', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    description: 'Streetlight not working on MG Road',
    address: 'MG Road, Bengaluru North, Karnataka 560001',
    latitude: 12.9716,
    longitude: 77.5946,
    citizen_phone: '9876543210',
    citizen_name: 'Ramesh Kumar',
    corporation_id: 'north',
    category_id: 'streetlight_not_working'
  })
});

const data = await response.json();
console.log('Ticket Number:', data.complaint_number);

// With photo upload
function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

// Convert photo to base64
const photoFile = document.getElementById('photoInput').files[0];
const base64Photo = await fileToBase64(photoFile);

const responseWithPhoto = await fetch('https://notf-cms.vercel.app/api/submit-complaint', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    description: 'Broken pavement causing safety hazard',
    address: 'MG Road, Bengaluru North, Karnataka 560001',
    latitude: 12.9716,
    longitude: 77.5946,
    citizen_phone: '9876543210',
    citizen_name: 'Ramesh Kumar',
    corporation_id: 'north',
    category_id: 'pavement_broken',
    photo: base64Photo,
    photo_filename: photoFile.name,
    photo_size: photoFile.size
  })
});

const dataWithPhoto = await responseWithPhoto.json();
console.log('Ticket Number:', dataWithPhoto.complaint_number);
console.log('Photo URL:', dataWithPhoto.photo_url);

Python (Requests)

import requests
import base64

# Without photo
response = requests.post(
    'https://notf-cms.vercel.app/api/submit-complaint',
    json={
        'description': 'Streetlight not working on MG Road',
        'address': 'MG Road, Bengaluru North, Karnataka 560001',
        'latitude': 12.9716,
        'longitude': 77.5946,
        'citizen_phone': '9876543210',
        'citizen_name': 'Ramesh Kumar',
        'corporation_id': 'north',
        'category_id': 'streetlight_not_working'
    }
)

data = response.json()
print(f"Ticket Number: {data['complaint_number']}")

# With photo upload
with open('photo.jpg', 'rb') as photo_file:
    photo_data = photo_file.read()
    base64_photo = f"data:image/jpeg;base64,{base64.b64encode(photo_data).decode('utf-8')}"

response_with_photo = requests.post(
    'https://notf-cms.vercel.app/api/submit-complaint',
    json={
        'description': 'Broken pavement causing safety hazard',
        'address': 'MG Road, Bengaluru North, Karnataka 560001',
        'latitude': 12.9716,
        'longitude': 77.5946,
        'citizen_phone': '9876543210',
        'citizen_name': 'Ramesh Kumar',
        'corporation_id': 'north',
        'category_id': 'pavement_broken',
        'photo': base64_photo,
        'photo_filename': 'photo.jpg',
        'photo_size': len(photo_data)
    }
)

data_with_photo = response_with_photo.json()
print(f"Ticket Number: {data_with_photo['complaint_number']}")
print(f"Photo URL: {data_with_photo['photo_url']}")

cURL

curl -X POST https://notf-cms.vercel.app/api/submit-complaint \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Streetlight not working on MG Road",
    "address": "MG Road, Bengaluru North, Karnataka 560001",
    "latitude": 12.9716,
    "longitude": 77.5946,
    "citizen_phone": "9876543210",
    "citizen_name": "Ramesh Kumar",
    "corporation_id": "north",
    "category_id": "streetlight_not_working"
  }'

Try It Out

🧪 Test the API Live

Rate Limits

Currently, there are no strict rate limits. However, we recommend:

  • Maximum 100 requests per minute from a single IP
  • Implement exponential backoff for retries
  • Cache responses when appropriate
⚠️ Fair Use Policy: Please use the API responsibly. Excessive usage may result in temporary IP blocking.

Support & Feedback

Need help? Found a bug? Have a feature request?

📝 Changelog: Last updated January 18, 2026 - Added base64 photo upload support and category code auto-conversion (all 304 categories available)