Container and Product EZID DOIs with Python

Author

Andrea Zonca

Published

December 2, 2025

This post refers to the ezid_api repository.

The previous tutorial showed how to wire a canonical DOI to multiple versions; start there if you need versioning rather than parts: single DOI basics and hierarchical versioned DOIs. This follow-up creates a container DOI for a data release and two product DOIs that declare they belong to that release. The pattern mirrors a collection landing page (container) that links to specific datasets (products) using DataCite’s HasPart and IsPartOf relations.

What the container/product pattern does

The new create_container_doi.py script mints three identifiers under the EZID test shoulder doi:10.5072/FK2:

  1. Release container (SIMONSOBS-RELEASE-2025) – represents the 2025 Simons Observatory release and lists each product DOI with HasPart.
  2. Product 1 (SIMONSOBS-RELEASE-2025-P1) – a sample data product that points back to the container DOI with IsPartOf.
  3. Product 2 (SIMONSOBS-RELEASE-2025-P2) – another product that also uses IsPartOf to reference the same container DOI.

Because we stay on the EZID test shoulder, you can try the flow without touching production identifiers.

Running the scripts

From the ezid_api repository root:

# Mint the release DOI plus two product DOIs
uv run python create_container_doi.py

# Inspect the three identifiers and highlight relation fields
uv run python check_container_doi.py

Both scripts reuse the .env credentials described in the earlier posts (EZID_USERNAME and EZID_PASSWORD). The creation step prints each EZID response along with the resolver URLs (https://doi.org/10.5072/FK2/...).

Relationship fields you should see

check_container_doi.py prints the ANVL metadata returned by EZID and highlights the relationship fields. A shortened sample looks like:

_target: https://example.org/data-releases/simonsobs-2025
datacite.relatedidentifier.1: 10.5072/FK2/SIMONSOBS-RELEASE-2025-P1
datacite.relatedidentifiertype.1: DOI
datacite.relationtype.1: HasPart
datacite.relatedidentifier.2: 10.5072/FK2/SIMONSOBS-RELEASE-2025-P2
datacite.relatedidentifiertype.2: DOI
datacite.relationtype.2: HasPart

_target: https://example.org/data-releases/simonsobs-2025/product-1
datacite.relatedidentifier.1: 10.5072/FK2/SIMONSOBS-RELEASE-2025
datacite.relatedidentifiertype.1: DOI
datacite.relationtype.1: IsPartOf

The container DOI lists both products with HasPart, while each product DOI declares IsPartOf to connect back to the release landing page. Swap in your own URLs, creators, and titles before running against a production shoulder.