Skip to main content

API Reference β€” Overview

The CivicPulse REST API is a JSON-over-HTTP API served by the Express backend. All endpoints are prefixed with /api.


Base URL​

EnvironmentBase URL
Local developmenthttp://localhost:3001/api
Productionhttps://api.civicpulse.in/api

Authentication​

Most write endpoints and some read endpoints require a valid JWT access token.

Header format:

Authorization: Bearer <accessToken>

Access tokens are issued by POST /api/auth/google and refreshed via POST /api/auth/refresh. They expire after 15 minutes. The refresh token is stored as an httpOnly cookie and is valid for 7 days.

Endpoints that require authentication are marked with a lock icon or note in their respective sections.


Response Envelope​

All API responses follow a consistent envelope:

Success:

{
"success": true,
"data": { }
}

Error:

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "title is required",
"details": [
{ "field": "title", "message": "title must not be empty" }
]
}
}

Common error codes:

CodeHTTP StatusMeaning
VALIDATION_ERROR400Request body/params failed validation
UNAUTHORIZED401Missing or expired access token
FORBIDDEN403Valid token but insufficient role
NOT_FOUND404Resource does not exist
CONFLICT409Duplicate action (e.g. upvoting twice)
RATE_LIMITED429Too many requests
INTERNAL_ERROR500Unexpected server error

Paginated Responses​

List endpoints that can return large result sets use DynamoDB-style cursor pagination:

{
"success": true,
"data": {
"count": 20,
"items": [ ],
"nextKey": "eyJQSyI6Ikl...",
"_links": {
"self": "/api/issues?city=mumbai&limit=20",
"next": "/api/issues?city=mumbai&limit=20&lastKey=eyJQSyI6Ikl..."
}
}
}
FieldTypeDescription
countnumberNumber of items in this page
itemsarrayThe result records
nextKeystring | nullOpaque cursor for the next page; null if this is the last page
_links.nextstring | nullReady-to-use URL for the next page

To fetch subsequent pages, pass ?lastKey=<nextKey> as a query parameter.


Rate Limits​

ScopeLimitWindow
General (/api/*)100 requests15 minutes per IP
Auth (/api/auth/*)20 requests15 minutes per IP

When the limit is exceeded, the API responds with HTTP 429 and the following headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312200
Retry-After: 847

Machine-Readable API Index​

GET /api/ returns a JSON document listing all available routes, valid enum values, and pagination parameters. This is useful for building API clients or integration tests without reading documentation.

curl http://localhost:3001/api/

See Discovery & Enums for details.


Postman Collection​

The fastest way to explore the API is with the official Postman collection. It covers all 41 endpoints, includes pre-request auth scripts that auto-save the access token after login, and ships ready-to-use environments for local dev and production.

Download​

πŸ‘‰ Download CivicPulse_API.postman_collection.json

Or clone the repo and find it at postman/CivicPulse_API.postman_collection.json.

Import & run in 3 steps​

Step 1 β€” Import

Postman β†’ File β†’ Import β†’ select CivicPulse_API.postman_collection.json

Or drag the file into the Postman window.

Step 2 β€” Set the base URL

Open the collection's Variables tab and set baseUrl:

EnvironmentValue
Local devhttp://localhost:3001/api
Productionhttps://api.civicpulse.in/v1

Step 3 β€” Authenticate

  1. Open πŸ” Auth β†’ Google Sign-In.
  2. Replace <google-id-token> in the body with a real Google ID token.
  3. Send β€” the test script auto-saves the accessToken collection variable.
  4. All subsequent requests are automatically authenticated via the collection-level bearer token.

Run with Newman (CLI)​

Newman lets you run the collection in CI/CD:

# Install Newman globally
npm install -g newman

# Run the full collection against local dev
newman run postman/CivicPulse_API.postman_collection.json \
--env-var "baseUrl=http://localhost:3001/api" \
--env-var "accessToken=<your-token>"

# Pretty HTML report
npm install -g newman-reporter-html
newman run postman/CivicPulse_API.postman_collection.json \
--reporters html \
--reporter-html-export newman-report.html

Collection variables​

VariableDefaultDescription
baseUrlhttp://localhost:3001/apiAPI root β€” change per environment
accessToken(auto-set on login)JWT access token
issueIdISS-001Issue ID used in parameterised requests
userIdu1User ID for score/role endpoints
mediaId(auto-set on presign)Media ID from presign response
messageId(auto-set on post)Message ID from post response
reqIdReopen-request ID for review endpoints

Endpoint Groups​

GroupBase PathDescription
Authentication/api/authGoogle OAuth login, token refresh, logout
Issues/api/issuesCRUD for civic issues, upvotes, assignment, bulk status, stats
Resolution Flow/api/issues/:id/resolveResolve with proof, community rating, reopen requests, close
Messages/api/issues/:id/messagesPer-issue chat thread and reactions
Media/api/issues/:id/mediaS3 presigned uploads and Twitter URL attachments
Scores/api/scoresContributor leaderboard and individual score
Admin/api/admin, /api/usersUser role management, reopen queue, flagged issues
Accountability/api/accountability-chain, /api/jurisdictions, /api/officialsAccountability chain resolution, official hierarchy, departments, police stations
X (Twitter)/api/x/mentionsX API v2 mentions feed, tweet β†’ issue conversion
WhatsApp/api/whatsapp/webhook, /api/whatsapp/messagesWhatsApp Business API webhook, message β†’ issue conversion
Instagram/api/ig/mentionsInstagram Graph API mentions feed, post β†’ issue conversion
Discovery/api/, /api/cities, /api/categoriesAPI index, city list, category list

Health Check​

GET /api/health

Returns server uptime and timestamp. No authentication required. Use this endpoint for load balancer health probes.

{
"status": "ok",
"uptime": 14523.4,
"timestamp": "2025-01-15T10:30:00.000Z"
}