Mapping NIH DMS Policy Fields to DataCite Metadata

A NIH Data Management and Sharing (DMS) Plan is written as prose for a program officer, but the dataset it governs is deposited as structured metadata for a machine. Between those two forms sits a crosswalk that most teams do by hand and therefore do inconsistently: the plan promises deposit in a repository, a persistent identifier, an access timeline, and reuse terms, yet the deposited record often omits the very DataCite properties that would make those promises verifiable. This page is the field-level mapping that closes that gap. It takes the six elements of the NIH DMS Plan and pins each to specific properties of the DataCite Metadata Schema (version 4.5), so that a plan commitment becomes a concrete, checkable field in the minted record rather than an unenforced paragraph.

It sits beneath the broader Funder Mandate Alignment guide and assumes you already write DMS Plans and mint DataCite DOIs, and are comfortable with Python 3.10+ and the Pydantic V2 API. Where Aligning NIH Data Sharing Policies with FAIR Principles explains why each DMS commitment maps onto a FAIR obligation, this page is the narrower mechanical step: which DMS element populates which DataCite property, and a mapper that emits a valid property set. The DOI-minting call that consumes that property set is covered in DOI Minting with DataCite.

NIH DMS Plan to DataCite metadata mapping The six NIH DMS Plan elements feed a mapper that consults a crosswalk table and emits DataCite Metadata Schema properties. A decision node asks whether the required properties are complete. Complete records proceed to DOI minting; incomplete records route back to plan remediation. DMS Plan six elements Crosswalk mapper element to property DataCite props 4.5 schema Required complete? yes Mint DOI no Plan remediation fill missing field

The Six DMS Elements and Their DataCite Targets

The NIH DMS Policy structures a plan around six elements: the types of data to be produced, the related tools and software needed to interpret them, the standards applied, the preservation and access plan with its repository and timelines, the access and reuse considerations, and the oversight arrangements. DataCite’s schema was not designed around those elements, but almost every one has a natural home in a specific property. The mapping is not one-to-one — a single DMS element can populate several DataCite properties, and a few elements (notably oversight) map onto contributor roles rather than descriptive fields — but it is deterministic once the target properties are fixed.

The crosswalk below is the authoritative reference for this operation. Each row names a DMS element, the DataCite property or properties that carry it, and the notes an implementer needs to populate the field correctly.

NIH DMS Plan element DataCite property Notes
Element 1 — Data type types.resourceTypeGeneral = Dataset; subjects Set the general type to Dataset; encode data categories as subjects, ideally with a subjectScheme.
Element 2 — Related tools, software, code relatedIdentifiers (relationType = Requires / IsSupplementedBy); relatedItems Link the DOI or URL of each tool; use Requires for software needed to open the data.
Element 3 — Standards subjects (subjectScheme); formats; relatedIdentifiers (IsDescribedBy) Record the metadata standard as a subjectScheme/schemeURI and file formats in formats.
Element 4 — Preservation, access, timelines identifiers/DOI; publisher; publicationYear; dates (dateType = Available) The repository is the publisher; the sharing timeline is a dates entry with dateType Available.
Element 5 — Access, distribution, reuse rightsList (rightsIdentifier, rightsUri); descriptions (descriptionType = Other) Encode the license in rightsList; note controlled-access terms in a descriptions entry.
Element 6 — Oversight contributors (contributorType = DataManager / WorkPackageLeader) Name the responsible party as a contributor with an oversight role, not as a creator.

Two rows carry the most compliance weight. Element 4 is where the plan’s promise of a persistent identifier and a sharing timeline becomes machine-checkable: the publisher names the trusted repository, and a dates entry with dateType Available records exactly when the data becomes accessible. Element 5 is where reuse terms stop being prose and become a rightsList entry with an SPDX identifier — the same structured license object built in Configuring CC-BY Licenses for Automated Dataset Publishing.

Production Implementation

The mapper takes a structured DMS Plan and emits a DataCite property dictionary. Modelling the plan with Pydantic V2 lets the mapper fail at the plan boundary — a plan missing a repository or a license cannot silently produce an incomplete record — and keeps the crosswalk itself a small, readable transformation. The output is a partial DataCite payload: the properties this crosswalk owns, ready to be merged with creators and titles before minting.

python
from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field, field_validator


class DMSPlan(BaseModel):
    """The machine-readable slice of an NIH DMS Plan the crosswalk consumes."""

    data_categories: list[str] = Field(min_length=1)     # Element 1
    required_tools: list[str] = Field(default_factory=list)  # Element 2 (DOIs/URLs)
    metadata_standard: str                                # Element 3
    file_formats: list[str] = Field(default_factory=list)  # Element 3
    repository_name: str                                  # Element 4
    available_date: str                                   # Element 4 (ISO 8601)
    publication_year: int                                 # Element 4
    license_id: str                                       # Element 5 (SPDX)
    license_uri: str                                      # Element 5
    access_terms: str = "Open access"                     # Element 5
    oversight_party: str                                  # Element 6

    @field_validator("available_date")
    @classmethod
    def date_is_iso(cls, v: str) -> str:
        from datetime import date

        date.fromisoformat(v)  # raises ValueError on a malformed date
        return v


def map_plan_to_datacite(plan: DMSPlan) -> dict[str, Any]:
    """Emit the DataCite 4.5 properties the six DMS elements govern."""
    return {
        # Element 1 — data type
        "types": {"resourceTypeGeneral": "Dataset", "resourceType": "Research dataset"},
        "subjects": [
            {"subject": cat, "subjectScheme": plan.metadata_standard}
            for cat in plan.data_categories
        ],
        # Element 2 — related tools/software
        "relatedIdentifiers": [
            {
                "relatedIdentifier": tool,
                "relatedIdentifierType": "DOI" if tool.startswith("10.") else "URL",
                "relationType": "Requires",
            }
            for tool in plan.required_tools
        ],
        # Element 3 — standards
        "formats": list(plan.file_formats),
        # Element 4 — preservation, access, timelines
        "publisher": plan.repository_name,
        "publicationYear": str(plan.publication_year),
        "dates": [{"date": plan.available_date, "dateType": "Available"}],
        # Element 5 — access, distribution, reuse
        "rightsList": [
            {
                "rights": plan.access_terms,
                "rightsIdentifier": plan.license_id,
                "rightsIdentifierScheme": "SPDX",
                "rightsUri": plan.license_uri,
            }
        ],
        # Element 6 — oversight
        "contributors": [
            {
                "name": plan.oversight_party,
                "contributorType": "DataManager",
            }
        ],
    }


REQUIRED_PROPERTIES: tuple[str, ...] = (
    "types", "publisher", "publicationYear", "dates", "rightsList",
)


def missing_required(record: dict[str, Any]) -> list[str]:
    """Return the required DataCite properties absent or empty in a record."""
    return [p for p in REQUIRED_PROPERTIES if not record.get(p)]

The missing_required check is the compliance gate: the mapper always produces the property keys, but a plan that supplied no license or no available date yields empty values, and this function surfaces them before the record reaches the minting call. Pairing the mapper with that check turns the crosswalk into an enforceable control rather than a best-effort translation.

Verification

Exercise the mapper against a complete plan and assert that each element landed in its DataCite property, then confirm the required-property gate catches an incomplete record. No network access is needed; the mapper is pure.

python
def test_plan_maps_each_element() -> None:
    plan = DMSPlan(
        data_categories=["genomic sequences", "phenotype tables"],
        required_tools=["10.5281/zenodo.123456"],
        metadata_standard="dcat",
        file_formats=["text/csv", "application/vcf"],
        repository_name="Zenodo",
        available_date="2026-12-01",
        publication_year=2026,
        license_id="CC-BY-4.0",
        license_uri="https://creativecommons.org/licenses/by/4.0/",
        oversight_party="Dr. R. Mensah",
    )
    rec = map_plan_to_datacite(plan)
    assert rec["types"]["resourceTypeGeneral"] == "Dataset"
    assert rec["dates"][0]["dateType"] == "Available"
    assert rec["rightsList"][0]["rightsIdentifier"] == "CC-BY-4.0"
    assert rec["contributors"][0]["contributorType"] == "DataManager"
    assert missing_required(rec) == []


def test_incomplete_record_is_flagged() -> None:
    assert "rightsList" in missing_required({"types": {"resourceTypeGeneral": "Dataset"}})


if __name__ == "__main__":
    import json

    plan = DMSPlan(
        data_categories=["imaging"],
        metadata_standard="dcat",
        repository_name="Dryad",
        available_date="2026-09-30",
        publication_year=2026,
        license_id="CC0-1.0",
        license_uri="https://creativecommons.org/publicdomain/zero/1.0/",
        oversight_party="Data Core",
    )
    print(json.dumps(map_plan_to_datacite(plan), indent=2))

Run the tests with pytest -q test_dms_crosswalk.py; a passing run prints 2 passed. The __main__ block prints a ready-to-merge DataCite property set, and a plan built without a license_id or repository_name fails Pydantic validation at construction time — the earliest possible point to catch a DMS Plan that would mint a non-compliant record.

Gotchas

  • The repository is the publisher, not a contributor. Teams often record the trusted repository as a contributing organization, leaving publisher blank and breaking a required DataCite field. Fix: map Element 4’s repository straight to publisher, and reserve contributors for the oversight party from Element 6.
  • The sharing timeline needs dateType Available, not Issued. A plan’s “data available by” date encoded as Issued misrepresents when the data can be accessed and fails a timeline audit. Fix: always encode the DMS access timeline as a dates entry with dateType Available.
  • Oversight maps to a contributor role, not a creator. Listing the data manager as a creator inflates authorship and misstates responsibility. Fix: use contributors with contributorType DataManager (or WorkPackageLeader) so oversight is recorded without claiming authorship.

Frequently Asked Questions

Which DataCite property records the NIH DMS sharing timeline?

The sharing timeline maps to a dates entry with dateType set to Available, carrying the date the data becomes accessible. This is distinct from publicationYear, which records when the DOI is registered, and from a dateType of Issued. Encoding the DMS Plan’s “available by” commitment as an Available date makes the timeline machine-checkable, so an audit can confirm the record honors the plan rather than reading it from prose.

Where does the repository named in a DMS Plan go in DataCite metadata?

The trusted repository named in Element 4 becomes the DataCite publisher. This is a required property, and mapping the repository there — rather than into contributors — keeps the record valid and makes the preservation commitment explicit. The persistent identifier promised alongside it is the DOI itself, minted against that publisher, so the plan’s preservation and access element is captured by the publisher, the DOI, and the Available date together.

How should the oversight element be represented so it does not inflate authorship?

Record the responsible party from Element 6 as a contributor with contributorType DataManager (or WorkPackageLeader), never as a creator. The creator list is for the dataset’s authors; oversight is a stewardship role. Using the contributor role keeps responsibility visible in the metadata while preserving an accurate authorship record, which matters for both attribution and for any downstream credit or citation counting.

See the Open Science Infrastructure Planning overview for how funder alignment fits the wider governance and deposit workflow.