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, sets sentDate and deliveryDate
    • 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
    • DraftInTransit (when sent)
    • InTransitDelivered (when delivery time reached)
    • DeliveredRead (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)