Skip to content

API Overview

Introduction

The ESG Data Collection Platform provides a RESTful API for mobile collectors, web frontends, and admin dashboards to submit, review, and report on ESG (Environmental, Social, and Governance) metrics.

The API supports: - Data Collection: Mobile and web submission of environmental, social, and governance metrics - Review & Approval: Workflow management for data validation and approval - Report Generation: Automated generation of GRI sustainability reports, carbon footprint reports, human capital reports (GRI 405-1, GRI 401), and environment reports (G.1-G.10) - Administration: User management, metric catalog configuration, and audit logging

This document outlines the fundamental API conventions, authentication mechanisms, versioning strategy, and rate limiting rules that apply across all endpoints.

Base URL

Production:  https://api.esgplatform.com
Staging:     https://staging-api.esgplatform.com
Development: http://localhost:8080

All API endpoints are prefixed with /api/v1/ unless otherwise specified.

Authentication

JWT Authentication

The API uses JSON Web Tokens (JWT) for authentication. All endpoints except /api/v1/auth/login and /api/v1/auth/refresh require a valid JWT token.

Token Structure

{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "user-uuid",
    "tenant_id": "tenant-uuid",
    "roles": ["COLLECTOR", "REVIEWER"],
    "iat": 1704067200,
    "exp": 1704153600
  }
}

Authentication Flow

  1. Login: Obtain access and refresh tokens
POST /api/v1/auth/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "securePassword123"
}

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "user": {
    "id": "user-uuid",
    "email": "user@example.com",
    "roles": ["COLLECTOR"]
  }
}

  1. Authenticated Requests: Include token in Authorization header
GET /api/v1/collector/submissions
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
  1. Token Refresh: Obtain new access token before expiration
POST /api/v1/auth/refresh
Content-Type: application/json

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 86400
}

Token Lifecycle

  • Access Token: Valid for 24 hours
  • Refresh Token: Valid for 30 days
  • Session Storage: Redis-backed for revocation capability
  • Logout: Invalidates both tokens immediately

Password Security

  • Hashing: Quarkus Elytron password providers (BCrypt, PBKDF2, scrypt)
  • Failed Login: Account lockout after 5 failed attempts (15-minute lockout)
  • Password Requirements: Minimum 12 characters, must include uppercase, lowercase, number, and special character

Tenant Isolation

All authenticated requests automatically scope data access to the user's tenant. The tenant_id from the JWT is enforced at the database query level to ensure complete data isolation between organizations.

Attempting to access resources from another tenant results in:

{
  "error": "RESOURCE_NOT_FOUND",
  "message": "The requested resource does not exist",
  "timestamp": "2025-01-11T10:30:00Z",
  "request_id": "req_abc123"
}

API Versioning

Versioning Strategy

The API uses URI versioning with the version identifier in the path: /api/v1/, /api/v2/, etc.

Version Support Policy

  • Current Version: v1
  • Support Window: Each major version is supported for 24 months after the next version's release
  • Deprecation Notice: 6 months advance notice via email, API headers, and documentation
  • Breaking Changes: Only introduced in new major versions

Version Headers

All responses include version information:

HTTP/1.1 200 OK
X-API-Version: v1
X-API-Deprecated: false

When an endpoint is deprecated:

HTTP/1.1 200 OK
X-API-Version: v1
X-API-Deprecated: true
X-API-Deprecation-Date: 2026-06-01
X-API-Sunset-Date: 2026-12-01
Link: </api/v2/collector/submissions>; rel="successor-version"

Breaking vs Non-Breaking Changes

Non-Breaking Changes (patch/minor versions): - Adding new endpoints - Adding optional request parameters - Adding new fields to responses - Adding new response codes for edge cases - Relaxing validation rules

Breaking Changes (major versions only): - Removing endpoints - Removing request/response fields - Changing field types - Making optional fields required - Changing authentication mechanisms - Changing error response structure

Version Migration

When migrating to a new version: 1. Review the migration guide at /docs/api/migration-v1-to-v2.md 2. Test thoroughly in staging environment 3. Update client code to use new version path 4. Monitor for deprecation headers 5. Complete migration before sunset date

Rate Limiting

Rate Limit Rules

Rate limits protect the API from abuse and ensure fair resource allocation across all users.

Limits by Endpoint Category

Endpoint Category Rate Limit Window Scope
Authentication (/auth/*) 10 requests 15 minutes IP address
Collector API (/collector/*) 1000 requests 1 hour User + Tenant
Admin API (/admin/*) 500 requests 1 hour User + Tenant
Report Generation 10 reports 1 hour Tenant
File Upload 100 uploads 1 hour User + Tenant
Sync Endpoint 60 requests 1 minute User

Rate Limit Headers

All responses include rate limit information:

HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1704153600
X-RateLimit-Window: 3600

Where: - X-RateLimit-Limit: Maximum requests allowed in the window - X-RateLimit-Remaining: Requests remaining in current window - X-RateLimit-Reset: Unix timestamp when the window resets - X-RateLimit-Window: Window size in seconds

Rate Limit Exceeded Response

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 3600
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704153600

{
  "error": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded. Please retry after 3600 seconds.",
  "limit": 1000,
  "window": 3600,
  "retry_after": 3600,
  "timestamp": "2025-01-11T10:30:00Z",
  "request_id": "req_abc123"
}

Rate Limit Best Practices

  1. Monitor Headers: Check X-RateLimit-Remaining before making bulk requests
  2. Implement Backoff: Use exponential backoff when receiving 429 responses
  3. Batch Operations: Use batch endpoints when available (e.g., bulk submission creation)
  4. Cache Responses: Cache GET responses to reduce redundant requests
  5. Contact Support: Request limit increases for legitimate high-volume use cases

Enterprise Rate Limits

Enterprise customers can request higher rate limits by contacting support. Custom limits are configured per tenant based on usage patterns and SLA agreements.

API Conventions

HTTP Methods

The API follows RESTful conventions for HTTP methods:

Method Usage Idempotent
GET Retrieve resources Yes
POST Create resources, trigger actions No*
PUT Replace entire resource Yes
PATCH Partial update No
DELETE Remove resource (soft delete) Yes

*POST endpoints with idempotency keys are idempotent

Idempotency

All POST endpoints that create resources support idempotency to prevent duplicate submissions from network retries.

Idempotency Key

Include an Idempotency-Key header with a unique identifier (e.g., UUID v4):

POST /api/v1/collector/submissions
Authorization: Bearer token...
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{
  "metric_template_id": "metric-uuid",
  "value": 42.5,
  ...
}

Behavior: - First request with a new key: Creates the resource, returns 201 Created - Duplicate request with same key within 24 hours: Returns original 201 response from cache - After 24 hours: Key expires, treated as new request

Request Format

Content Type

All request bodies must use application/json unless uploading files (which use multipart/form-data).

Content-Type: application/json

Request Body Structure

Request bodies use camelCase for field names:

{
  "metricTemplateId": "uuid",
  "value": 42.5,
  "collectedAt": "2025-01-11T10:30:00Z",
  "metadata": {
    "source": "manual",
    "notes": "Measured during morning shift"
  }
}

Date/Time Format

All dates and timestamps use ISO 8601 format with UTC timezone:

{
  "collectedAt": "2025-01-11T10:30:00Z",
  "periodStart": "2025-01-01",
  "periodEnd": "2025-12-31"
}

Response Format

Content Type

All responses return application/json:

Content-Type: application/json; charset=utf-8

Success Response Structure

Success responses use camelCase and include relevant metadata:

{
  "id": "uuid",
  "metricTemplateId": "uuid",
  "value": 42.5,
  "state": "VALIDATED",
  "createdAt": "2025-01-11T10:30:00Z",
  "updatedAt": "2025-01-11T10:35:00Z"
}

Collection Response Structure

Collection endpoints return paginated results:

{
  "data": [
    { "id": "uuid1", ... },
    { "id": "uuid2", ... }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 50,
    "totalPages": 10,
    "totalItems": 487,
    "hasNext": true,
    "hasPrevious": false
  },
  "links": {
    "self": "/api/v1/collector/submissions?page=1&pageSize=50",
    "next": "/api/v1/collector/submissions?page=2&pageSize=50",
    "last": "/api/v1/collector/submissions?page=10&pageSize=50"
  }
}

Error Response Structure

All errors follow a consistent format (see Error Handling for details):

{
  "error": "VALIDATION_ERROR",
  "message": "Invalid submission data",
  "timestamp": "2025-01-11T10:30:00Z",
  "request_id": "req_abc123",
  "details": [
    {
      "field": "value",
      "code": "VALUE_OUT_OF_RANGE",
      "message": "Value must be between 0 and 1000"
    }
  ]
}

HTTP Status Codes

The API uses standard HTTP status codes:

Success Codes (2xx)

  • 200 OK: Request succeeded
  • 201 Created: Resource created successfully
  • 202 Accepted: Request accepted for async processing
  • 204 No Content: Success with no response body (e.g., DELETE)

Client Error Codes (4xx)

  • 400 Bad Request: Invalid request format or validation error
  • 401 Unauthorized: Missing or invalid authentication token
  • 403 Forbidden: Authenticated but lacking permissions
  • 404 Not Found: Resource does not exist
  • 409 Conflict: Resource conflict (e.g., duplicate submission)
  • 422 Unprocessable Entity: Valid format but business rule violation
  • 429 Too Many Requests: Rate limit exceeded

Server Error Codes (5xx)

  • 500 Internal Server Error: Unexpected server error
  • 502 Bad Gateway: Upstream service failure
  • 503 Service Unavailable: Service temporarily unavailable
  • 504 Gateway Timeout: Upstream service timeout

Pagination

All collection endpoints support pagination with consistent query parameters:

Query Parameters

GET /api/v1/collector/submissions?page=1&pageSize=50&sort=createdAt:desc
Parameter Type Default Description
page integer 1 Page number (1-indexed)
pageSize integer 50 Items per page (max 100)
sort string - Sort field and direction (e.g., createdAt:desc)

Response Format

See Collection Response Structure above.

Filtering and Searching

Collection endpoints support filtering via query parameters:

GET /api/v1/collector/submissions?state=DRAFT&periodId=uuid&search=energy

Common filter parameters: - state: Filter by submission state - periodId: Filter by reporting period - search: Full-text search across relevant fields - createdAfter / createdBefore: Filter by creation date - metricTemplateId: Filter by metric template

Request ID Tracking

Every request includes a unique request ID for tracing:

X-Request-ID: req_abc123

This ID appears in: - Response headers - Error messages - Application logs - Support tickets

When reporting issues, always include the request ID.

CORS Configuration

The API supports Cross-Origin Resource Sharing (CORS) for web frontends:

Allowed Origins: - https://app.esgplatform.com (production) - https://staging.esgplatform.com (staging) - http://localhost:3000 (development)

Allowed Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS

Allowed Headers: Authorization, Content-Type, Idempotency-Key, X-Request-ID

Exposed Headers: X-RateLimit-*, X-API-Version, X-Request-ID

Credentials: Supported (cookies and authentication headers)

Compression

The API supports gzip compression. Include the Accept-Encoding header:

GET /api/v1/admin/submissions
Accept-Encoding: gzip, deflate

Response:

HTTP/1.1 200 OK
Content-Encoding: gzip

Security Considerations

HTTPS Only

All production and staging endpoints require HTTPS. HTTP requests are automatically redirected to HTTPS.

API Keys vs JWT

  • JWT Tokens: Used for user authentication (web/mobile apps)
  • API Keys: Not currently supported (may be added for machine-to-machine integrations)

Security Headers

All responses include security headers:

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'self'

Input Validation

All inputs are validated before processing: - Request body structure validation - Field type validation - Business rule validation - SQL injection prevention - XSS prevention

Sensitive Data

The following fields are considered sensitive and are: - Encrypted at rest in the database - Redacted in logs - Excluded from error messages

Sensitive fields: password, jwt_secret, PII fields (name, email when required by GDPR)

API Documentation

Interactive Documentation

Explore the API interactively using Quarkus Swagger UI (SmallRye OpenAPI):

https://api.esgplatform.com/q/swagger-ui/

OpenAPI Specification

Download the OpenAPI 3.0 specification:

https://api.esgplatform.com/q/openapi

Additional Documentation

Support

For API questions or issues: - Documentation: https://docs.esgplatform.com - Email: api-support@esgplatform.com - Status Page: https://status.esgplatform.com

Changelog

v1.0.0 (2025-01-11)

  • Initial API release
  • JWT authentication
  • Collector and Admin endpoints
  • Rate limiting
  • Comprehensive error handling

v1.1.0 (2026-01-17)

  • Added human capital report generation endpoints
  • Support for GRI 405-1 and GRI 401 reporting
  • CSV/XLSX export formats for HR metrics
  • Advanced filtering and aggregation options