Pydantic Schemas Used in Securo API for Validation: Complete Reference Guide
The Securo API uses over 20 purpose-built Pydantic schemas located in backend/app/schemas/ to validate requests and serialize responses across user management, transactions, workspaces, assets, and financial data domains.
Securo Finance's backend architecture relies extensively on Pydantic for runtime data validation and API documentation generation. Every incoming request body passes through a strictly typed schema before reaching business logic, ensuring type safety and automatic OpenAPI schema generation. This article maps every validation schema in the codebase, tracing their file locations, dependencies, and usage patterns in FastAPI routes.
Core Schema Architecture
The Securo project organizes Pydantic models hierarchically under backend/app/schemas/. Each domain receives its own module, following single-responsibility principles for maintainable validation logic.
backend/app/schemas/
├── __init__.py
├── workspace.py
├── user.py
├── two_factor.py
├── passkey.py
├── account.py
├── transaction.py
├── transaction_split.py
├── transaction_calendar.py
├── recurring_transaction.py
├── transaction_group_settlement.py
├── payee.py
├── category.py
├── category_group.py
├── budget.py
├── goal.py
├── asset.py
├── asset_group.py
├── asset_import.py
├── bank_connection.py
├── attachment.py
├── export.py
├── import_log.py
├── admin.py
├── rule.py
├── report.py
├── dashboard.py
└── collection.py
All schemas inherit from pydantic.BaseModel and leverage Pydantic v2 features including field_validator, model_validator, and ConfigDict for strict type enforcement.
User Authentication & Security Schemas
Securo handles sensitive financial data, requiring robust validation for authentication flows, multi-factor authentication, and modern passkey credentials.
User Schema (backend/app/schemas/user.py)
The foundational identity model validates user registration, profile updates, and public user representations. It typically includes:
email:EmailStrwith DNS validationpassword:SecretStrfor write operations, excluded from responsesfull_name: constrainedstrwith length limitsis_active,is_verified: boolean flags for account state
# backend/app/schemas/user.py
from pydantic import BaseModel, EmailStr, Field, SecretStr
class UserBase(BaseModel):
email: EmailStr
full_name: str = Field(..., min_length=1, max_length=128)
class UserCreate(UserBase):
password: SecretStr = Field(..., min_length=12)
class User(UserBase):
id: int
is_active: bool
is_verified: bool
model_config = {"from_attributes": True}
Two-Factor Authentication (backend/app/schemas/two_factor.py)
Validates TOTP enrollment, backup code generation, and verification requests. Critical fields include totp_secret, backup_codes, and verified_at timestamps.
Passkey Schema (backend/app/schemas/passkey.py)
Supports WebAuthn credential registration and authentication with fields for credential_id, public_key, sign_count, and device attestation metadata.
Workspace & Account Management Schemas
Financial applications require strict isolation between organizational boundaries. Securo implements this through workspace-scoped validation.
Workspace Schema (backend/app/schemas/workspace.py)
Validates organizational creation, billing tier selection, and member invitation flows. Key fields:
name: unique workspace identifierslug: URL-safe normalized namebilling_tier: enum-constrained subscription levelfiscal_year_start: month-day pair for reporting cycles
Account Schema (backend/app/schemas/account.py)
Represents financial accounts within a workspace, validating:
institution_name: connected bank or manual entryaccount_type: checking, savings, credit, investment enumcurrency_code: ISO 4217 three-letter code with custom validatorinitial_balance:Decimalprecision for monetary valuesconnection_id: optional foreign key toBankConnection
Transaction Validation Schemas
The transaction domain contains the most complex validation logic, with six specialized schemas handling different financial record types.
Base Transaction Schema (backend/app/schemas/transaction.py)
Core model for single financial transactions with extensive custom validators:
# backend/app/schemas/transaction.py
from datetime import datetime
from decimal import Decimal
from pydantic import BaseModel, field_validator, Field
class Transaction(BaseModel):
amount: Decimal = Field(..., decimal_places=2, max_digits=15)
currency: str = Field(..., min_length=3, max_length=3)
description: str = Field(..., max_length=512)
posted_at: datetime
category_id: int | None = None
payee_id: int | None = None
@field_validator("currency")
@classmethod
def validate_supported_currency(cls, v: str) -> str:
supported = {"USD", "BRL", "EUR", "GBP", "JPY", "CAD"}
if v.upper() not in supported:
raise ValueError(f"Currency {v} not supported. Use: {', '.join(sorted(supported))}")
return v.upper()
@field_validator("amount")
@classmethod
def validate_non_zero(cls, v: Decimal) -> Decimal:
if v == 0:
raise ValueError("Transaction amount cannot be zero")
return v
Transaction Split Schema (backend/app/schemas/transaction_split.py)
Validates division of single transactions across multiple categories or payees. Enforces that split percentages sum to 100% or split amounts sum to parent transaction total via model_validator.
Transaction Calendar Schema (backend/app/schemas/transaction_calendar.py)
Schedules future or recurring transactions with fields for frequency (daily, weekly, monthly, yearly), interval multiplier, occurrences limit, and end_date termination.
Recurring Transaction Schema (backend/app/schemas/recurring_transaction.py)
Similar to calendar schema but for automatically generated transactions, including next_occurrence prediction and last_generated tracking.
Transaction Group Settlement (backend/app/schemas/transaction_group_settlement.py)
Validates multi-party settlement workflows for shared expenses, tracking payer_splits, ower_splits, and settlement status.
Classification & Budgeting Schemas
Financial organization requires structured categorization and goal tracking.
Category & CategoryGroup Schemas (backend/app/schemas/category.py, backend/app/schemas/category_group.py)
- Category: Individual classification with
name,color,icon,parent_idfor hierarchies, andis_systemflag for protected categories - CategoryGroup: Container for related categories with
sort_orderand budget rollup configuration
Budget Schema (backend/app/schemas/budget.py)
Validates spending limits with period-aware validation:
amount: periodic spending ceilingperiod: enum ofweekly,monthly,quarterly,yearlycategory_idsorcategory_group_ids: scope specificationrollover_enabled: boolean for unused amount carryover
Goal Schema (backend/app/schemas/goal.py)
Tracks financial targets with target_amount, current_amount, deadline, and goal_type (savings, debt reduction, purchase target). Includes progress calculation validators.
Asset Management Schemas
Investment and physical asset tracking uses nested validation for complex portfolio structures.
Asset Schema (backend/app/schemas/asset.py)
Validates individual holdings:
asset_class: equity, fixed_income, real_estate, commodity, crypto enumsymbol: ticker or identifier with format validation per asset classquantity:Decimalwith precision appropriate to asset typecost_basis: purchase price tracking for gain/loss calculationcurrent_price: optional live price withlast_price_updatetimestamp
AssetGroup Schema (backend/app/schemas/asset_group.py)
Portfolio-level validation with allocation_targets dictionary mapping asset classes to target percentages, enforced by model_validator summing to 100%.
AssetImport Schema (backend/app/schemas/asset_import.py)
Validates bulk import operations from CSV brokerage files, including column mapping validation and duplicate detection rules.
Financial Connection Schemas
Third-party integrations require specialized validation for credentials and connection state.
BankConnection Schema (backend/app/schemas/bank_connection.py)
Validates open banking and screen-scraping connections:
provider_id: supported institution identifierconnection_type:oauth,credentials,api_keyenumcredentials:SecretStrfields conditionally required by typesync_frequency:timedeltawith minimum boundslast_sync_at,last_sync_status: operational metadata
Auxiliary Schemas
Supporting functionality validates file attachments, data exports, and administrative operations.
Attachment Schema (backend/app/schemas/attachment.py)
Validates file metadata with content-type restriction and size limits:
filename: sanitized string with extension validationcontent_type: allowlist ofimage/*,application/pdf,text/csvsize_bytes: maximum 10MB defaultchecksum: SHA-256 for integrity verification
Export Schema (backend/app/schemas/export.py)
Validates data export requests with format (CSV, JSON, OFX, QIF), date_range bounds, included_accounts, and include_attachments flag.
ImportLog Schema (backend/app/schemas/import_log.py)
Tracks asynchronous import job status with source_type, file_checksum, records_processed, records_failed, and error_details array.
Admin Schema (backend/app/schemas/admin.py)
Validates privileged operations with enhanced secret handling. Uses SecretStr for sensitive configuration and includes audit_reason fields for compliance logging.
Rule Schema (backend/app/schemas/rule.py)
Validates automated transaction categorization with conditions (field, operator, value triples) and actions (set_category, set_payee, flag_for_review).
Report, Dashboard, Collection Schemas
- Report: Scheduled or on-demand analytics with
metric_selections,grouping_dimensions,filter_criteria - Dashboard: Widget layout validation with position coordinates and refresh intervals
- Collection: Saved filter combinations for quick data access
Integration with FastAPI Routes
Pydantic schemas integrate directly into route definitions for automatic validation and documentation:
# backend/app/api/payees.py
from fastapi import APIRouter, Depends
from app.schemas.payee import Payee, PayeeCreate
from app.api.dependencies import get_current_user, get_db_session
router = APIRouter(prefix="/payees", tags=["payees"])
@router.post("/", response_model=Payee, status_code=201)
async def create_payee(
payee: PayeeCreate, # ← Pydantic validation applied automatically
session=Depends(get_db_session),
current_user=Depends(get_current_user)
):
"""Create a new payee with validated tax ID and source information."""
return await payee_service.create(session, current_user.workspace_id, payee)
The PayeeCreate schema validates incoming JSON, returning 422 Unprocessable Entity for type mismatches or validation failures before the service layer executes.
Configuration via Pydantic-Settings
Beyond request validation, Securo uses pydantic-settings for environment-based configuration in backend/app/core/config.py:
# backend/app/core/config.py
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import SecretStr, PostgresDsn, RedisDsn
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
DATABASE_URL: PostgresDsn
REDIS_URL: RedisDsn
SECRET_KEY: SecretStr
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
SUPPORTED_CURRENCIES: list[str] = ["USD", "BRL", "EUR"]
@property
def async_database_url(self) -> str:
return str(self.DATABASE_URL).replace("postgresql://", "postgresql+asyncpg://")
settings = Settings()
This pattern separates runtime configuration (secrets, URLs) from request validation schemas while maintaining Pydantic's validation guarantees.
Summary
- 20+ specialized schemas in
backend/app/schemas/cover all API validation needs - Hierarchical organization by domain (user, transaction, asset, etc.) enables maintainable code
- Pydantic v2 features employed:
field_validator,model_validator,ConfigDict,SecretStr - Custom validators enforce business rules like currency support, split totaling, and allocation balancing
- FastAPI integration provides automatic request validation, serialization, and OpenAPI documentation
- Pydantic-Settings handles environment configuration with identical validation rigor
Frequently Asked Questions
How does Securo ensure currency values are validated correctly?
The base Transaction schema in backend/app/schemas/transaction.py implements a @field_validator("currency") that checks against a supported set of ISO 4217 codes. Invalid currencies trigger a descriptive error listing all supported options. Monetary amounts use Decimal with explicit decimal_places=2 to prevent floating-point errors.
What prevents split transactions from having invalid totals?
The TransactionSplit schema in backend/app/schemas/transaction_split.py uses a @model_validator(mode="after") that executes after individual field validation. This validator sums all split amounts or percentages and compares against the parent transaction total, raising ValueError if the difference exceeds a configurable epsilon.
Are password hashes exposed in API responses?
No. The User schema hierarchy separates UserCreate (input, contains SecretStr password) from User (response model). The response model never includes password fields. Additionally, SecretStr automatically masks values in logs and serialization, and model_config = {"from_attributes": True} ensures proper ORM mapping without accidental field leakage.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →