Skip to content

omnilab/oqmd

Omnilab OQMD: the Open Quantum Materials Database - an entry by its OQMD id (formula, space group, prototype, volume, formation energy, hull distance, band gap, ICSD id) and the entries of a composition or a phase space, through its RESTful API, no key. Not tested live.

Floor
Provider · Omnilab
Version
1.x
Conformance suite
not wired
Verified for real
Its README does not say
Licence
MIT
composer require omnilab/oqmd:1.x-dev

Not tested live: OQMD did not answer on 2026-10-15 (see Verified, and not).

Installation

composer require omnilab/oqmd
use Omnilab\Oqmd\OqmdSourceFactory;

$oqmd = (new OqmdSourceFactory($httpClient))->create(['mailto' => 'support@glitchr.io']);

Credentials

None: OQMD's API takes no key and no account. Give mailto, so that the service can reach the caller before it blocks them.

Options

The factory's options, with the defaults it applies (OqmdSourceFactory):

Option Type Default Required Effect
mailto ?string null no a contact address, sent in the User-Agent
user_agent ?string null no the whole User-Agent, in place of the one made from mailto
throttle float 0 no seconds left between two calls: OQMD publishes no rate
base_uri string https://oqmd.org/oqmdapi/ no the API the source calls

Capabilities

capabilities() answers entity, search; an operation it does not answer throws NotSupportedException before any call.

Capability Supported
entity yes an OQMD id: oqmd:16974, its page oqmd.org/materials/entry/16974, or a bare number; any other identifier refused before any call
search yes a composition (Al2O3) or a phase space (Fe-O), white space removed; 100 entries a page at most; a domain other than chemistry answers an empty page
series no
products no
occurrences no
datasets no
jobs no
open no
structure no
cross_references no none: the ICSD id is a property (xref), the entry it duplicates a related thing (duplicate_of)
forecast no
historical no
area no
station no
cloud_cover no

The scheme

An entry is named in the core's oqmd scheme by its number (16974), read from oqmd:16974 and from its page oqmd.org/materials/entry/16974; a bare number is read as one by this source.

Which API

OQMD's RESTful API, oqmd.org/oqmdapi/formationenergy (documented at static.oqmd.org/static/docs/restful.html), format=json, the fields asked (name, entry_id, icsd_id, duplicate_entry_id, composition_generic, prototype, spacegroup, natoms, ntypes, volume, delta_e, stability, band_gap):

Method Call
entity() filter=entry_id={id}&limit=1 - an assumption: the documentation lists entry_id among the fields, not among the filter's keywords; the row whose entry_id is the one asked is kept, any other ignored
search() composition={text}&limit=...&offset=... (a composition, Al2O3, or a phase space, Fe-O: the documentation's "composition" key); total from meta.data_available, the next page from meta.more_data_available

What an entity holds

id, label (its name and space group: NaAlH2CO5 (Imma)), domain chemistry, kind material, url (its page), and: formula, generic_formula, prototype, space_group, atoms, element_types, volume (ų, the cell's), formation_energy_per_atom (delta_e, eV/atom), energy_above_hull (stability, the hull distance, eV/atom), band_gap (eV), xref (icsd: ...); related: duplicate_of (the preferred entry with the same structure). The units are those OQMD's papers use for these quantities; the API's documentation gives none.

Example

<?php

require __DIR__.'/vendor/autoload.php';

use Omnilab\Exception\UnavailableException;
use Omnilab\Oqmd\OqmdSourceFactory;
use Omnilab\Source\Query;
use Symfony\Component\HttpClient\HttpClient;

$oqmd = (new OqmdSourceFactory(HttpClient::create()))->create(['mailto' => 'you@example.org']);

try {
    $page = $oqmd->search(new Query('Al2O3', limit: 3));
    printf("%s entries of Al2O3:\n", $page->total ?? '?');
    foreach ($page as $entry) {
        printf("  %s  %s  %s, hull %s\n", $entry->id, $entry->label, $entry->property('formation_energy_per_atom'), $entry->property('energy_above_hull'));
    }
    $entry = $oqmd->entity('oqmd:16974');
    echo $entry?->label ?? 'unknown', "\n";
} catch (UnavailableException $e) {
    echo get_class($e), ': ', $e->getMessage(), "\n";
}
Omnilab\Exception\UnavailableException: [oqmd] the service answered 502

(as answered on 2026-10-27: OQMD was down again - a 502, and time-outs on other tries that day - so the script shows the exception a caller gets, never an empty answer)

# config/packages/omnilab.yaml
omnilab:
    sources:
        oqmd: { factory: oqmd, options: { mailto: '%env(OMNILAB_MAILTO)%' } }

Errors

Every call goes through HttpSource: a 404 or a 410 (and a 204) is null - an empty page for a list -; a 429 is a RateLimitedException (retryAfter from Retry-After); a 5xx, a time-out or a host that does not answer an UnavailableException; any other 4xx a ProviderException with its status and what the service said; an answer that is not JSON a ProviderException, a web page answered for JSON an UnavailableException.

Before any call, entity() refuses an identifier that is not of the oqmd scheme (NotSupportedException: The "oqmd" source cannot look up "..."), and the operations OQMD does not have (series, products, occurrences, datasets, files) are HttpSource's refusals. An id OQMD answers no row for is null; a row whose entry_id is not the one asked is ignored.

Verified, and not

Not tested live. On 2026-10-15 oqmd.org/oqmdapi/formationenergy answered 502 ("Server Error... Please try again in 30 seconds"), then every call to oqmd.org timed out (30 to 40 s), retried for forty minutes; the documentation (static.oqmd.org) answered. The fixtures are that documentation's example answer, as published (two entries of element_set=(Al-Fe),O), one cut to its first entry, and one emptied (Tests/Fixtures/README.md). Not verified: every call of the package, filter=entry_id=... above all; the units; the rate the service bears (none published).

Tried again on 2026-10-27, four runs of the example below: once the search for Al2O3 answered (its first entry 14842) and the filter=entry_id=14842 call that followed timed out; then a search timed out; then twice a 502. The entity call is still unverified.

Responsibility

This package is an independent, unofficial client: it is not affiliated with, endorsed by or sponsored by the OQMD team (Northwestern University). OQMD states its terms on oqmd.org, and asks that the two papers the README's Terms of use names be cited. Whoever runs the package is responsible for complying with those terms and for any use made of what it returns: see the README's Responsibility section.

Propose a change docs/index.md