Altaporta Technical Documentation

Last updated: February 12, 2026

Production Access

System Overview

Altaporta is a mobile-first goal and travel planning platform. The iOS app orchestrates user flows for Trips, Goals, Wishes, Tasks, and Social Circles. The backend is a Bun + Hono API that exposes OpenAPI-documented endpoints, handles AI generation, manages subscriptions, and provides real-time SSE updates.

  • Frontend (iOS): SwiftUI app with modular feature screens and a shared design system.
  • Backend API: Hono + Zod OpenAPI route contracts mounted under /api.
  • Database: Drizzle ORM on SQLite (WAL mode + startup migrations).
  • Auth: Better Auth (email/password + Google + Apple + bearer token plugin).
  • AI: OpenAI for itinerary/task/wish intelligence and Replicate for image generation.
  • Storage: S3-compatible object storage (Cloudflare R2 pattern via AWS SDK).
  • Billing: RevenueCat webhooks + subscription state endpoints.
  • Realtime: SSE streams for user, goal, and circle event channels.

Frameworks & Core Technologies

  • Web Documentation Site: Next.js 16 + React 19 + TypeScript + Tailwind CSS 4.
  • Backend Framework: Hono with OpenAPI route contracts via Zod schemas.
  • Runtime: Bun (build and runtime execution).
  • Database Layer: Drizzle ORM with SQLite (WAL mode and startup migrations).
  • Auth Framework: Better Auth with bearer plugin and social providers (Google/Apple).
  • Realtime Transport: Server-Sent Events (SSE) for live user/goal/circle updates.

Important Backend Dependencies

These are key production dependencies used by the API service and feature stack.

hono@hono/zod-openapibetter-authdrizzle-ormhono-rate-limiteropenaireplicate@aws-sdk/client-s3@aws-sdk/s3-request-presignerresendsharpzodqrcode

Deployment Architecture (Hetzner + Cloudflare)

  • Hosting: Backend runs on a Hetzner VPS in Dockerized production.
  • Edge/DNS: Cloudflare manages DNS for api.altaporta.com and can proxy traffic in front of the VPS.
  • Application Container: altaporta-app serves Bun/Hono API on internal port 3000.
  • Data Services: SQLite persistent volume (./data) with Redis sidecar for cache-oriented workloads.
  • Proxy/TLS Layer: Optional Nginx container for SSL termination and additional rate limiting.
  • Ops Sidecars: Database backup, health checks, metrics/log pipelines, and optional watchtower updates.

Traffic Flow

Client (iOS/Web) → Cloudflare (DNS/Proxy) → Hetzner VPS → Nginx (optional) → Bun/Hono API → SQLite/Redis + external services (R2/S3, OpenAI, Replicate, RevenueCat, Resend).

Authentication & Session Lifecycle

  • Protected endpoints expect Authorization: Bearer <token>.
  • Backend middleware validates tokens and attaches sessionUser context for route handlers.
  • If a token is close to expiry (within 7 days), the backend renews session and returns: x-session-token and x-session-expires-at.
  • OTP-sensitive endpoints are rate-limited to 5 requests per 15 minutes per IP.

Data & Domain Model

  • Trips: AI-generated itineraries, tier selection, and cost plans.
  • Goals: Habit and accumulation goals, streaks, daily actions, and progress history.
  • Wishes: Idea capture with AI milestone decomposition and tip completion.
  • Tasks: Date-based planning with classification support and recurrence-aware updates.
  • Circles: Shared progress spaces, invites, comments, likes, and check-ins.
  • Users: Profile, timezone, device tokens, sessions, and account security controls.

Endpoint Catalog

All routes below are relative to https://api.altaporta.com/api.

Auth & Account Access

  • GET /health
  • POST /auth/sign-up
  • POST /auth/sign-in
  • POST /auth/google-signin
  • POST /auth/apple-signin
  • POST /verify-otp
  • POST /resend-otp
  • GET /verification-status/{email}
  • POST /auth/forgot-password
  • POST /auth/verify-reset-code
  • POST /auth/reset-password
  • POST /auth/* (Better Auth passthrough)

Trips

  • POST /v1/generate-trip
  • GET /v1/trips
  • GET /v1/trips/{tripId}
  • POST /v1/trips/{tripId}/select-tier
  • DELETE /v1/trips/{tripId}

Goals & Daily Progress

  • POST /v1/goals
  • GET /v1/goals
  • GET /v1/goals/{goalId}
  • PATCH /v1/goals/{goalId}
  • DELETE /v1/goals/{goalId}
  • GET /v1/goals/daily-status
  • POST /v1/goals/{goalId}/checkin
  • POST /v1/goals/{goalId}/progress
  • GET /v1/goals/{goalId}/actions
  • POST /v1/goals/{goalId}/actions/{actionId}/complete
  • POST /v1/goals/{goalId}/streak/freeze
  • DELETE /v1/goals/{goalId}/streak/freeze
  • POST /v1/trips/{tripId}/create-goal

Tasks

  • GET /v1/tasks
  • GET /v1/tasks/by-date
  • POST /v1/tasks
  • GET /v1/tasks/{taskId}
  • PATCH /v1/tasks/{taskId}
  • DELETE /v1/tasks/{taskId}
  • POST /v1/tasks/classify

Wishes

  • POST /v1/wishes
  • GET /v1/wishes
  • GET /v1/wishes/{wishId}
  • PATCH /v1/wishes/{wishId}
  • DELETE /v1/wishes/{wishId}
  • PATCH /v1/wishes/{wishId}/milestones/{milestoneId}
  • POST /v1/wishes/{wishId}/milestones/{milestoneId}/tips/{tipIndex}/toggle

Circles

  • GET /v1/circles
  • POST /v1/circles
  • GET /v1/circles/{circleId}
  • PATCH /v1/circles/{circleId}
  • DELETE /v1/circles/{circleId}
  • GET /v1/circles/invitations
  • POST /v1/circles/{circleId}/invite
  • POST /v1/circles/{circleId}/accept
  • POST /v1/circles/{circleId}/decline
  • POST /v1/circles/{circleId}/leave
  • DELETE /v1/circles/{circleId}/members/{memberId}
  • GET /v1/circles/{circleId}/goals
  • POST /v1/circles/{circleId}/goals
  • DELETE /v1/circles/{circleId}/goals/{goalId}

Circle Invites, Feed & Check-ins

  • POST /v1/circles/{circleId}/invite-links
  • GET /v1/circles/{circleId}/invite-links
  • DELETE /v1/circles/{circleId}/invite-links/{linkId}
  • GET /v1/circles/{circleId}/invite-links/{linkId}/qr
  • GET /v1/circle-invite/{token}
  • POST /v1/circle-invite/{token}/accept
  • POST /v1/circle-invite/{token}/decline
  • GET /v1/circle-invite/{token}/qr
  • POST /v1/circles/{circleId}/checkin
  • GET /v1/circles/{circleId}/checkins/today
  • GET /v1/circles/{circleId}/checkins/history
  • GET /v1/circles/{circleId}/streak
  • GET /v1/circles/{circleId}/wins
  • PATCH /v1/circles/{circleId}/settings/checkin
  • GET /v1/circles/{circleId}/comments
  • POST /v1/circles/{circleId}/comments
  • POST /v1/circles/{circleId}/comments/{commentId}/like
  • GET /v1/circles/{circleId}/comments/{commentId}/replies
  • DELETE /v1/circles/{circleId}/comments/{commentId}

Goal Collaboration & Social

  • POST /v1/goals/{goalId}/invite-link
  • GET /v1/invite/{token}
  • POST /v1/invite/{token}/accept
  • POST /v1/invite/{token}/decline
  • GET /v1/invite/{token}/qr
  • GET /v1/goals/{goalId}/invite-links
  • DELETE /v1/goals/{goalId}/invite-links/{linkId}
  • GET /v1/goals/{goalId}/invite-links/{linkId}/qr
  • GET /v1/goals/{goalId}/participants
  • POST /v1/goals/{goalId}/leave
  • DELETE /v1/goals/{goalId}/participants/{participantId}
  • PATCH /v1/goals/{goalId}/participants/me/private-mode
  • GET /v1/goals/{goalId}/participants/me/settings
  • PATCH /v1/goals/{goalId}/participants/me/settings
  • GET /v1/goals/{goalId}/comments
  • POST /v1/goals/{goalId}/comments
  • DELETE /v1/goals/{goalId}/comments/{commentId}
  • GET /v1/goals/{goalId}/reactions
  • POST /v1/goals/{goalId}/reactions
  • DELETE /v1/goals/{goalId}/reactions/{reactionId}
  • POST /v1/goals/{goalId}/reactions/toggle

Realtime, Uploads, Devices, Subscription, User Settings, Webhooks

  • GET /v1/sse/events
  • GET /v1/sse/goals/{goalId}
  • GET /v1/sse/circles/{circleId}
  • GET /v1/sse/health
  • GET /v1/sse/missed-updates
  • POST /v1/uploads/presigned-url
  • POST /v1/devices/register
  • POST /v1/devices/unregister
  • GET /v1/subscription/status
  • POST /v1/subscription/activate
  • PATCH /v1/user/timezone
  • GET /v1/user/timezone
  • PATCH /v1/user/profile
  • GET /v1/user/profile
  • PATCH /v1/user/profile-picture
  • POST /v1/user/profile-picture/upload
  • DELETE /v1/user/profile-picture
  • GET /v1/user/sessions
  • DELETE /v1/user/sessions/{sessionId}
  • DELETE /v1/user/sessions
  • POST /v1/user/change-password
  • DELETE /v1/user/account
  • POST /webhooks/revenuecat
  • POST /webhooks/replicate

Request/Response Conventions

  • JSON request/response format across standard API operations.
  • SSE endpoints use text/event-stream with heartbeat pings.
  • Validation errors return 400; auth failures return 401; permission issues return 403; missing resources return 404.
  • Webhook handlers are built to acknowledge reliably and log failures for retry-safe processing.

Typical authenticated request

curl -X GET "https://api.altaporta.com/api/v1/goals" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json"

Operational Notes

  • Swagger UI at /docs is backed by a custom OpenAPI document at /doc-custom with bearer security preconfigured.
  • RevenueCat integration uses webhook-driven state sync and exposes a runtime check endpoint for current entitlement status.
  • Replicate image completion webhook updates trip visuals asynchronously after itinerary generation.
  • Session management includes token rotation support to reduce forced re-login behavior on mobile clients.