Working examples interacting with the ODR API, grouped by their target database. Each one is a small, runnable script rather than a library — read it, run it, copy the parts you need.
One directory per database:
| Directory | Database | Examples | Languages |
|---|---|---|---|
AMCSD/ |
American Mineralogist Crystal Structure Database | Download a record's CIF by its database_code_amcsd value; print the database template |
Python, JavaScript |
Each directory holds its own scripts, its own env.example, and a
README.md describing what the scripts do and how to run them. Start
with the README in the directory you care about.
Configuration is per directory, so each set of examples can point at a different host or account:
cd AMCSD
cp env.example .env # then fill in the values
./amcsd_download_cif.py --show-templateSettings common to every example:
| Setting | Meaning |
|---|---|
ODR_API_BASE_URL |
ODR host, no trailing slash. On WordPress-integrated sites this is the ODR alias, e.g. https://www.rruff.net/odr_rruff, not the site root |
ODR_API_USERNAME / ODR_API_PASSWORD |
Account allowed to authenticate at /api/v5/token. Reading public data needs no special permissions |
ODR_VERIFY_TLS |
0 accepts self-signed certificates. Development only |
Individual directories add their own settings, such as the dataset uuid
they work against. Real environment variables take precedence over
.env, and most scripts accept command-line overrides as well.
.env holds credentials and is gitignored. Don't commit it.
Examples come in more than one language. Each is written against its
runtime's standard library alone -- Python 3 needs no pip installs, and
the JavaScript versions run on Node.js 18+ with no npm install -- so a
script can be copied out and run on its own. Where the same example
exists in several languages, all versions take the same arguments and
behave identically.
Whatever the language, they follow the same four steps:
-
Get a token.
POST /api/v5/tokenwith a username and password returns a JWT. Send it asAuthorization: Bearer <token>on subsequent calls. -
Read the template.
GET /api/v5/search/database/<dataset_uuid>describes a database: every field with its uuid, its type, and its numeric id, plus any related databases. Most scripts take a--show-templateflag that prints this, which is the quickest way to find the uuid of a field you want. -
Search.
POST /api/v5/dataset/<dataset_uuid>/search/<limit>/<offset>takes a plain JSON body — no base64 — identifying each field byfield_uuid(ortemplate_field_uuid):{ "fields": [ { "field_uuid": "77bff846555653b1530001b25c23", "value": "0000035" } ] } -
Follow the links. Records come back with their field values already included, and file fields carry a
hreffor each attached file. Downloading is a plain GET on that link.
- Address things by uuid, not numeric id. Field and database uuids are stable across installs; the numeric ids are not. Where an example starts from a numeric id, it uses the template to translate it into a uuid and does everything else by uuid.
- Don't quote a value to force an exact match. ODR treats
surrounding quotes as literal characters, so
"0000035"matches nothing. Send the raw value and confirm the match in your own code — a text search can return more than one record. - Search results are paged. A response looks like
{"results": 2094, "offset": 30, "limit": 30, "records": [...]}, whereresultsis the total number of matches andrecordsis the page you asked for. Omitting a limit returns 25 records, and 100 is the most a single request will return; ask for more and it is capped at 100. - File downloads live outside
/api. Public files need no token, but sending one anyway lets an authorized account fetch restricted files.
Create a directory named after the database, and include:
- the script itself, executable, with a
--helpthat explains it (a port into another language keeps the same name, arguments and output as the original) env.examplelisting every setting it reads, with no real values.gitignorecontaining.envREADME.mdcovering what it does, how to run it, and anything surprising you hit in the API- a row in the table above
Keeping each directory self-contained means an example can be handed to someone on its own.