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 under stable slugs (for example/casp/euwax-ag) based on the latest API snapshot available during build. Legacy numeric-id URLs (/casp/{id}) get redirect stubs pointing at the slug URL; unknown paths are served by anoindexSPA fallback (spa-fallback.html). 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.