Add comprehensive .gitignore
This commit is contained in:
939
docs/maternal-app-api-spec.md
Normal file
939
docs/maternal-app-api-spec.md
Normal file
@@ -0,0 +1,939 @@
|
||||
# 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
|
||||
});
|
||||
};
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user