How Securo Handles Data Import and Export via API: A Complete Technical Guide

Securo's FastAPI backend implements a three-step import/export workflow—template download, preview validation, and commit—that ensures safe, auditable bulk data operations through dedicated endpoints for transactions and assets.

The Securo platform provides robust data import and export via API capabilities for financial records. Built on FastAPI, its architecture separates read-only validation from destructive writes, giving clients confidence before committing changes. This guide examines the implementation details, source files, and practical usage patterns drawn directly from the securo-finance/securo repository.

Three-Step Import Workflow Design

Securo's data import API follows a consistent pattern across all entity types. The workflow protects production data by forcing explicit preview validation before any database mutation.

Step Endpoint Pattern Purpose Write Safety
Template GET /api/{entity}/import/template Download CSV structure with headers and sample data Read-only
Preview POST /api/{entity}/import/preview Validate payload, return row-level results without persisting Read-only
Commit POST /api/{entity}/import Execute actual insert/update operations inside transaction Writes enabled

This design appears in both backend/app/api/import_transactions.py and backend/app/api/assets.py, ensuring uniform behavior regardless of data type.

Core API Endpoints for Data Import

Transaction Import Endpoints

The transaction router in backend/app/api/import_transactions.py exposes the full import surface:


# Conceptual router structure based on implementation patterns

router.get("/import/template")      # Returns CSV template

router.post("/import/preview")      # Dry-run validation

router.post("/import")              # Actual import execution

Asset Import Endpoints

Asset imports mirror the transaction pattern in backend/app/api/assets.py:


# Parallel implementation for asset entities

router.get("/import/template")
router.post("/import/preview")
router.post("/import")

Both modules delegate to the shared ImportService class, eliminating code duplication and guaranteeing consistent validation logic.

The ImportService: Central Processing Engine

Located at backend/app/services/import_service.py, the ImportService orchestrates all data import and export via API operations. It handles:

  • Format parsing: CSV and JSON deserialization with configurable delimiters and encodings
  • Field validation: Date formatting, numeric ranges, foreign key existence checks
  • Row mapping: Transformation from flat import format to normalized SQLAlchemy models
  • Preview generation: Construction of ImportPreview objects showing create/update/reject counts
  • Transactional writes: ACID-guarded commit operations with rollback on failure

The service uses identical code paths for preview and commit phases, ensuring that validation results accurately predict commit behavior.

Step-by-Step API Usage

Step 1: Obtain Import Template

Download the canonical CSV structure to ensure column alignment:

curl -H "Authorization: Bearer ${SECURO_JWT}" \
     https://api.securo.finance/api/transactions/import/template \
     -o transaction_template.csv

The template endpoint in backend/app/api/import_transactions.py generates headers dynamically from the Transaction model definition, guaranteeing schema currency.

Step 2: Preview Before Committing

Validate your data without side effects:

curl -X POST \
     -H "Authorization: Bearer ${SECURO_JWT}" \
     -H "Content-Type: text/csv" \
     --data-binary @populated_transactions.csv \
     https://api.securo.finance/api/transactions/import/preview

Example response structure:

{
  "imported": 25,
  "updated": 0,
  "rejected": 3,
  "errors": [
    {"row": 14, "field": "date", "message": "Invalid date format"},
    {"row": 18, "field": "amount", "message": "Negative amount not allowed"}
  ]
}

The preview endpoint is tested in backend/tests/test_write_permission_gate.py to verify zero database mutations occur during this phase.

Step 3: Execute Import

After preview approval, trigger persistent changes:

curl -X POST \
     -H "Authorization: Bearer ${SECURO_JWT}" \
     -H "Content-Type: text/csv" \
     --data-binary @populated_transactions.csv \
     https://api.securo.finance/api/transactions/import

Success response includes audit reference:

{
  "import_log_id": "2f9c8e12-5b4a-4b9d-9a37-1c2e5d8f7a1d",
  "imported": 25,
  "updated": 0,
  "rejected": 0
}

Security and Permission Architecture

Authentication and Authorization

All data import and export via API endpoints require valid JWT authentication. The permission model distinguishes:

  • Preview access: Granted to users with read permissions on the target entity
  • Commit access: Restricted to users with explicit write permissions

This enforcement occurs through FastAPI dependency injection in backend/app/api/import_transactions.py and backend/app/api/assets.py.

Audit Logging

Every successful import creates an ImportLog record defined in backend/app/models/import_log.py. The log captures:

  • Original filename and checksum
  • Row counts (processed, created, updated, rejected)
  • Validation warnings
  • Timestamp and user attribution
  • Reference to import batch for reconciliation

Retrieve logs via:

curl -H "Authorization: Bearer ${SECURO_JWT}" \
     https://api.securo.finance/api/imports/${IMPORT_LOG_ID}

Testing and Quality Assurance

The repository includes comprehensive test coverage for import functionality:

Test File Purpose
backend/tests/test_import_api.py End-to-end validation of preview and commit workflows
backend/tests/test_write_permission_gate.py Verifies preview endpoints never perform writes

These tests assert that ImportService.preview() and ImportService.import_data() produce identical validation results while differing only in persistence behavior.

Summary

Securo's data import and export via API implementation prioritizes safety and auditability through:

Frequently Asked Questions

What file formats does Securo's import API support?

Securo accepts CSV and JSON payloads for import operations. The ImportService in backend/app/services/import_service.py detects format from Content-Type headers and applies appropriate parsers. CSV is recommended for bulk operations due to streaming efficiency with large datasets.

Why does Securo require a preview step before importing?

The preview endpoint provides dry-run validation that surfaces row-level errors without database mutation. As enforced by tests in backend/tests/test_write_permission_gate.py, this design allows clients to fix data issues before attempting actual commits, preventing partial imports and data inconsistency.

How does Securo handle import failures during commit?

The commit endpoint in backend/app/api/import_transactions.py wraps import operations in database transactions. If any row fails validation during the commit phase—after passing preview—the entire batch rolls back. This atomic behavior ensures the database remains consistent, with error details returned to the caller for remediation.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →