Implements the API from Aurand, Siadat, Shaska (2025) — a self-populating database for rational points in M₂(Q).
All endpoints require an API key:
Authorization: Bearer crv_your_key_here
# or
?api_key=crv_your_key_here
API requests are rate-limited to 30 requests per minute per API key. Admin accounts are exempt. Returns 429 when exceeded with a Retry-After header.
All /api/ endpoints include CORS headers, so you can call the API directly from
browser-based environments like Jupyter notebooks, Google Colab, or Observable.
import requests
KEY = "crv_your_key_here"
BASE = "https://data.i-aims.com"
# Lookup a curve by equation
r = requests.get(f"{BASE}/api/v1/lookup?curve=x^5+3x^3-2x^2+x+1&api_key={KEY}")
info = r.json()
print(info["canonical_key"])
print(info["automorphism_group"])
print(info["igusa"])
# Browse with filters
r = requests.get(f"{BASE}/api/v1/browse?page=1&per_page=10&signature=2,1&api_key={KEY}")
for c in r.json()["curves"]:
print(c["value"]["coefficients"])
# Get statistics
r = requests.get(f"{BASE}/api/moduli/stats")
print(r.json()["total"], "curves in database")
GET /api/curve/J2_J4_J6_J10
Returns the full record for a canonical moduli point in P(2,4,6,10). Redis-first, sub-millisecond.
curl "https://data.i-aims.com/api/curve/1_2_-3_4?api_key=YOUR_KEY"
GET POST /api/v1/lookup
Accepts any input format. Computes invariants, looks up by canonical key, and auto-inserts missing points into the database.
# By equation
curl "https://data.i-aims.com/api/v1/lookup?curve=x^5+3x^3-2x^2+x+1&api_key=YOUR_KEY"
# By canonical key (fastest)
curl -X POST https://data.i-aims.com/api/v1/lookup \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"canonical_key": "1_2_-3_4"}'
# By Igusa invariants
curl -X POST https://data.i-aims.com/api/v1/lookup \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"J2": -40, "J4": -80, "J6": 320, "J10": -256}'
# By reduced coefficients
curl -X POST https://data.i-aims.com/api/v1/lookup \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"coefficients": [-912, 61956, -13777884, 12393056]}'
# By binary sextic vector
curl -X POST https://data.i-aims.com/api/v1/lookup \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"sextic": [1, 0, -82, 0, -14, 0, 1]}'
Response includes all fields from the paper's schema: canonical_key,
igusa, absolute_invariants_i, absolute_invariants_t,
automorphism_group, height, weighted_height,
is_fine, in_L2/in_L3/..., in_database,
stored (full record if found).
GET /api/moduli/search
# Search by equation (self-populating)
curl "https://data.i-aims.com/api/moduli/search?equation=x^5+3x^3-2x^2+x+1"
# Search by Igusa invariants (self-populating)
curl "https://data.i-aims.com/api/moduli/search?J2=-40&J4=-80&J6=320&J10=-256"
# Filtered search: fine points in L3 with height ≤ 5
curl "https://data.i-aims.com/api/moduli/search?fine=true&height_lt=5&inLn=L3"
GET /api/moduli/stats
Live aggregate statistics: total points, locus distribution, fine/coarse counts, automorphism group distribution.
GET /api/v1/browse
# All curves, paginated
curl "https://data.i-aims.com/api/v1/browse?page=1&per_page=25&api_key=YOUR_KEY"
# Filter by invariant range and signature
curl "https://data.i-aims.com/api/v1/browse?inv_min=0&inv_max=100&signature=2,1&api_key=YOUR_KEY"
# Filter by coefficient range
curl "https://data.i-aims.com/api/v1/browse?c0_min=-1000&c0_max=1000&api_key=YOUR_KEY"
from curvedb import CurveDB
db = CurveDB("YOUR_KEY", base_url="https://data.i-aims.com")
# Lookup by equation (self-populating)
info = db.lookup("x^5 + 3x^3 - 2x^2 + x + 1")
print(info["automorphism_group"])
print(info["canonical_key"])
print(info["in_database"]) # Always True after self-population
# Lookup by canonical key
info = db.lookup(canonical_key="1_2_-3_4")
# Lookup by Igusa invariants
info = db.lookup(J2=-40, J4=-80, J6=320, J10=-256)
# Direct canonical key retrieval (<1ms)
record = db.curve("1_2_-3_4")
# Paper-style filtered search
results = db.search(fine=True, height_lt=5.0, inLn="L3")
# Extended statistics
stats = db.stats()
print(stats["loci"]) # {'L2': 0, 'L3': 30933, ...}
print(stats["fine"]) # count of fine moduli points
# Browse
for curve in db.browse_all(signature="2,1", inv_max=100):
print(curve["value"]["coefficients"])
Install: pip install curvedb or copy curvedb.py into your project.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/curve/<key> | Direct canonical key lookup (Redis-first) |
| GET/POST | /api/v1/lookup | Smart lookup with self-populating |
| GET | /api/moduli/search | Paper-style search (equation, invariants, filters) |
| GET | /api/moduli/stats | Extended statistics |
| GET | /api/v1/browse | Browse/filter curves with pagination |
| GET | /api/v1/me | Your user info and API key |
| POST | /api/v1/regenerate-key | Generate a new API key (invalidates old) |