Skip to content
ag-tech-groupPublic

About

Backend API for Trove - Personal collection management system for tracking antiques, art, and valuables with REST endpoints and database integration

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

AG Technology Group

Trove API

CI License: Apache 2.0 Python

Personal collection management API for tracking antiques, art, and valuables.

Tech Stack

Component Technology
Framework FastAPI
Database PostgreSQL (async via asyncpg)
ORM SQLAlchemy 2.0
Migrations Alembic
Auth FastAPI-Users (JWT)
Email Resend
Package Manager uv
Containerization Docker / Docker Compose
Testing Pytest (async)
Linting/Formatting Ruff

Requirements

  • Python 3.12+
  • uv
  • Docker & Docker Compose (for local development)

Quick Start

# Clone and enter directory
cd trove-api

# Copy environment file
cp .env.example .env

# Install dependencies
uv sync

# Start PostgreSQL
docker compose up -d db

# Run migrations
uv run alembic upgrade head

# Start the API
uv run uvicorn app.main:app --reload

The API will be available at http://localhost:8000

Running with Docker

# Start everything (API + PostgreSQL)
docker compose up

# Or run in background
docker compose up -d

API Documentation

Once running, visit:

API Endpoints

Auth

Method Endpoint Description
POST /auth/register Create a new account
POST /auth/jwt/login Get JWT access token
POST /auth/jwt/logout Revoke the refresh token family and clear cookies
POST /auth/refresh Exchange the refresh cookie for a new access token
GET /auth/me Current user
PATCH /auth/me Change own settings (preferred_units)
POST /auth/forgot-password Email a password reset link (always 202)
POST /auth/reset-password Consume a reset token and set a new password
POST /auth/request-verify-token Email an address-confirmation link (always 202)
POST /auth/verify Consume a verification token

/auth/forgot-password and /auth/request-verify-token answer 202 whether or not the address has an account, so neither reveals who is registered. Both links land in the frontend (/reset-password, /verify-email), which posts the token back to the endpoint above it. Tokens last one hour.

Verification is offered, not required: nothing in the API checks is_verified, so registering grants immediate access.

Collections

Method Endpoint Auth Description
GET /collections Yes List user's collections
GET /collections/{id} Yes Get collection with item count
POST /collections Yes Create a collection
PATCH /collections/{id} Yes Update a collection
DELETE /collections/{id} Yes Delete a collection

Items

Method Endpoint Auth Description
GET /items Yes List items (supports filters)
GET /items/{id} Yes Get an item by ID
POST /items Yes Create an item
PATCH /items/{id} Yes Update an item
DELETE /items/{id} Yes Delete an item

Item List Filters:

  • collection_id - Filter by collection
  • category - Filter by category
  • search - Search in name, description and reference number

Categories

Method Endpoint Auth Description
GET /categories Yes List suggested + user's categories

Data Model

Collection

  • id - UUID
  • name - String (max 200)
  • description - Text (optional)
  • created_at, updated_at - Timestamps

Item

  • Basic Info: name, description, reference_number, condition, location
  • Acquisition: acquisition_date, acquisition_method, acquisition_price, acquisition_source, acquisition_place
  • Value: estimated_value (the owner's current figure), plus a history of valuations (/items/{id}/valuations)
  • Provenance: artist_maker, origin, date_era
  • Physical: height_cm, width_cm, depth_cm, length_cm, diameter_cm, weight_kg, materials
  • Metadata: created_at, updated_at

Condition Options: excellent, good, fair, poor, unknown

Acquisition Methods: purchase, gift, inheritance, trade, commission, other

Dates that may be imprecise (acquisition_date, a valuation's valued_on) are ISO 8601 at the precision known: 1998, 1998-06 or 1998-06-15. Measurements are stored metric; a user's preferred_units only changes how they are shown.

Database Migrations

# Apply all pending migrations
uv run alembic upgrade head

# Rollback one migration
uv run alembic downgrade -1

# Generate new migration after model changes
uv run alembic revision --autogenerate -m "description"

Testing

Tests use SQLite in-memory for speed and isolation.

# Run all tests
uv run pytest

# Run with verbose output
uv run pytest -v

# Run with coverage
uv run pytest --cov=app

Linting & Formatting

# Check for linting errors
uv run ruff check .

# Format code
uv run ruff format .

Project Structure

trove-api/
├── app/
│   ├── auth/           # FastAPI-Users JWT setup
│   ├── models/         # SQLAlchemy models (User, Collection, Item)
│   ├── routers/        # API route handlers
│   ├── schemas/        # Pydantic request/response schemas
│   ├── config.py       # Settings from environment
│   ├── database.py     # Async SQLAlchemy setup
│   ├── email.py        # Transactional email transport (Resend)
│   ├── email_templates.py  # What those emails say
│   └── main.py         # FastAPI app entry point
├── alembic/
│   ├── versions/       # Migration files
│   └── env.py          # Alembic configuration
├── tests/
│   ├── conftest.py     # Pytest fixtures
│   ├── test_collections.py
│   └── test_items.py
├── .env.example
├── docker-compose.yml
├── Dockerfile
└── pyproject.toml

Environment Variables

Variable Description Default
DATABASE_URL PostgreSQL connection string postgresql+asyncpg://postgres:postgres@localhost:5432/trove_db
SECRET_KEY JWT signing key change-me-in-production
ENVIRONMENT development or production development
RESEND_API_KEY Resend API key. Empty disables sending (see below) (empty)
EMAIL_FROM Sender, RFC 5322 form Trove <noreply@mail.trovebox.io>

Email in development

Leave RESEND_API_KEY empty. Nothing is sent, and the message — including the reset link — is logged to stdout instead, so the whole forgot-password flow can be walked through locally with no Resend account and no real inbox.

That only happens when ENVIRONMENT=development. Anywhere else an empty key logs an error naming the recipient and the subject, and never the link: the link is a working password reset token, and a log is the wrong place to keep one.

License

This project is licensed under the Apache 2.0 License - see the LICENSE file for details.

About

Backend API for Trove - Personal collection management system for tracking antiques, art, and valuables with REST endpoints and database integration

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages