Fuscorrespondence API Detailed Design
Design Documents
Last updated August 2, 2025
Fuscorrespondence API Detailed Design
Overview
The Fuscorrespondence API powers a digital "slow mail" app, enabling authenticated users to create, send, and receive virtual letters with delivery delays based on rea## Error States
- 401: Unauthenticated (invalid/missing JWT token)
- 403: Forbidden (trying to access another user's resources)
- 404: Resource not found (letter, mailbox, or FuscAddress not found)
- 422: Validation error (invalid FuscAddress when sending)
- 400: Bad request (malformed input or missing required fields)
- 500: Internal server error
Implementation Status
✅ Completed Features:
- User mailbox creation and management
- Draft letter creation and auto-save
- Letter sending with distance-based delivery delays
- FuscAddress validation
- Letter status tracking and automatic transitions
- JWT authentication middleware
- Frontend React application with all major pages
🚧 Pending Features:
- Delete draft functionality (API endpoint and frontend integration)
- Enhanced error handling and user feedback
- Comprehensive testing suitence calculations. All endpoints are authenticated via Fuscauth using JWT tokens.
Base URL: https://6nnj8no7u0.execute-api.us-east-1.amazonaws.com/dev/fuscorrespondence
Stack Summary
- Framework: Node.js + Express + TypeScript + Serverless Framework
- Deployment: AWS Lambda with API Gateway
- Database: DynamoDB (using existing monotable structure)
- Authentication: JWT Bearer tokens
- Endpoint Areas:
- Mailbox management
- Letter composition and management
- Letter sending and delivery
- Address validation
Endpoints
Authentication
All endpoints require an Authorization: Bearer <token>
header. Tokens are obtained through the Fuscauth service.
Mailbox
Create/Update Mailbox
- POST
/mailbox
- Body:json
{ "location": { "latitude": 37.421, "longitude": -122.084 }, // user current location "fuscaddress": "123 Mockingbird Lane, Springfield" }
- Logical outline
- Validates parameters
- gets user’s mailbox from db (if any)
- if mailbox exists
- updates location and fuscaddress in object
- else
- creates uuid
- creates mailbox object
- saves object to db
- Returns:
- 200 + new/updated mailbox record
- 400 if location or fuscaddress parameters missing
Get My Mailbox
- GET
/mailbox
- Logical outline
- get user’s mailbox from db
- returns object
- Returns: 200 + mailbox object
Letter Endpoints
Create Draft
- POST
/letters
- Body:json
{ "content": "<html/markdown for styled letter>", "status": "Draft" }
- Logical outline
- Creates letter object in draft state
- Creates uuid for letter
- Populates content and uuid
- Saves object to DB
- Returns: 201 + letter record with created uuid
Update Draft
- PATCH
/letters/{letterId}
- Body:
json
{
"content": "<html/markdown for styled letter>"
}
- Returns 201 + success message (no updated content)
Send Letter
- POST
/letters/{letterId}/send
- Body:json
{ "recipientFuscaddress": "456 Oak Avenue, Shelbyville" }
- Logical outline:
- Validates recipient FuscAddress exists in the system
- Calculates delivery delay based on real GPS distance between sender and recipient
- Uses Haversine Formula to calculate distance between GPS coordinates
- Delivery time calculation:
deliveryTime = 1 hour + (distance_km / 100) hours
- Minimum delivery time: 1 hour (even for same location)
- Updates letter record: status changes to
InTransit
, setssentDate
anddeliveryDate
- Letter status will automatically update to
Delivered
when delivery time is reached
- Returns:
- 200 + updated letter with delivery ETA
- 404 if recipient postal address does not exist
List My Letters
- GET
/letters?status={Draft|InTransit|Delivered|Read}&sent={true|false}
- Query Parameters:
status
: Filter by letter status (optional, defaults to all)sent
:true
for sent letters,false
for received letters (optional, defaults to all)
- Returns: Array of letters (content included for full letter objects)
Get Letter
- GET
/letters/{letterId}
- Returns: Complete letter object with full content
Address Validation
Validate Address
- POST
/address/validate
- Body:json
{ "fuscaddress": "456 Oak Avenue, Shelbyville" }
- Returns
- 200 + { valid: true/false }
- 400 if fuscaddress parameter missing
Database
Entities
Entity | Description |
---|---|
Mailbox | Stores Fuscaddress information for a user |
Letter | The actual message send between users |
Mailbox
json
{
"pk": "USER#<userId>",
"sk": "MAILBOX#<mailboxId>",
"fuscaddress": "string",
"location": {"latitude": float, "longitude": float},
"createdAt": timestamp,
"updatedAt": timestamp
}
Field | Description |
---|---|
PK | string containing the user id that owns that mailbox |
SK | string containing the system generated mailbox id |
Fuscaddress | String with the visible name of the address |
Location | Lat/Long value of user’s location at the time the mailbox was created |
Letter
json
{
"pk": "LETTER#<letterId>",
"sk": "LETTER#<letterId>",
"senderUserId": "string",
"senderMailboxId": "<mailboxId>",
"recipientMailboxId": "<mailboxId>",
"status": "Draft|InTransit|Delivered|Read",
"content": "string",
"recipientName": "string (optional)",
"senderName": "string (optional)",
"sentDate": "ISO timestamp",
"deliveryDate": "ISO timestamp",
"createdAt": "ISO timestamp",
"updatedAt": "ISO timestamp"
}
Field | Description |
---|---|
pk/sk | Both use LETTER#{letterId} for the letter entity |
senderUserId | User ID of the letter sender |
senderMailboxId/recipientMailboxId | Mailbox IDs for sender and recipient |
status | Current letter status with automatic transitions |
content | Letter content (plain text) |
recipientName | How the sender addresses the recipient (optional) |
senderName | How the sender signs their letter (optional) |
sentDate | When letter was sent (status changed to InTransit) |
deliveryDate | Calculated delivery time based on distance |
Key Logic / Edge Cases
- Address Validation: FuscAddress must exist exactly as stored in a mailbox
- Delivery Delay Calculation:
- Uses Haversine formula for GPS distance calculation
- Formula:
deliveryTime = 1 hour + (distance_km / 100) hours
- Minimum delivery time: 1 hour (even for same location)
- Status Transitions: Automatic updates based on delivery time calculations
Draft
→InTransit
(when sent)InTransit
→Delivered
(when delivery time reached)Delivered
→Read
(when recipient opens letter)
- Draft auto-save: Frontend auto-saves drafts every 3 seconds using PATCH
- Letter Access: Recipients can only read letters after delivery time
Error States
- 401: Unauthenticated (invalid/missing token)
- 403: Not your resource (trying to access another user’s letter)
- 404: Letter or mailbox not found
- 422: Invalid address (sending letter to non-existent address)
- 400: Bad request (malformed input)