Core API Design
Last Updated: 2025-11-02
Last Updated: 2025-11-02 ADR Reference: ADR-003: Meaningful Identifiers in Public APIs
This document outlines the foundational API design patterns, external integrations, and common components shared across all BATbern Event Management Platform domain APIs.
OpenAPI Specification
openapi: 3.0.0
info:
title: BATbern Event Management Platform API
version: 1.0.0
description: Comprehensive API for the BATbern Event Management Platform supporting organizers, speakers, partners, and attendees
servers:
- url: https://api.batbern.ch
description: Production API
- url: https://api.staging.batbern.ch
description: Staging API
- url: http://localhost:8080
description: Local Development API
security:
- BearerAuth: []
Domain API Documentation
The BATbern API is organized by domain-driven design principles. Each domain has its own detailed API documentation:
- Event Management API - Event lifecycle, workflows, slots, and organizer operations
- Speaker Coordination API - Speaker management, preferences, quality review, and materials
- Partner Coordination API - Partner relationships, topic voting, and meeting coordination
- Attendee Experience API - Registration, content discovery, and attendee dashboard
- Company Management API - Company profiles, Swiss UID validation, and verification workflows
- User Management API - User profiles, preferences, settings, roles, and GDPR compliance
External APIs
AWS Cognito API
- Purpose: Multi-role user authentication and authorization management
- Documentation: https://docs.aws.amazon.com/cognito/latest/developerguide/
- Base URL(s): https://cognito-idp.eu-central-1.amazonaws.com/
- Authentication: AWS IAM roles and policies
- Rate Limits: 10,000 requests per second per user pool
Key Endpoints Used:
POST /oauth2/token- JWT token generation and refreshPOST /admin/createUser- Programmatic user creation for organizersGET /oauth2/userInfo- User profile and role information
Integration Notes: Custom attributes store BATbern-specific roles (organizer, speaker, partner, attendee). Lambda triggers handle user registration workflows and role assignment validation.
AWS SES API
- Purpose: Transactional email delivery for notifications, invitations, and newsletter distribution
- Documentation: https://docs.aws.amazon.com/ses/latest/dg/
- Base URL(s): https://email.eu-central-1.amazonaws.com/
- Authentication: AWS IAM service roles
- Rate Limits: 14 emails per second (adjustable based on reputation)
Key Endpoints Used:
POST /v2/email/outbound-emails- Send transactional emailsPOST /v2/email/bulk-emails- Newsletter distributionPOST /v2/email/templates- Email template management
Integration Notes: Templates stored for speaker invitations, event notifications, and partner reports. Bounce and complaint handling integrated with user management.
AWS S3 API
- Purpose: File storage for logos, presentations, handouts, and historical content
- Documentation: https://docs.aws.amazon.com/s3/latest/API/
- Base URL(s): https://s3.eu-central-1.amazonaws.com/
- Authentication: AWS IAM service roles with bucket policies
- Rate Limits: 3,500 PUT/POST requests per second per prefix
Key Endpoints Used:
PUT /bucket/{key}- File upload with metadataGET /bucket/{key}- File retrieval with access controlPOST /bucket?delete- Batch file deletion for content management
Integration Notes: Presigned URLs for direct browser uploads. Lifecycle policies for archival content. CloudFront integration for global CDN distribution.
API Design Principles
Authentication & Authorization
- JWT Bearer Tokens: AWS Cognito-issued tokens with custom claims
- Role-Based Access Control: Fine-grained permissions per user type
- Rate Limiting: Per-user and per-endpoint rate limits
- API Key Management: Service-to-service authentication
Data Consistency
- Eventual Consistency: Cross-service data synchronization via events
- Optimistic Locking: Concurrent update conflict resolution
- Idempotency: Safe retry mechanisms for critical operations
- Data Validation: Schema validation at API gateway level
Performance Optimization
- Response Caching: Caffeine in-memory caching for frequently accessed data
- Pagination: Consistent pagination patterns across all list endpoints
- Field Selection: GraphQL-style field selection for large objects
- Bulk Operations: Batch endpoints for high-volume operations
Error Handling
- Standard HTTP Status Codes: Consistent error response patterns
- Detailed Error Messages: Structured error objects with context
- Correlation IDs: Request tracing across service boundaries
- Circuit Breakers: Fault tolerance for external service calls
Common Components & Schemas
Security Schemes
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
Common Schemas
# Page-based pagination metadata (NOT offset/cursor). Source: shared-kernel api.PaginationMetadata.
PaginationMetadata:
type: object
required: [page, limit, totalItems, totalPages, hasNext, hasPrev]
properties:
page:
type: integer
description: Current page index
limit:
type: integer
description: Page size (items per page)
totalItems:
type: integer
format: int64
description: Total number of items across all pages
totalPages:
type: integer
description: Total number of pages
hasNext:
type: boolean
description: Whether a next page exists
hasPrev:
type: boolean
description: Whether a previous page exists
# Flat error envelope (NOT nested under `error`). Source: shared-kernel dto.ErrorResponse.
# @JsonInclude(NON_NULL): absent fields are omitted from the wire.
ErrorResponse:
type: object
properties:
timestamp:
type: string
format: date-time
path:
type: string
description: Request path that generated the error
status:
type: integer
description: HTTP status code
error:
type: string
description: Short HTTP reason phrase
errorCode:
type: string
description: Stable machine-readable error code for typed client handling
message:
type: string
description: Human-readable error message
correlationId:
type: string
description: Correlation ID for tracing
severity:
type: string
enum: [LOW, MEDIUM, HIGH, CRITICAL]
details:
type: object
additionalProperties: true
description: Additional structured context (e.g. per-field validation errors)
stackTrace:
type: string
description: Dev/staging diagnostics only β never in production
Venue:
type: object
properties:
name:
type: string
address:
type: string
city:
type: string
postalCode:
type: string
capacity:
type: integer
Session:
type: object
properties:
id:
type: string
description: Meaningful identifier (see ADR-003)
title:
type: string
description:
type: string
startTime:
type: string
format: date-time
endTime:
type: string
format: date-time
speakers:
type: array
items:
$ref: '#/components/schemas/SessionSpeaker'
materials:
type: array
items:
$ref: '#/components/schemas/ContentMetadata'
SessionSpeaker:
type: object
properties:
username:
type: string
description: Meaningful identifier (see ADR-003)
workflowState:
$ref: '#/components/schemas/SpeakerWorkflowState'
invitedAt:
type: string
format: date-time
confirmedAt:
type: string
format: date-time
declinedAt:
type: string
format: date-time
SpeakerProfile:
type: object
properties:
bio:
type: string
maxLength: 500
photoUrl:
type: string
format: uri
expertiseAreas:
type: array
items:
type: string
socialLinks:
type: object
properties:
linkedin:
type: string
format: uri
twitter:
type: string
format: uri
website:
type: string
format: uri
CompanyLogo:
type: object
properties:
fileId:
type: string
description: Meaningful identifier (see ADR-003)
url:
type: string
format: uri
thumbnailUrl:
type: string
format: uri
uploadedAt:
type: string
format: date-time
ContentMetadata:
type: object
properties:
fileId:
type: string
description: Meaningful identifier (see ADR-003)
filename:
type: string
contentType:
type: string
enum: [presentation, logo, speaker_photo, speaker_cv, event_photo, archive_material]
mimeType:
type: string
fileSizeBytes:
type: integer
format: int64
uploadedBy:
type: string
description: Meaningful identifier (see ADR-003)
uploadedAt:
type: string
format: date-time
cdnUrl:
type: string
format: uri
description: CloudFront CDN URL for file access
status:
type: string
enum: [pending, uploading, completed, failed, deleted]
checksum:
type: string
description: SHA-256 checksum for integrity verification
API Versioning Strategy
All APIs use URL-based versioning with the format /api/v{version}/...:
- Current version:
v1 - Version changes trigger new major version only for breaking changes
- Backward-compatible additions made to existing version
- Deprecated endpoints maintained for minimum 6 months with deprecation headers
Cross-Cutting Concerns
Request/Response Headers
Standard Request Headers:
Authorization: Bearer {token}- JWT authentication tokenX-Correlation-ID: {uuid}- Request correlation ID (auto-generated if not provided)Accept-Language: {locale}- Preferred response language (en, de)Content-Type: application/json- Request content type
Standard Response Headers:
X-Correlation-ID: {uuid}- Request correlation ID for tracingX-RateLimit-Limit: {number}- Rate limit thresholdX-RateLimit-Remaining: {number}- Remaining requests in windowX-RateLimit-Reset: {timestamp}- Rate limit window reset time
Rate Limiting
All endpoints enforce rate limiting based on user role:
- Attendee: 100 requests per minute
- Speaker: 200 requests per minute
- Partner: 300 requests per minute
- Organizer: 500 requests per minute
Rate limit exceeded returns 429 Too Many Requests with retry-after header.
Caching Strategy
- GET endpoints: Support
ETagandIf-None-Matchheaders - Cache-Control headers: Set appropriately per endpoint
- CDN caching: Static content (logos, archived materials) cached at edge
- API caching: Caffeine-backed for frequently accessed data (15-minute TTL)
Pagination
All list endpoints use page-based pagination (NOT offset/cursor):
page- Page index (default: 0)limit- Items per page (default: 20, max: 100)sort- JSON:API-style sort expression (ADR-013 Β§3)filter- JSON:API-style filter expression (ADR-013 Β§3)
Response wraps data in a PaginatedResponse with PaginationMetadata:
{
"data": [...],
"pagination": {
"page": 0,
"limit": 20,
"totalItems": 150,
"totalPages": 8,
"hasNext": true,
"hasPrev": false
}
}
Field Selection
Large object endpoints support field selection via fields query parameter:
fields=id,title,status- Return only specified fields- Reduces payload size and improves performance
- Nested field selection:
fields=id,venue.name,venue.city
Internationalization
All text responses support English (en) and German (de) via Accept-Language header:
- Error messages localized based on locale
- Email templates use recipientβs preferred language
- Date/time formatting follows locale conventions