PID/DOI Guide¶
This guide describes how to generate PIDs (DOIs) for resources in the Språkbanken Metadata
repository. A Resources are assigned a PID with the
gen_pids/gen_pids.py script, which is run periodically on the server.
All types of resources, including collections should have a PID. The PID is stored in the metadata YAML file for the resource and is also shown on the Språkbanken Text website. The PID/DOI is generated by the DataCite service.
Terminology¶
- data set: (previously called resource) a resource which is not an analysis or utility, (i.e. a corpus, lexicon or model).
- PID/DOI: a unique identifier for a resource, generated by DataCite. A PID is a persistent identifier, and a DOI is a type of PID. In this project, we use the terms PID and DOI interchangeably.
- DMS (record): DataCite Metadata Schema (record): what we construct and send to DataCite to get (or update) a DOI
- Metadata API: Språkbanken Text's API for getting information out of our repo
- SND: Swedish National Data Service, which is the organization that manages the DOI service for Swedish research data. SND is a member of DataCite and has an account with them. SND has provided us with a test account and a production account for generating DOIs.
Method¶
The gen_pids/gen_pids.py script checks every resource in the Språkbanken Metadata
repository for a DOI:
- If it does not exist, create a DMS record and add DOI to Metadata YAML file.
- (Add existing Handle if possible: We don't do that - Markus' decision.)
- Update DMS record and fix relation between collection and members.
In more technical detail:
gen_pids.pyis called periodically by cron on k2 which should:- Read all data sets (including collections)
- Iterated over all data sets (including collections):
- If data set has no AlternateIdentifier, look up if it already has a Handle and set it.
- If data set has no PID, generate a DOI (via DataCite API) and add it to the metadata YAML file.
- Iterate over all collections:
- Set DMS-12-RelatedIdentifier to HasPart for all members of each collection (found in YAML
resourcesfield). - Set DMS-12-RelatedIdentifier to IsPartOf for each member of each collection.
- Update DMS record (via DataCite API).
- Set DMS-12-RelatedIdentifier to HasPart for all members of each collection (found in YAML
Notes on gen_pids.py¶
- Resources with
unlisted=trueare skipped (no PID/DOI is generated). - Script will only update an existing DataCite record if it is older than the YAML record (
updatedfield) or if run with the '--force_update' flag. - The login credentials to DataCite saved in
/home/fksbwww/.netrconk2(credentials were received from SND and can be found in Språkbanken Text's safe). - When testing locally with one of the test repositories, you can enter the credentials in
gen_pids/settings.py(DMS_URL, DMS_REPOID and DMS_AUTH_PASSWORD) instead of using the netrc file. Remember to remove them before committing the code. - The
identifierstag in JSON is calledalternateIdentifiersin XML format (https://support.datacite.org/docs/what-is-the-identifiers-attribute-in-the-rest-api)
DataCite Metadata Schema (DMS)¶
This is what WE have to generate to get a DOI. Shouldn't be a problem as the Metadata in our repository is generously populated. (Source: DataCite Metadata Schema Documentation)
M - Mandatory. R - recommended. 1 - 1 value allowed. n - multiple values allowed.
- M1. Identifier. (10.21384/foo; "DOI"). Let DataCite autogen a DOI (4-4 chars) (https://support.datacite.org/docs/api-create-dois)
- Mn. Creator. May be a corporate/institutional or personal name. (+ROR/ORCID) Comment from SND: även där blir det nog Språkbanken Text
- Mn. Title. Title of dataset in multiple languages.
- M1. Publisher. "Språkbanken Text"? Eller "Språkbanken"? (+ROR) Comment from SND: organisationen ansvarig för att tillhandlahålla resursen så i ert fall borde det vara Språkbanken Text då resurserna ligger i erat repositorie.
- M1. PublicationYear. Not in YAML, but add it. Update later. Possibly weClarin repos can provide some dates.
- Rn. Subject. språkteknologi; nyckelord (see below). Choose the 1st ("Svenska ...")
- Rn. Contributor. The institution and/or person responsible for... (+ROR/ORCID). Wait.
- Rn. Date. Several types. Wait.
- O1. Language. Primary language. https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes. Use 39.3!
- M1. ResourceType. +subtype. Dataset/Collection; "Dataset"/"lexicon"
- On. AlternateIdentifier: ex Handle. From SweClarin repos.
- Rn. RelatedIdentifier. Id or related resources. Ex: IsVersionOf, HasPart/IsPartOf (collection - and vice versa), Obsoletes/IsObsoletedBy (successor!)
- On. Size. Free format. State bytes and tokens.
- On. Format. File ext or MIME type.
- O1. Version. (leave out for now) Suggested practice: track major_version.minor_version. Register a new identifier for a major version change. Use with 11 and 12.
- On. Rights.
- Rn. Description. Take short description. Filter HTML.
- Rn. GeoLocation. Named place or coord. Comment from SND: skulle nog skippa att fylla i något där.
- On. Funding reference. VR?
- On. RelatedItem. Where resource does not have an id.
Also see the SND guide.
More DataCite info¶
Viewing a DMS record¶
Insert a resource ID in the following URL to view the DMS record for that resource:
REST API usage¶
- create DMS record: https://support.datacite.org/docs/api-create-dois
- update DMS record: https://support.datacite.org/docs/updating-metadata-with-the-rest-api
- test-prefix, Support > Datacite.org > Support > Testing DOI domain, testprefix
- create code examples: https://support.datacite.org/reference/put_dois-id
- API guide
- Comment from SND:
För API-anrop så har DataCite relativt snälla regler med en ganska hög gräns: https://support.datacite.org/docs/is-there-a-rate-limit-for-making-requests-against-the-datacite-apis. Ibland kan API:et ha väldigt hög belastning så kan ta lite tid med första körningen. Det går göra flera anrop för att updatera metadatan så om metadatan för en collection ska updateras med nya relatedIdentifier så är det bara att köra en nytt anrop med den nya metadatan.
DataCite references¶
- metadata store API guide
- metadata schema documentation
- metadata schema release landing page, use 4.5 (not 4.4)
- reference for JSON structure
- XML to JSON mapping
- API reference for adding DOIs
- DOI creation examples
DataCite rate limit¶
- 3000 requests in a 5 minute window. requests that come via doi.org Content Negotiation of 1000 requests in a 5
minute window. But, since 2025Q3 there seems to be an "alternate limit" of 300-500 requests every 5 minutes. To
handle this,
gen_pids.pypauses for 5 minutes every 300 requests. We also add a User-agent to the header. - https://support.datacite.org/reference/introduction#upcoming-changes
- https://support.datacite.org/docs/api
- https://support.datacite.org/docs/rate-limit
Changing a resource id (slug) from A to B¶
In the metadata repository, rename the metadata file from A.yaml to B.yaml (A and B are resource IDs).
On DataCite:
- Go to https://datacite.org and hit "Member login" to sign in to Fabrica.
- Find the metadata record/DOI.
- Click "Update DOI (form)".
- Update the following fields (change A to B):
- URL
- Alternate identifier
- Check that the update was successful by querying the API:
https://api.datacite.org/dois?client-id=SND.SPRKB&query=identifiers.identifier:<A>%20AND%20identifiers.identifierType:slug&detail=true%22
Further info¶
SND¶
- https://snd.gu.se/sv/beskriv-och-dela-data/pid-tjanster-doi-epic
- https://snd.gu.se/sv/hantera-data/fardigstalla-tillgangliggora/PID
Contact persons at SND for questions about DataCite and DOIs:
Python packages¶
- Python package to work with Document Object Identifier (DOI): https://github.com/papis/python-doi
- Python package for DataCite
Usage examples for gen_pids.py¶
# Test gen_pids, don't write yaml or update DataCite
uv run -m python gen_pids.py --debug --dry-run
# Create DOIs for resources without them (don't update)
uv run -m python gen_pids.py --debug --no-update
# Test one resource
uv run -m python gen_pids.py --debug --dry-run --file corpus/attasidor.yaml
# Force update of one
uv run -m gen_pids.gen_pids --debug --force-update --file corpus/attasidor.yaml
# Force update all resources
python gen_pids.py --debug --force-update
Other useful commands¶
- Finding successors in YAML directory:
grep -lzrP "successors:\n - .+\n" . - Removing "doi:" line from all YAML files:
grep -rl 'doi:' yaml | xargs sed -i '/^doi:/d'
Geting DataCite data for a certain year¶
To check how many posts have been updated or created within a certain year use the following calls (and update the year param in the end of the URL):
- https://api.datacite.org/dois?page[size]=1000&prefix=10.23695&client-id=SND.SPRKB&&query=dates.dateType:Updated%20AND%20dates.date:2026
- https://api.datacite.org/dois?page[size]=1000&prefix=10.23695&client-id=SND.SPRKB&&query=dates.dateType:Created%20AND%20dates.date:2026
This is used for "återrapportering" within Språkbanken.