# API Specification Document - Maternal Organization App ## API Architecture Overview ### Base Configuration - **Base URL**: `https://api.{domain}/api/v1` - **GraphQL Endpoint**: `https://api.{domain}/graphql` - **WebSocket**: `wss://api.{domain}/ws` - **API Style**: Hybrid (REST for CRUD, GraphQL for complex queries) - **Versioning**: URL path versioning (`/api/v1/`) - **Rate Limiting**: 100 requests/minute per user - **Pagination**: Cursor-based with consistent structure ### Standard Headers ```http Content-Type: application/json Accept: application/json Accept-Language: en-US,en;q=0.9 X-Client-Version: 1.0.0 X-Device-ID: uuid-device-fingerprint X-Timezone: America/New_York Authorization: Bearer {access_token} X-Refresh-Token: {refresh_token} ``` ### Device Fingerprinting ```json { "deviceId": "uuid", "platform": "ios|android", "model": "iPhone14,2", "osVersion": "16.5", "appVersion": "1.0.0", "pushToken": "fcm_or_apns_token" } ``` --- ## Authentication Endpoints ### POST `/api/v1/auth/register` Create new user account with family setup. **Request Body:** ```json { "email": "user@example.com", "password": "SecurePass123!", "phone": "+1234567890", "name": "Jane Doe", "locale": "en-US", "timezone": "America/New_York", "deviceInfo": { "deviceId": "uuid", "platform": "ios", "model": "iPhone14,2", "osVersion": "16.5" } } ``` **Response 201:** ```json { "success": true, "data": { "user": { "id": "usr_2n4k8m9p", "email": "user@example.com", "name": "Jane Doe", "locale": "en-US", "emailVerified": false }, "family": { "id": "fam_7h3j9k2m", "shareCode": "ABC123", "role": "parent" }, "tokens": { "accessToken": "eyJhbGc...", "refreshToken": "eyJhbGc...", "expiresIn": 3600 }, "deviceRegistered": true } } ``` ### POST `/api/v1/auth/login` Authenticate existing user with device registration. **Request Body:** ```json { "email": "user@example.com", "password": "SecurePass123!", "deviceInfo": { "deviceId": "uuid", "platform": "ios", "model": "iPhone14,2", "osVersion": "16.5" } } ``` **Response 200:** ```json { "success": true, "data": { "user": { "id": "usr_2n4k8m9p", "email": "user@example.com", "families": ["fam_7h3j9k2m"] }, "tokens": { "accessToken": "eyJhbGc...", "refreshToken": "eyJhbGc...", "expiresIn": 3600 }, "requiresMFA": false, "deviceTrusted": true } } ``` ### POST `/api/v1/auth/refresh` Refresh access token using refresh token. **Request Body:** ```json { "refreshToken": "eyJhbGc...", "deviceId": "uuid" } ``` **Response 200:** ```json { "success": true, "data": { "accessToken": "eyJhbGc...", "refreshToken": "eyJhbGc...", "expiresIn": 3600 } } ``` ### POST `/api/v1/auth/logout` Logout and revoke tokens for specific device. **Request Body:** ```json { "deviceId": "uuid", "allDevices": false } ``` **Response 200:** ```json { "success": true, "message": "Successfully logged out" } ``` --- ## Family Management Endpoints ### POST `/api/v1/families/invite` Generate invitation for family member. **Request Body:** ```json { "email": "partner@example.com", "role": "parent|caregiver|viewer", "permissions": { "canAddChildren": true, "canEditChildren": true, "canLogActivities": true, "canViewReports": true }, "message": "Join our family on the app!" } ``` **Response 201:** ```json { "success": true, "data": { "invitationId": "inv_8k3m9n2p", "shareCode": "XYZ789", "expiresAt": "2024-01-15T00:00:00Z", "invitationUrl": "app://join/XYZ789" } } ``` ### POST `/api/v1/families/join` Join family using share code. **Request Body:** ```json { "shareCode": "XYZ789" } ``` **Response 200:** ```json { "success": true, "data": { "familyId": "fam_7h3j9k2m", "familyName": "The Doe Family", "role": "parent", "members": [ { "id": "usr_2n4k8m9p", "name": "Jane Doe", "role": "parent" } ], "children": [] } } ``` ### GET `/api/v1/families/{familyId}/members` Get all family members with their permissions. **Response 200:** ```json { "success": true, "data": { "members": [ { "id": "usr_2n4k8m9p", "name": "Jane Doe", "email": "jane@example.com", "role": "parent", "permissions": { "canAddChildren": true, "canEditChildren": true, "canLogActivities": true, "canViewReports": true }, "joinedAt": "2024-01-01T00:00:00Z", "lastActive": "2024-01-10T15:30:00Z" } ] } } ``` --- ## Children Management Endpoints ### POST `/api/v1/children` Add a new child to the family. **Request Body:** ```json { "familyId": "fam_7h3j9k2m", "name": "Emma", "birthDate": "2023-06-15", "gender": "female", "bloodType": "O+", "allergies": ["peanuts", "dairy"], "medicalConditions": ["eczema"], "pediatrician": { "name": "Dr. Smith", "phone": "+1234567890" }, "photo": "base64_encoded_image" } ``` **Response 201:** ```json { "success": true, "data": { "id": "chd_9m2k4n8p", "familyId": "fam_7h3j9k2m", "name": "Emma", "birthDate": "2023-06-15", "ageInMonths": 7, "developmentalStage": "infant", "photoUrl": "https://storage.api/photos/chd_9m2k4n8p.jpg" } } ``` ### GET `/api/v1/children/{childId}` Get child details with calculated metrics. **Response 200:** ```json { "success": true, "data": { "id": "chd_9m2k4n8p", "name": "Emma", "birthDate": "2023-06-15", "ageInMonths": 7, "developmentalStage": "infant", "currentWeight": { "value": 8.2, "unit": "kg", "percentile": 75, "recordedAt": "2024-01-10T10:00:00Z" }, "currentHeight": { "value": 68, "unit": "cm", "percentile": 80, "recordedAt": "2024-01-10T10:00:00Z" }, "todaySummary": { "feedings": 5, "sleepHours": 14.5, "diapers": 6, "lastFeedingAt": "2024-01-10T14:30:00Z", "lastSleepAt": "2024-01-10T13:00:00Z" } } } ``` --- ## Activity Tracking Endpoints (REST) ### POST `/api/v1/activities/feeding` Log a feeding activity. **Request Body:** ```json { "childId": "chd_9m2k4n8p", "type": "breast|bottle|solid", "startTime": "2024-01-10T14:30:00Z", "endTime": "2024-01-10T14:45:00Z", "details": { "breastSide": "left|right|both", "amount": 120, "unit": "ml|oz", "foodType": "formula|breastmilk|puree" }, "notes": "Good feeding session", "mood": "happy|fussy|sleepy" } ``` **Response 201:** ```json { "success": true, "data": { "id": "act_3k9n2m4p", "childId": "chd_9m2k4n8p", "type": "feeding", "timestamp": "2024-01-10T14:30:00Z", "duration": 15, "createdBy": "usr_2n4k8m9p", "syncedToFamily": true } } ``` ### POST `/api/v1/activities/sleep` Log sleep activity. **Request Body:** ```json { "childId": "chd_9m2k4n8p", "startTime": "2024-01-10T13:00:00Z", "endTime": "2024-01-10T14:30:00Z", "type": "nap|night", "location": "crib|stroller|car|bed", "quality": "good|restless|interrupted", "notes": "Went down easily" } ``` ### POST `/api/v1/activities/diaper` Log diaper change. **Request Body:** ```json { "childId": "chd_9m2k4n8p", "timestamp": "2024-01-10T15:00:00Z", "type": "wet|dirty|both", "consistency": "normal|loose|hard", "color": "normal|green|yellow", "hasRash": false, "notes": "Applied diaper cream" } ``` ### GET `/api/v1/activities` Get activities with cursor pagination. **Query Parameters:** - `childId`: Filter by child (required) - `type`: Filter by activity type - `startDate`: ISO date string - `endDate`: ISO date string - `cursor`: Pagination cursor - `limit`: Items per page (default: 20, max: 100) **Response 200:** ```json { "success": true, "data": { "activities": [ { "id": "act_3k9n2m4p", "childId": "chd_9m2k4n8p", "type": "feeding", "timestamp": "2024-01-10T14:30:00Z", "details": {}, "createdBy": "usr_2n4k8m9p" } ], "cursor": { "next": "eyJpZCI6ImFjdF8za...", "hasMore": true, "total": 150 } } } ``` --- ## AI Assistant Endpoints ### POST `/api/v1/ai/chat` Send message to AI assistant. **Request Body:** ```json { "message": "Why won't my baby sleep?", "childId": "chd_9m2k4n8p", "conversationId": "conv_8n2k4m9p", "context": { "includeRecentActivities": true, "includeSleepPatterns": true, "includeDevelopmentalInfo": true }, "locale": "en-US" } ``` **Response 200:** ```json { "success": true, "data": { "conversationId": "conv_8n2k4m9p", "messageId": "msg_7k3n9m2p", "response": "Based on Emma's recent sleep patterns...", "suggestions": [ "Try starting bedtime routine 15 minutes earlier", "Check room temperature (ideal: 68-72°F)" ], "relatedArticles": [ { "title": "7-Month Sleep Regression", "url": "/resources/sleep-regression-7-months" } ], "confidenceScore": 0.92 } } ``` ### POST `/api/v1/ai/voice` Process voice command. **Request Body (multipart/form-data):** ``` audio: [audio file - wav/mp3] childId: chd_9m2k4n8p locale: en-US ``` **Response 200:** ```json { "success": true, "data": { "transcription": "Baby fed 4 ounces at 3pm", "interpretation": { "action": "log_feeding", "childId": "chd_9m2k4n8p", "parameters": { "amount": 4, "unit": "oz", "time": "15:00" } }, "executed": true, "activityId": "act_9k2m4n3p" } } ``` --- ## Analytics & Insights Endpoints ### GET `/api/v1/insights/{childId}/patterns` Get AI-detected patterns for a child. **Response 200:** ```json { "success": true, "data": { "sleepPatterns": { "averageNightSleep": 10.5, "averageDaySleep": 3.5, "optimalBedtime": "19:30", "wakeWindows": [90, 120, 150, 180], "trend": "improving", "insights": [ "Emma sleeps 45 minutes longer when put down before 7:30 PM", "Morning wake time is consistently between 6:30-7:00 AM" ] }, "feedingPatterns": { "averageIntake": 28, "feedingIntervals": [2.5, 3, 3, 4], "preferredSide": "left", "insights": [ "Feeding intervals increasing - may be ready for longer stretches" ] } } } ``` ### GET `/api/v1/insights/{childId}/predictions` Get predictive suggestions. **Response 200:** ```json { "success": true, "data": { "nextNapTime": { "predicted": "2024-01-10T16:30:00Z", "confidence": 0.85, "wakeWindow": 120 }, "nextFeedingTime": { "predicted": "2024-01-10T17:30:00Z", "confidence": 0.78 }, "growthSpurt": { "likelihood": 0.72, "expectedIn": "5-7 days", "symptoms": ["increased feeding", "fussiness", "disrupted sleep"] } } } ``` --- ## GraphQL Queries for Complex Data ### GraphQL Endpoint `POST https://api.{domain}/graphql` ### Family Dashboard Query ```graphql query FamilyDashboard($familyId: ID!, $date: Date!) { family(id: $familyId) { id name children { id name age todaySummary(date: $date) { feedings { count totalAmount lastAt } sleep { totalHours naps nightSleep currentStatus } diapers { count lastAt } } upcomingEvents { type scheduledFor description } aiInsights { message priority actionable } } members { id name lastActive recentActivities(limit: 5) { type childName timestamp } } } } ``` ### Weekly Report Query ```graphql query WeeklyReport($childId: ID!, $startDate: Date!, $endDate: Date!) { child(id: $childId) { weeklyReport(startDate: $startDate, endDate: $endDate) { sleep { dailyAverages { date nightHours napHours totalHours } patterns { consistentBedtime averageWakeTime longestStretch } } feeding { dailyTotals { date numberOfFeedings totalVolume } trends { direction averageInterval } } growth { measurements { date weight height percentiles } } milestones { achieved { name achievedAt } upcoming { name expectedBy } } } } } ``` --- ## WebSocket Events ### Connection ```javascript // Client connects with auth ws.connect('wss://api.{domain}/ws', { headers: { 'Authorization': 'Bearer {access_token}', 'X-Device-ID': 'uuid' } }); ``` ### Family Room Events ```javascript // Join family room ws.emit('join-family', { familyId: 'fam_7h3j9k2m' }); // Activity logged by family member ws.on('activity-logged', { activityId: 'act_3k9n2m4p', childId: 'chd_9m2k4n8p', type: 'feeding', loggedBy: 'usr_2n4k8m9p', timestamp: '2024-01-10T14:30:00Z' }); // Real-time timer sync ws.on('timer-started', { timerId: 'tmr_8k3m9n2p', type: 'feeding', childId: 'chd_9m2k4n8p', startedBy: 'usr_2n4k8m9p', startTime: '2024-01-10T14:30:00Z' }); // AI insight generated ws.on('insight-available', { childId: 'chd_9m2k4n8p', type: 'pattern_detected', message: 'New sleep pattern identified', priority: 'medium' }); ``` --- ## Error Responses ### Standard Error Format ```json { "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Invalid input data", "details": { "field": "email", "reason": "Invalid email format" }, "timestamp": "2024-01-10T15:30:00Z", "traceId": "trace_8k3m9n2p" } } ``` ### Error Codes | Code | HTTP Status | Description | |------|------------|-------------| | `UNAUTHORIZED` | 401 | Invalid or expired token | | `FORBIDDEN` | 403 | Insufficient permissions | | `NOT_FOUND` | 404 | Resource not found | | `VALIDATION_ERROR` | 400 | Invalid input data | | `RATE_LIMITED` | 429 | Too many requests | | `FAMILY_FULL` | 400 | Family member limit reached | | `CHILD_LIMIT` | 400 | Free tier child limit reached | | `AI_QUOTA_EXCEEDED` | 429 | AI query limit reached | | `SYNC_CONFLICT` | 409 | Data sync conflict | | `SERVER_ERROR` | 500 | Internal server error | ### Rate Limit Headers ```http X-RateLimit-Limit: 100 X-RateLimit-Remaining: 45 X-RateLimit-Reset: 1704903000 Retry-After: 3600 ``` --- ## Localization ### Supported Locales - `en-US` - English (United States) - `es-ES` - Spanish (Spain) - `es-MX` - Spanish (Mexico) - `fr-FR` - French (France) - `fr-CA` - French (Canada) - `pt-BR` - Portuguese (Brazil) - `zh-CN` - Chinese (Simplified) ### Locale-Specific Responses All error messages, AI responses, and notifications are returned in the user's selected locale based on the `Accept-Language` header or user profile setting. ### Date/Time Formatting Dates are returned in ISO 8601 format but should be displayed according to user's locale: - US: MM/DD/YYYY, 12-hour clock - EU: DD/MM/YYYY, 24-hour clock - Time zones always included in responses ### Measurement Units ```json { "measurement": { "value": 8.2, "unit": "kg", "display": "8.2 kg", "imperial": { "value": 18.08, "unit": "lbs", "display": "18 lbs 1 oz" } } } ``` --- ## Security Considerations ### Authentication Flow 1. User provides credentials + device fingerprint 2. Server validates and issues access token (1 hour) + refresh token (30 days) 3. Device fingerprint stored and validated on each request 4. Refresh token rotation on use 5. All tokens revoked on suspicious activity ### Data Encryption - All API communication over HTTPS/TLS 1.3 - Sensitive fields encrypted at rest (AES-256) - PII data anonymized in logs - No sensitive data in URL parameters ### COPPA/GDPR Compliance - Parental consent required for child profiles - Data minimization enforced - Right to deletion implemented - Data portability via export endpoints - Audit logs for all data access ### Request Signing (Optional Enhanced Security) ```http X-Signature: HMAC-SHA256(request-body + timestamp + nonce) X-Timestamp: 1704903000 X-Nonce: unique-request-id ``` --- ## Testing Endpoints ### Health Check `GET /api/v1/health` **Response 200:** ```json { "status": "healthy", "version": "1.0.0", "timestamp": "2024-01-10T15:30:00Z", "services": { "database": "connected", "redis": "connected", "ai": "operational" } } ``` ### Test Notifications `POST /api/v1/test/notification` **Request Body:** ```json { "type": "test", "deviceId": "uuid" } ``` --- ## SDK Usage Examples ### JavaScript/TypeScript ```typescript import { MaternalAPI } from '@maternal/sdk'; const api = new MaternalAPI({ baseUrl: 'https://api.maternal.app', version: 'v1' }); // Authentication const { tokens, user } = await api.auth.login({ email: 'user@example.com', password: 'password', deviceInfo: getDeviceInfo() }); // Set tokens for subsequent requests api.setTokens(tokens); // Log activity const activity = await api.activities.logFeeding({ childId: 'chd_9m2k4n8p', type: 'bottle', amount: 120, unit: 'ml' }); // Subscribe to real-time updates api.websocket.on('activity-logged', (data) => { console.log('New activity:', data); }); ``` ### React Native ```typescript import { useMaternalAPI } from '@maternal/react-native'; function FeedingScreen() { const { logFeeding, isLoading } = useMaternalAPI(); const handleLogFeeding = async () => { await logFeeding({ childId: currentChild.id, type: 'breast', duration: 15 }); }; } ```