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
ImportPreviewobjects 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:
- Unified ImportService (
backend/app/services/import_service.py) providing consistent parsing and validation - Three-phase workflow (template → preview → commit) preventing accidental data corruption
- Strict permission separation between read-only preview and destructive commit operations
- Comprehensive audit logging via
ImportLogmodel for regulatory compliance - Shared endpoint patterns across transactions (
backend/app/api/import_transactions.py) and assets (backend/app/api/assets.py)
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →