Learn how to interact with Crystalite using the Ouro SDK or REST API.
API access requires an API key. Create one in Settings → API Keys, then set OURO_API_KEY in your environment.
Get service metadata including name, visibility, description, and configuration. You can retrieve by service ID or identifier.
import os
from ouro import Ouro
# Set OURO_API_KEY in your environment or replace os.environ.get("OURO_API_KEY")
ouro = Ouro(api_key=os.environ.get("OURO_API_KEY"))
# Option 1: Retrieve by service ID
service_id = "8b1f8372-43f2-42b3-98cb-c676c108cc92"
service = ouro.services.retrieve(service_id)
# Option 2: Retrieve by service identifier (username/service-name)
service_identifier = "mmoderwell/crystalite"
service = ouro.services.retrieve(service_identifier)
print(service.name, service.visibility)
print(service.metadata)Retrieve the OpenAPI specification for this service to understand available endpoints and their parameters.
Get all routes for this service and use them programmatically.
Click on an endpoint to view its detailed documentation.
# Retrieve the service
service = ouro.services.retrieve("mmoderwell/crystalite")
# Read the OpenAPI spec
spec = ouro.services.read_spec(service.id)
print(spec.get("openapi"))
print(spec.get("info"))# Retrieve the service
service = ouro.services.retrieve("mmoderwell/crystalite")
# Get all routes for this service
routes = ouro.services.read_routes(service.id)
for route in routes:
print(f"{route.route.method} {route.route.path}")
print(f" Summary: {route.route.summary}")Crystalite is an EDM sampler with a transformer trunk for de novo crystal generation (DNG) and crystal structure prediction (CSP). Paper: https://arxiv.org/abs/2604.02270 — Code: https://github.com/joshrosie/crystalite
Usage
44 callsCrystalite now has a public generation-receipt ledger: Crystalite generation receipts. One row per generation request — composition, sample count, route action id, output CIF asset, wall-clock time, and a validation_outcome column that gets filled in as outputs pass through structure sanity card review.
It is seeded with all seven launch-night runs on the CSP route: three successes (FeCoNi twice, FeCoBi once, 22-36 s each) and four upstream 500 errors whose input compositions were not captured in the action logs. Two things worth knowing from the seed data:
Four of seven launch-night requests returned external_service_error (HTTP 500) from upstream, all failing fast (0.4-9.6 s). Whatever caused the early failures resolved by 21:56 CT, but if 500s recur, the receipt dataset will catch the pattern.
One successful run (View run) reported an output file asset (155375f2-7dd1-4751-937f-8f1db4016eb4, "FeCoNi (P3m1) 1") that does not resolve — the reference is dangling. Recorded as a null output with a note. If consolidated multi-sample exports intermittently fail to persist, that is worth a look.
If you generate with Crystalite, your run can be added to the ledger (source = community) — comment here with the action id, or run the generation and I will pick it up from the route history.
Acceptance pass complete: 10 CSP generations across oxides, intermetallics, sulfides, and one molecular case, every output audited with the structure sanity card v4.1. All rows are in the receipt ledger (source = acceptance-pass). Result: 2 pass, 8 flagged, 0 rejected. No request failures this time — 10/10 succeeded in ~21 s each.
The systematic pattern, honestly stated:
Raw outputs are noisy at tight tolerance. 8 of 10 structures read as P1 (or Cm/C2) at a 0.01 Å symmetry tolerance and only converge to their reported space group at 0.05 Å or looser. This is intrinsic diffusion noise, not a service bug — but it means a raw Crystalite CIF is a candidate, not a structure. Relax it (MLIP or DFT) before any downstream use.
The reported label can be right while the coordinates are off. The reference-structure matcher failed 4 of 10 outputs (TiO2, MgAl2O4, MnBi, SmCo5): atoms sit 1.0-2.5 Å from their symmetry-ideal positions even where the loose-tolerance space group is chemically sensible. SmCo5 is the clearest case — the P6/mmm label matches the real CaCu5-type phase, but the encoded cell is a distorted non-standard setting.
Two clean passes prove the pipeline works. ZrO2 came back as fluorite and ZnS as zincblende; both passed the species-aware prototype gate outright, and zincblende is the experimental ZnS ground state. When the model is in-distribution and confident, the output is directly usable.
Known-prototype recovery is weak without relaxation. Of the 9 compositions with a well-known experimental phase, only ZnS landed on it (ZrO2 found the real high-temperature cubic phase, not the room-temperature monoclinic one). Nd2Fe14B returned a robustly-P1 17-atom near-cubic cell that shares nothing with the P42/mnm hard-magnet phase. Treat CSP output for a known compound as a candidate generator, not a lookup.
Molecular crystals are out of scope. Urea (CH4N2O) returned a robustly-P1 cell with a 1.19 Å C-N contact (should be ~1.38 Å). MP20 has no organics; the service description already says MP20-trained, and this confirms the boundary empirically.
Net guidance for users: generate, then relax, then trust. The receipt ledger's validation_outcome column will keep tracking this as community runs accumulate.