skills/pymatgen/references/materials_project_api.md
This reference targets mp-api==0.46.4 (released 2026-06-15) with
pymatgen==2026.5.4 and pymatgen-core==2026.7.16. mp-api requires Python
3.11+ and depends on pymatgen>2024.2.20.
Use the separate official client:
from mp_api.client import MPRester
Do not use a legacy Materials Project client import from older pymatgen examples.
Pin the tested client and materials stack:
uv add "pymatgen==2026.5.4" "pymatgen-core==2026.7.16" "mp-api==0.46.4"
uv lock
uv sync --frozen
The 0.46.4 package metadata declares direct dependencies including
pymatgen>2024.2.20, monty>=2024.12.10, emmet-core>=0.87.1,
requests>=2.23.0, orjson>=3.10,<4, pyarrow>=20, and
deltalake>=1.4,<1.6, plus boto3 and typing extensions. A lockfile is needed
to freeze transitive artifacts.
An API key is required and is available from the logged-in Materials Project dashboard.
The approved pattern is:
from mp_api.client import MPRester
# MPRester reads only the already-injected MP_API_KEY.
with MPRester() as rester:
pass
Operational rules:
MP_API_KEYThe bundled query CLI follows these rules and reads the variable only after
--execute.
Before any request, disclose:
mp-api versionnum_chunks, chunk_size, and maximum serialized bytesThe dry-run planner:
python scripts/mp_query.py \
--chemsys Li-Fe-O \
--energy-above-hull 0 0.05 \
--fields formula_pretty,energy_above_hull,band_gap,origins \
--limit 25
Only an explicit execution permits the disclosed network workflow:
python scripts/mp_query.py \
--material-id mp-149 \
--fields formula_pretty,structure,origins,last_updated \
--limit 1 --output mp-149.json --execute
The CLI has no implicit result cache. The explicit bounded JSON output is the
reusable artifact. MPRester initialization performs compatibility and
heartbeat/database-version metadata requests before the bounded summary
search. The CLI discloses those requests, disables the platform-detail user
agent and local database-version notification log, and records the server's
database version.
The official docs identify summary data as the main property overview for a material:
from mp_api.client import MPRester
with MPRester() as rester:
docs = rester.materials.summary.search(
material_ids=["mp-149", "mp-13"],
fields=[
"material_id",
"formula_pretty",
"energy_above_hull",
"band_gap",
"origins",
"last_updated",
],
all_fields=False,
num_chunks=1,
chunk_size=25,
)
material_ids accepts one ID or a list in the current signature. The result is
a list of SummaryDoc model objects by default.
Verified public SummaryRester.search parameters include:
with MPRester() as rester:
docs = rester.materials.summary.search(
chemsys="Li-Fe-O",
elements=["Li", "O"],
exclude_elements=["F"],
energy_above_hull=(0.0, 0.05),
band_gap=(0.5, 3.0),
is_stable=None,
fields=["material_id", "formula_pretty", "energy_above_hull", "band_gap"],
all_fields=False,
num_chunks=1,
chunk_size=25,
)
Other current filters include formula, crystal system, density, deprecation, dielectric ranges, elastic ranges, metal/direct-gap flags, property availability, magnetic ordering, element/site counts, space group, theoretical status, energy ranges, volume, and surface-property ranges. Consult the exact installed signature instead of passing guessed keywords.
exclude_elements is a list of element symbols; it is not a Boolean flag.
available_fields lists fields the endpoint can return. It does not mean every
field is a valid filter:
with MPRester() as rester:
returnable_fields = rester.materials.summary.available_fields
Requesting all fields is the documented default and can be expensive. Always
pass a short fields list and bound chunks.
Use the public Pydantic model interface:
payload = [document.model_dump(mode="json") for document in docs]
Then write strict JSON with allow_nan=False, a byte bound, and a new output
path. Include query, fields, retrieval time, endpoint, client versions, and
license/citation. Do not use deprecated generic dictionary shims, pickle, or a
general object decoder on untrusted cached data.
from mp_api.client import MPRester
with MPRester() as rester:
structure = rester.get_structure_by_material_id(
"mp-149",
final=True,
conventional_unit_cell=False,
)
Alternatively request structure as an explicit summary field. Preserve:
origins and task IDsValidate the returned structure locally. A Materials Project structure is a computed relaxed representation, not necessarily the experimental setting, lattice parameters, disorder, temperature, or composition model.
from mp_api.client import MPRester
with MPRester() as rester:
entries = rester.get_entries_in_chemsys(
"Li-Fe-O",
compatible_only=True,
conventional_unit_cell=False,
)
The current method also accepts use_gibbs, property_data, and
additional_criteria. The official query guide shows filtering thermo types
through:
with MPRester() as rester:
entries = rester.get_entries_in_chemsys(
"Co-N",
additional_criteria={
"thermo_types": ["GGA_GGA+U", "GGA_GGA+U_R2SCAN", "R2SCAN"]
},
)
Do not mix thermo types or correction schemes casually. Record all arguments, entry IDs, correction data, origins, and database release. Preserve the retrieved entries locally and build the hull offline.
Official convenience methods include:
with MPRester() as rester:
bands = rester.get_bandstructure_by_material_id("mp-149")
dos = rester.get_dos_by_material_id("mp-149")
These can return None when data is unavailable. Their values are computed and
method-dependent. Preserve calculation/task origins, spin/SOC, path/mesh,
functional, and database release. Do not treat an absent object as a zero gap
or zero DOS.
The official query guide recommends requesting origins to connect a summary
property to a calculation task:
with MPRester() as rester:
summaries = rester.materials.summary.search(
material_ids=["mp-149"],
fields=["material_id", "structure", "origins"],
all_fields=False,
num_chunks=1,
chunk_size=1,
)
An origin can identify the task used for a property. A corresponding thermo
document's run_type distinguishes categories such as GGA, GGA+U, or r2SCAN.
Do not assume all properties on one summary document came from one calculation
or functional.
The client exposes endpoint-specific resters under rester.materials, with
routes documented for thermo, electronic structure, elasticity, dielectric,
magnetism, phonons, surfaces, XAS, synthesis-related data, and others.
Signatures and document models vary. Inspect the current route documentation
and request only supported fields.
Do not copy old endpoint examples or invent filter names. Endpoint availability and schema can evolve independently of the Python wrapper.
Use the current exception:
from mp_api.client.core.exceptions import MPRestError
try:
with MPRester() as rester:
docs = rester.materials.summary.search(
material_ids=["mp-149"],
fields=["material_id"],
all_fields=False,
num_chunks=1,
chunk_size=1,
)
except MPRestError:
# Report a bounded, credential-redacted failure.
raise
Official 0.46.4 client source configures retries for HTTP 429, 502, and 504 and
respects Retry-After. It wraps request failures as MPRestError and advises
smaller requests on connection timeout.
Safety rules:
MP_API_KEY from any exception textCaching can improve reproducibility but creates a data-governance obligation. Before using a cache, disclose:
Never cache credentials. Never treat a cache as current without checking its
retrieval time and database version. mp-api exposes a local full-dataset cache
path for bulk/delta-table workflows; the bundled summary-query CLI does not
request those downloads and intentionally uses no hidden result cache.
Materials Project states that its data is licensed under CC BY 4.0 and that contributed data is owned by its respective contributors.
The official FAQ says citations are appropriate wherever Materials Project data, methods, or output are used. Preserve:
See How to Cite and Database Versions.
Materials Project documents that:
symprec; the MP pipeline commonly uses 0.1 ÅTherefore:
{
"retrieved_at_utc": "2026-07-23T00:00:00Z",
"endpoint": "https://api.materialsproject.org/materials/summary/",
"filters": {"material_ids": ["mp-149"]},
"fields": ["material_id", "formula_pretty", "origins", "last_updated"],
"limit": 1,
"client": {
"mp-api": "0.46.4",
"pymatgen": "2026.5.4",
"pymatgen-core": "2026.7.16"
},
"database_version": "record from current MP release metadata",
"license": "CC BY 4.0",
"citation": "https://materialsproject.org/about/cite"
}
Do not include the API key.