Files
maternal-app/docs/maternal-app-api-spec.md
2025-10-01 19:01:52 +00:00

939 lines
18 KiB
Markdown

# 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
});
};
}
```