Public web app for browsing ESMA MiCA registers in one searchable interface.
Live app: www.micaregister.com
Backend API docs (recommended custom domain): https://api.micaregister.com/docs
- Aggregates all 5 ESMA MiCA registers in one UI:
- CASP (Crypto-Asset Service Providers)
- OTHER (White papers for other crypto-assets)
- ART (Asset-Referenced Token Issuers)
- EMT (E-Money Token Issuers)
- NCASP (Non-compliant entities)
- Fast filtering by name, country, LEI, services, dates, and register-specific fields
- Shareable entity deep links (for example
/casp/{entity_id}) that open details directly - CASP list and detail views group duplicate LEI rows into one company card with multiple authorisation records
- Home Member State filtering falls back to LEI country when ESMA country is missing
- Backend API for search, filtering, and admin imports
- Data update scripts for download, validation, cleaning, and import
- Backend: FastAPI, SQLAlchemy, Alembic-style migrations
- Frontend: React + Vite
- Database: PostgreSQL (production) or SQLite (local)
- Deploy: Railway (backend) + Vercel (frontend)
git clone https://github.com/Kymylyy/mica-register.git
cd mica-registerpython3 -m venv .venv
source .venv/bin/activate
pip install -r backend/requirements.txtOptional database config:
export DATABASE_URL="postgresql://user:password@localhost:5432/mica_register"If DATABASE_URL is not set, local SQLite is used.
python3 backend/import_all_registers.pycd backend
uvicorn app.main:app --reloadBackend URL: http://localhost:8000
cd frontend
npm install
npm run devFrontend URL: http://localhost:5173
Backend:
DATABASE_URL(required in production)CORS_ORIGINS(comma-separated allowed origins)ADMIN_API_TOKEN(orADMIN_TOKEN) for/api/admin/*and authenticated entity write endpointsDEEPSEEK_API_KEY(optional, only for LLM remediation flows)
Frontend:
VITE_API_URL(e.g.https://api.micaregister.comin production)
See .env.example and frontend/.env.example for local templates.
- Connect repository to Railway
- Ensure PostgreSQL service is attached
- Set required env vars (
DATABASE_URL,CORS_ORIGINS,ADMIN_API_TOKEN) - Schema bootstrap in production happens via
backend/start.sh, which runs the repo migrations before starting the API. - Add custom domain (recommended):
api.micaregister.com - Optional cron: run
python scripts/run_railway_cron_update.py
- Import
frontendproject - Set
VITE_API_URLto your API domain (recommended:https://api.micaregister.com) - Build command:
npm run build - Output directory:
dist - Build output includes static prerendered pages for
/,/casp,/other,/art,/emt, and/ncasp, plus entity detail pages (for example/casp/{id}) based on the latest API snapshot available during build. sitemap.xmlandrobots.txtare generated during prerender from the same route set (including entity detail URLs when available at build time).micaregister.comis redirected permanently (301) towww.micaregister.com.- Detail prerender validation: by default it fails on CI/Vercel (
PRERENDER_DETAIL_FAILURE_MODE=error) and warns locally (warn) when detail pages cannot be generated or are belowPRERENDER_MIN_DETAIL_PAGES(default1).
Per-register feeds (public):
GET /api/feeds(index with feed links + docs + OpenAPI URL on current host)GET /api/feeds/{register}.jsonGET /api/feeds/{register}.csv- API crawler endpoints on the API host:
GET /robots.txtGET /sitemap.xml
Where {register} is one of: casp, other, art, emt, ncasp.
CASP grouped UI behavior:
- The web UI groups CASP entries by LEI for list and detail views.
- Public CASP feed endpoints remain raw-row exports of the underlying ESMA-style data.
Operational behavior:
- Feed responses are cached in API process memory for 300 seconds.
- Feed responses include
ETagandCache-Controlheaders for conditional requests and client/proxy caching. - Feed endpoints are rate limited to 30 requests per 60 seconds per client IP.
List endpoints support single-column global sorting before pagination:
GET /api/entitiesGET /api/casp/companies
Query params:
sort_by=<field>sort_dir=asc|desc
Behavior:
- Sorting is applied to the full filtered result set before
skipandlimit. - When
sort_byis omitted, each endpoint keeps its existing default ordering. - Date fields always place
nullvalues at the end. - Unsupported sort fields return
400.
Supported sort_by values depend on the register and match the sortable columns exposed in the UI for that register.
GET /llms.txtis served by the frontend domain (https://www.micaregister.com/llms.txt).- It documents canonical host, crawl entry points, entity URL pattern, API docs, data source notes, and technical contact.
Frontend:
cd frontend && npm run lintcd frontend && npm run typecheckcd frontend && npm run test -- --runcd frontend && npm run build
Backend:
python3 -m pytest
CI runs the same checks on every pull request and push.
Primary source: ESMA MiCA register publications.
Before redistributing data snapshots from data/, confirm legal/licensing requirements for your use case.
See CONTRIBUTING.md.
See SECURITY.md for vulnerability reporting and secret handling expectations.
MIT. See LICENSE.