Crossref API in C#

by Cyrus Gomes

Crossref API documentation: https://api.crossref.org/swagger-ui/index.html

These recipe examples were tested on July 25, 2023.

From our testing, we have found that the crossref metadata across publishers and even journals can vary considerably. As a result, it can be easier to work with one journal at a time when using the crossref API (e.g., particulary when trying to extract selected data from records).

Setup#

First, install the CURL and jq package by typing the following command in the terminal:

!sudo apt install curl jq libcurl4-openssl-dev

Then we set a directory where we want the CrossRef directory for our projects to be created:

!mkdir CrossRef

Finally, we change the directory to the folder we created:

%cd CrossRef

1. Basic Crossref API call#

Request data from the Crossref API#

We initialize a folder for the current project that we are working on. And then change to that directory

!mkdir crossref_api_call
%cd crossref_api_call

Then we utilize the %%file command to create the following makefile which will compile our program and create an executable.

%%file makefile


# Set the variable CC to gcc, which is used to build the program
CC=gcc

# Enable debugging information and enable all compiler warnings
CFLAGS=-g -Wall

# Set the bin variable as the name of the binary file we are creating
BIN=crossref_api

# Create the binary file with the name we put
all: $(BIN)

# Map any file ending in .c to a binary executable. 
# "$<" represents the .c file and "$@" represents the target binary executable
%: %.c

	# Compile the .c file using the gcc compiler with the CFLAGS and links 
	# resulting binary with the CURL library
	$(CC) $(CFLAGS) $< -o $@ -lcurl

# Clean target which removes specific files
clean:

	# Removes the binary file and an ".dSYM" (debug symbols for debugging) directories
	# the RM command used -r to remove directories and -f to force delete
	$(RM) -rf $(BIN) *.dSYM
Writing makefile

The command is used again to create our .c file which contains the code for the program

%%file crossref_api.c

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*CURL program that retrieves JSON data from the CrossRef API
This program allows custom request to be used along with the parameter*/


/* We are going to be inputting the custom email and doi like this: ./crossref_api -e "your_email@ua.edu" -d "10.1186/1758-2946-4-12"
If the arguments are missing then we use the default: "your_email@ua.edu" "10.1186/1758-2946-4-12"
*/

int main (int argc, char* argv[]) {
    
    // If arguments are invalid then return
    if (argc > 5){                                                                                      
        printf("Error. Please try again correctly.\n");
        return -1;
    }

    // Default parameter and request codes
    char parameter[100] = {};
    char request[500] = {}; 

    // If there is ./crossref_api -e/-d
    if ((argc == 1) || ((argc == 2) && ((strcmp(argv[1], "-e")==0) || (strcmp(argv[1], "-d")==0)))) {
        // These arguments run the default parameters and keeps the codes as they are
        strcat(parameter,"your_email@ua.edu");
        strcat(request, "10.1186/1758-2946-4-12");
    }

    // If there is ./crossref_api -e "your_email@ua.edu"
    else if ((argc == 3) && (strcmp(argv[1], "-e")==0)) {
        // Only the parameter code is changed
        strcat(parameter,argv[2]);
        strcat(request, "10.1186/1758-2946-4-12");
    }

    // If there is ./crossref_api -e "your_email@ua.edu" -d
    else if ((argc == 4) && (strcmp(argv[1], "-e")==0) && (strcmp(argv[3], "-d")==0)) {
        // Only the parameter code is changed
        strcat(parameter,argv[2]);
        strcat(request, "10.1186/1758-2946-4-12");
    }

    // If there is ./crossref_api -e "your_email@ua.edu" -d "10.1186/1758-2946-4-12"
    else if ((argc == 5) && (strcmp(argv[1], "-e")==0) && (strcmp(argv[3], "-d")==0)) {
        // Both the parameter and request codes are changed
        strcat(parameter,argv[2]);
        strcat(request, argv[4]);
    }

    // If there is ./crossref_api -d "10.1186/1758-2946-4-12"
    else if ((argc == 3) && (strcmp(argv[1], "-d")==0)) {
        // Only the request code is changed
        strcat(parameter,"your_email@ua.edu");
        strcat(request, argv[2]);
    }

    // If there is ./crossref_api -d "10.1186/1758-2946-4-12" -e
    else if ((argc == 4) && (strcmp(argv[1], "-d")==0) && (strcmp(argv[3], "-e")==0)) {
        // Only the request code is changed
        strcat(parameter,"your_email@ua.edu");
        strcat(request, argv[2]);
    }

    // If there is ./crossref_api -d "10.1186/1758-2946-4-12" -e "your_email@ua.edu" 
    else if ((argc == 5) && (strcmp(argv[1], "-d")==0) && (strcmp(argv[3], "-e")==0)) {
        // Both the request and parameter codes are changed
        strcat(parameter,argv[4]);
        strcat(request, argv[2]);
    }

    else {
        printf("usage: ./crossref_api [-d] request [-e] parameter\n\n");
        printf("the api_req_par program is used to retrieve json data from the CrossRef API\n\n");
        printf("optional arguments\n");
        printf("\t -d doi          optional custom doi code; default is '10.1186/1758-2946-4-12'\n");
        printf("\t -e email        optional custom email; default is 'your_email@ua.edu'\n");
        return -1;
    }

    // Initialize the CURL HTTP connection
    CURL *curl = curl_easy_init();

    // Bits of the url that are joined together later
    char api[] = "https://api.crossref.org/works/";                                                                     
    char type1[] = "?mailto=";                        
    char url[2000];

    // Check if CURL initialization is a success or not
    if (!curl) {                                                                                         
        fprintf(stderr, "init failed\n");
        return EXIT_FAILURE;
    }
        
    // Combine all the bits to produce a functioning url
    sprintf(url, "%s%s%s%s", api, request, type1, parameter);                                             
                                          
    // Set the url to which the HTTP request will be sent to
    // First parameter is for the initialized curl HTTP request, second for the option to be set, and third for the value to be set
    curl_easy_setopt(curl, CURLOPT_URL, url);

    // If result is not retrieved then output error
    CURLcode result = curl_easy_perform(curl);

    // If result is not retrieved then output error
    if (result != CURLE_OK) {                                                                            
        fprintf(stderr, "download problem: %s\n", curl_easy_strerror(result));
    }

    // Deallocate memory for the CURL connection
    curl_easy_cleanup(curl);                                                                            
    return EXIT_SUCCESS;
}
Writing crossref_api.c

The folowing program is run, and an executable is created after using the following command:

!make
# Compile the .c file using the gcc compiler with the CFLAGS and links 
# resulting binary with the CURL library
gcc -g -Wall crossref_api.c -o crossref_api -lcurl

To output the data from the CrossRef API, we enter the following command:

!./crossref_api | jq '.["message"] | {publisher, issue, title}'
{
  "publisher": "Springer Science and Business Media LLC",
  "issue": "1",
  "title": [
    "The Molecule Cloud - compact visualization of large collections of molecules"
  ]
}

Select Some Specific Data#

!./crossref_api | jq '.["message"]["container-title"]'
[
  "Journal of Cheminformatics"
]
!./crossref_api | jq '.["message"]["title"]'
[
  "The Molecule Cloud - compact visualization of large collections of molecules"
]
!./crossref_api | jq '.["message"]["author"] | length'
2

We can add our email and the custom doi to run the API call

!./crossref_api -d "10.1186/1471-2105-15-172" -e "test22@ua.edu"| jq '.'

Retrieve names from the file#

!./crossref_api  | jq '.message.author[0].given'
"Peter"
%%bash

# Algorithm to filter the first name and title for a given doi

# Calculate the number of data entries
length=$(./crossref_api | jq '.["message"]["author"] | length')

# Sleep delay
sleep 1 

# Iterate through all the data entries
for ((n = 0; n < $length; n++)); do

    # Retrieve the first and last name
    # Can also be uses as "./crossref_api -d [doi]" to input custom doi
    first=$(./crossref_api  | jq ".message.author[$n].given" | tr -d '"')
    
    # Sleep delay
    sleep 1
    
    last=$(./crossref_api | jq ".message.author[$n].family" | tr -d '"')
    
    # Sleep delay
    sleep 1
    
    # Print the first and last name
    echo "$first $last";
    
done
Peter Ertl
Bernhard Rohde

Save JSON data to a file#

This is particularly useful for downstream testing or returning to results in the future (e.g., no need to keep requesting the data from crossref, save the results to a file)

!./crossref_api | jq '.' > my_data.json

2. Crossref API call with a Loop#

%%bash

# List of DOIs
doi_List=('10.1021/acsomega.1c03250' '10.1021/acsomega.1c05512' '10.1021/acsomega.8b01647' '10.1021/acsomega.1c04287' '10.1021/acsomega.8b01834')

for doi in "${doi_List[@]}"; do 
    # Retrieve the api data for each DOI
    ./crossref_api -d "$doi" | jq '.message | {publisher, issue, title}'
    
    # Sleep delay
    sleep 1 
    
done
{
  "publisher": "American Chemical Society (ACS)",
  "issue": "36",
  "title": [
    "Navigating into the Chemical Space of Monoamine Oxidase Inhibitors by Artificial Intelligence and Cheminformatics Approach"
  ]
}
{
  "publisher": "American Chemical Society (ACS)",
  "issue": "49",
  "title": [
    "Impact of Artificial Intelligence on Compound Discovery, Design, and Synthesis"
  ]
}
{
  "publisher": "American Chemical Society (ACS)",
  "issue": "9",
  "title": [
    "How Precise Are Our Quantitative Structure–Activity Relationship Derived Predictions for New Query Chemicals?"
  ]
}
{
  "publisher": "American Chemical Society (ACS)",
  "issue": "1",
  "title": [
    "Applying Neuromorphic Computing Simulation in Band Gap Prediction and Chemical Reaction Classification"
  ]
}
{
  "publisher": "American Chemical Society (ACS)",
  "issue": "10",
  "title": [
    "QSPR Modeling of the Refractive Index for Diverse Polymers Using 2D Descriptors"
  ]
}
%%bash

# List of dois
doi_List=('10.1021/acsomega.1c03250' '10.1021/acsomega.1c05512' '10.1021/acsomega.8b01647' '10.1021/acsomega.1c04287' '10.1021/acsomega.8b01834')

for doi in "${doi_List[@]}"; do 

    # Retrieve the title for the DOI
    ./crossref_api -d "$doi" | jq '.["message"]["title"][0]'

    # Sleep delay
    sleep 1 

done
"Navigating into the Chemical Space of Monoamine Oxidase Inhibitors by Artificial Intelligence and Cheminformatics Approach"
"Impact of Artificial Intelligence on Compound Discovery, Design, and Synthesis"
"How Precise Are Our Quantitative Structure–Activity Relationship Derived Predictions for New Query Chemicals?"
"Applying Neuromorphic Computing Simulation in Band Gap Prediction and Chemical Reaction Classification"
"QSPR Modeling of the Refractive Index for Diverse Polymers Using 2D Descriptors"
%%bash

# List of dois
doi_List=('10.1021/acsomega.1c03250' '10.1021/acsomega.1c05512' '10.1021/acsomega.8b01647' '10.1021/acsomega.1c04287' '10.1021/acsomega.8b01834')

for doi in "${doi_List[@]}";do 

    # Retrieve the author name
    ./crossref_api -d "$doi" | jq '.["message"]["author"][].affiliation[0].name'
    
    # Sleep delay
    sleep 1

done
"Department of Pharmaceutical Chemistry and Analysis, Amrita School of Pharmacy, Amrita Vishwa Vidyapeetham, AIMS Health Sciences Campus, Kochi 682041, India"
"Department of Pharmaceutical Chemistry and Analysis, Amrita School of Pharmacy, Amrita Vishwa Vidyapeetham, AIMS Health Sciences Campus, Kochi 682041, India"
"Department of Pharmaceutical Chemistry and Analysis, Amrita School of Pharmacy, Amrita Vishwa Vidyapeetham, AIMS Health Sciences Campus, Kochi 682041, India"
"Department of Pharmaceutical Chemistry and Analysis, Amrita School of Pharmacy, Amrita Vishwa Vidyapeetham, AIMS Health Sciences Campus, Kochi 682041, India"
"Department of Pharmaceutical Chemistry and Analysis, Amrita School of Pharmacy, Amrita Vishwa Vidyapeetham, AIMS Health Sciences Campus, Kochi 682041, India"
"Department of Pharmaceutics and Industrial Pharmacy, College of Pharmacy, Taif University, P.O. Box 11099, Taif 21944, Saudi Arabia"
"Department of Pharmaceutical Chemistry, College of Pharmacy, Jouf University, Sakaka, Al Jouf 72341, Saudi Arabia"
"Department of Pharmaceutical Chemistry and Analysis, Amrita School of Pharmacy, Amrita Vishwa Vidyapeetham, AIMS Health Sciences Campus, Kochi 682041, India"
"Department of Life Science Informatics and Data Science, B-IT, LIMES Program Unit Chemical Biology and Medicinal Chemistry, Rheinische Friedrich-Wilhelms-Universität, Friedrich-Hirzebruch-Allee 6, D-53115 Bonn, Germany"
"Department of Life Science Informatics and Data Science, B-IT, LIMES Program Unit Chemical Biology and Medicinal Chemistry, Rheinische Friedrich-Wilhelms-Universität, Friedrich-Hirzebruch-Allee 6, D-53115 Bonn, Germany"
"Department of Life Science Informatics and Data Science, B-IT, LIMES Program Unit Chemical Biology and Medicinal Chemistry, Rheinische Friedrich-Wilhelms-Universität, Friedrich-Hirzebruch-Allee 6, D-53115 Bonn, Germany"
"Drug Theoretics and Cheminformatics Laboratory, Department of Pharmaceutical Technology, Jadavpur University, Kolkata 700 032, India"
"Drug Theoretics and Cheminformatics Laboratory, Department of Pharmaceutical Technology, Jadavpur University, Kolkata 700 032, India"
"Interdisciplinary Center for Nanotoxicity, Department of Chemistry, Physics and Atmospheric Sciences, Jackson State University, Jackson, Mississippi 39217, United States"
"Department of Chemical and Biomolecular Engineering, The Ohio State University, Columbus, Ohio 43210, United States"
"Department of Chemical and Biomolecular Engineering, The Ohio State University, Columbus, Ohio 43210, United States"
"Department of Chemical and Biomolecular Engineering, The Ohio State University, Columbus, Ohio 43210, United States"
"Department of Chemical and Biomolecular Engineering, The Ohio State University, Columbus, Ohio 43210, United States"
"Department of Pharmacoinformatics, National Institute of Pharmaceutical Educational and Research (NIPER), Chunilal Bhawan, 168, Manikata Main Road, 700054 Kolkata, India"
"Department of Coatings and Polymeric Materials, North Dakota State University, Fargo, North Dakota 58108-6050, United States"
"Drug Theoretics and Cheminformatics Laboratory, Division of Medicinal and Pharmaceutical Chemistry, Department of Pharmaceutical Technology, Jadavpur University, 700032 Kolkata, India"

3. Crossref API call for journal information#

We change the directory back to the CrossRef folder to create a new one for our project

%cd ..

We set a directory where we want the the jornal_api program to be made

!mkdir journal_api

Then we change the directory to the folder we created

%cd journal_api

Then we utilize the %%file command to create the following makefile which will compile our program and create an executable.

%%file makefile

# Set the variable CC to gcc, which is used to build the program
CC=gcc

# Enable debugging information and enable all compiler warnings
CFLAGS=-g -Wall

# Set the bin variable as the name of the binary file we are creating
BIN=journal_api

# Create the binary file with the name we put
all: $(BIN)

# Map any file ending in .c to a binary executable. 
# "$<" represents the .c file and "$@" represents the target binary executable
%: %.c

	# Compile the .c file using the gcc compiler with the CFLAGS and links 
	# resulting binary with the CURL library
	$(CC) $(CFLAGS) $< -o $@ -lcurl

# Clean target which removes specific files
clean:

	# Remove the binary file and an ".dSYM" (debug symbols for debugging) directories
	# the RM command used -r to remove directories and -f to force delete
	$(RM) -rf $(BIN) *.dSYM
Overwriting makefile

The command is used again to create our .c file which contains the code for the program

%%file journal_api.c

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*CURL program that retrieves the journal JSON data from the CrossRef API
This program allows custom request to be used along with the parameter*/


/* We are going to be inputting the custom email and issn with query like this: ./crossref_api -e "your_email@ua.edu" -i "1471-2105"
If the arguments are missing then we use the default: "your_email@ua.edu" "1471-2105"
*/

int main (int argc, char* argv[]) {
    
    // If arguments are invalid then return
    if (argc > 5){                                                                                      
        printf("Error. Please try again correctly.\n");
        return -1;
    }

    // Default parameter and request codes
    char parameter[100] = {};
    char request[500] = {}; 

    // If there is ./crossref_api -e/-i
    if ((argc == 1) || ((argc == 2) && ((strcmp(argv[1], "-e")==0) || (strcmp(argv[1], "-i")==0)))) {
        // These arguments run the default parameters and keeps the codes as they are
        strcat(parameter,"your_email@ua.edu");
        strcat(request, "1471-2105");
    }

    // If there is ./crossref_api -e "your_email@ua.edu"
    else if ((argc == 3) && (strcmp(argv[1], "-e")==0)) {
        // Only the parameter code is changed
        strcat(parameter,argv[2]);
        strcat(request, "1471-2105");
    }

    // If there is ./crossref_api -e "your_email@ua.edu" -i
    else if ((argc == 4) && (strcmp(argv[1], "-e")==0) && (strcmp(argv[3], "-i")==0)) {
        // Only the parameter code is changed
        strcat(parameter,argv[2]);
        strcat(request, "1471-2105");
    }

    // If there is ./crossref_api -e "your_email@ua.edu" -i "1471-2105"
    else if ((argc == 5) && (strcmp(argv[1], "-e")==0) && (strcmp(argv[3], "-i")==0)) {
        // Both the parameter and request codes are changed
        strcat(parameter,argv[2]);
        strcat(request, argv[4]);
    }

    // If there is ./crossref_api -i "1471-2105"
    else if ((argc == 3) && (strcmp(argv[1], "-i")==0)) {
        // Only the request code is changed
        strcat(parameter,"your_email@ua.edu");
        strcat(request, argv[2]);
    }

    // If there is ./crossref_api -i "1471-2105" -e
    else if ((argc == 4) && (strcmp(argv[1], "-i")==0) && (strcmp(argv[3], "-e")==0)) {
        // Only the request code is changed
        strcat(parameter,"your_email@ua.edu");
        strcat(request, argv[2]);
    }

    // If there is ./crossref_api -i "1471-2105" -e "your_email@ua.edu" 
    else if ((argc == 5) && (strcmp(argv[1], "-i")==0) && (strcmp(argv[3], "-e")==0)) {
        // Both the request and parameter codes are changed
        strcat(parameter,argv[4]);
        strcat(request, argv[2]);
    }

    else {
        printf("usage: ./crossref_api [-i] request [-e] parameter\n\n");
        printf("the api_req_par program is used to retrieve json data from the CrossRef API\n\n");
        printf("optional arguments\n");
        printf("\t -i issn with query         optional custom issn code; default is '1471-2105'\n");
        printf("\t -e email                   optional custom email; default is 'your_email@ua.edu'\n");
        return -1;
    }

    // Initialize the CURL HTTP connection
    CURL *curl = curl_easy_init();

    // Bits of the url that are joined together later
    char api[] = "https://api.crossref.org/journals/";                                                                     
    char type1[] = "?mailto=";                        
    char url[2000];

    // Check if CURL initialization is a success or not
    if (!curl) {                                                                                         
        fprintf(stderr, "init failed\n");
        return EXIT_FAILURE;
    }
        
    // Combine all the bits to produce a functioning url
    sprintf(url, "%s%s%s%s", api, request, type1, parameter);                                             
                                          
    
    // Set the url to which the HTTP request will be sent to
    // first parameter is for the initialized curl HTTP request, second for the option to be set, and third for the value to be set
    curl_easy_setopt(curl, CURLOPT_URL, url);

    // If result is not retrieved then output error
    CURLcode result = curl_easy_perform(curl);

    // If result is not retrieved then output error
    if (result != CURLE_OK) {                                                                            
        fprintf(stderr, "download problem: %s\n", curl_easy_strerror(result));
    }

    // Deallocate memory for the CURL connection
    curl_easy_cleanup(curl);                                                                            
    return EXIT_SUCCESS;
}
Writing journal_api.c
!make
# Compile the .c file using the gcc compiler with the CFLAGS and links 
# resulting binary with the CURL library
gcc -g -Wall journal_api.c -o journal_api -lcurl
!./journal_api | jq '.message | {publisher, coverage, title}'
{
  "publisher": "Springer (Biomed Central Ltd.)",
  "coverage": {
    "affiliations-current": 0,
    "similarity-checking-current": 1,
    "descriptions-current": 0,
    "ror-ids-current": 0,
    "funders-backfile": 0.1991365353480842,
    "licenses-backfile": 0.6345565749235474,
    "funders-current": 0.7076382791922738,
    "affiliations-backfile": 0,
    "resource-links-backfile": 0.6340169095161,
    "orcids-backfile": 0.1578521316783594,
    "update-policies-current": 1,
    "ror-ids-backfile": 0,
    "orcids-current": 0.2642669007901668,
    "similarity-checking-backfile": 0.9999100557654254,
    "references-backfile": 0.9846195358877496,
    "descriptions-backfile": 0,
    "award-numbers-backfile": 0.1800683576182767,
    "update-policies-backfile": 0.7215326497571506,
    "licenses-current": 1,
    "award-numbers-current": 0.6382791922739245,
    "abstracts-backfile": 0.4049289440546861,
    "resource-links-current": 1,
    "abstracts-current": 0.9754170324846356,
    "references-current": 0.9982440737489024
  },
  "title": "BMC Bioinformatics"
}

4. Crossref API - Get article DOIs for a journal#

Request DOI data from crossref API#

We change the directory back to the CrossRef folder to create a new one for our project

%cd ..

We set a directory where we want the the jornal_api program to be made

!mkdir journal_doi_api

Then we change the directory to the folder we created

%cd journal_doi_api

Then we utilize the %%file command to create the following makefile which will compile our program and create an executable.

%%file makefile

# Set the variable CC to gcc, which is used to build the program
CC=gcc

# Enable debugging information and enable all compiler warnings
CFLAGS=-g -Wall

# Set the bin variable as the name of the binary file we are creating
BIN=journal_doi

# Create the binary file with the name we put
all: $(BIN)

# Map any file ending in .c to a binary executable. 
# "$<" represents the .c file and "$@" represents the target binary executable
%: %.c

	# Compile the .c file using the gcc compiler with the CFLAGS and links 
	# resulting binary with the CURL library
	$(CC) $(CFLAGS) $< -o $@ -lcurl

# Clean target which removes specific files
clean:

	# Remove the binary file and an ".dSYM" (debug symbols for debugging) directories
	# the RM command used -r to remove directories and -f to force delete
	$(RM) -rf $(BIN) *.dSYM
Overwriting makefile

The command is used again to create our .c file which contains the code for the program

%%file journal_doi.c

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* CURL program that retrieves the journal JSON data from the CrossRef API
This program allows custom request to be used along with the parameter */


/* We are going to be inputting the custom email and issn with query like this: ./crossref_api -e "your_email@ua.edu" -i "1471-2105"
If the arguments are missing then we use the default: "your_email@ua.edu" "1471-2105"
*/

int main (int argc, char* argv[]) {
    
    // If arguments are invalid just return
    if (argc > 5){                                                                                      
        printf("Error. Please try again correctly.\n");
        return -1;
    }

    // Default parameter and request codes
    char parameter[100] = {};
    char request[500] = {}; 

    // If there is ./crossref_api -e/-i
    if ((argc == 1) || ((argc == 2) && ((strcmp(argv[1], "-e")==0) || (strcmp(argv[1], "-i")==0)))) {
        // These arguments run the default parameters and keeps the codes as they are
        strcat(parameter,"your_email@ua.edu");
        strcat(request, "1471-2105");
    }

    // If there is ./crossref_api -e "your_email@ua.edu"
    else if ((argc == 3) && (strcmp(argv[1], "-e")==0)) {
        // Only the parameter code is changed
        strcat(parameter,argv[2]);
        strcat(request, "1471-2105");
    }

    // If there is ./crossref_api -e "your_email@ua.edu" -i
    else if ((argc == 4) && (strcmp(argv[1], "-e")==0) && (strcmp(argv[3], "-i")==0)) {
        // Only the parameter code is changed
        strcat(parameter,argv[2]);
        strcat(request, "1471-2105");
    }

    // If there is ./crossref_api -e "your_email@ua.edu" -i "1471-2105"
    else if ((argc == 5) && (strcmp(argv[1], "-e")==0) && (strcmp(argv[3], "-i")==0)) {
        // Both the parameter and request codes are changed
        strcat(parameter,argv[2]);
        strcat(request, argv[4]);
    }

    // If there is ./crossref_api -i "1471-2105"
    else if ((argc == 3) && (strcmp(argv[1], "-i")==0)){
        // Only the request code is changed
        strcat(parameter,"your_email@ua.edu");
        strcat(request, argv[2]);
    }

    // If there is ./crossref_api -i "1471-2105" -e
    else if ((argc == 4) && (strcmp(argv[1], "-i")==0) && (strcmp(argv[3], "-e")==0)) {
        // Only the request code is changed
        strcat(parameter,"your_email@ua.edu");
        strcat(request, argv[2]);
    }

    // If there is ./crossref_api -i "1471-2105" -e "your_email@ua.edu" 
    else if ((argc == 5) && (strcmp(argv[1], "-i")==0) && (strcmp(argv[3], "-e")==0)) {
        // Both the request and parameter codes are changed
        strcat(parameter,argv[4]);
        strcat(request, argv[2]);
    }

    else{
        printf("usage: ./crossref_api [-i] request [-e] parameter\n\n");
        printf("the api_req_par program is used to retrieve json data from the CrossRef API\n\n");
        printf("optional arguments\n");
        printf("\t -i issn with query         optional custom issn code; default is '1471-2105'\n");
        printf("\t -e email                   optional custom email; default is 'your_email@ua.edu'\n");
        return -1;
    }

    // Initialize the CURL HTTP connection
    CURL *curl = curl_easy_init();

    // Bits of the url that are joined together later
    char api[] = "https://api.crossref.org/journals/";                                                                     
    char type1[] = "&mailto=";                        
    char url[2000];

    // Check if CURL initialization is a success or not
    if (!curl) {                                                                                         
        fprintf(stderr, "init failed\n");
        return EXIT_FAILURE;
    }
        
    // Combine all the bits to produce a functioning url
    sprintf(url, "%s%s%s%s", api, request, type1, parameter);                                             
                                          
    
    // Set the url to which the HTTP request will be sent to
    // first parameter is for the initialized curl HTTP request, second for the option to be set, and third for the value to be set
    curl_easy_setopt(curl, CURLOPT_URL, url);

    // If result is not retrieved then output error
    CURLcode result = curl_easy_perform(curl);

    // If result is not retrieved then output error
    if (result != CURLE_OK){                                                                            
        fprintf(stderr, "download problem: %s\n", curl_easy_strerror(result));
    }

    // Deallocate memory for the CURL connection
    curl_easy_cleanup(curl);                                                                            
    return EXIT_SUCCESS;
}
Writing journal_doi.c
!make
# Compile the .c file using the gcc compiler with the CFLAGS and links 
# resulting binary with the CURL library
gcc -g -Wall journal_doi.c -o journal_doi -lcurl
!./journal_doi -i "1471-2105/works?filter=from-pub-date:2014,until-pub-date:2014&select=DOI"| jq '.' | head -n 10
{
  "status": "ok",
  "message-type": "work-list",
  "message-version": "1.0.0",
  "message": {
    "facets": {},
    "total-results": 620,
    "items": [
      {
        "DOI": "10.1186/1471-2105-15-s10-p32"

By default, 20 results are displayed. Crossref allows up to 1000 returned results using the rows parameter. To get all 619 results, we can increase the number of returned rows.

We add the following to our query “&rows=700” to view all results

!./journal_doi -i "1471-2105/works?filter=from-pub-date:2014,until-pub-date:2014&select=DOI&rows=700"| jq '.' > dois_save.json

Extract DOIs#

!cat dois_save.json | jq '.["message"]["items"][:5][].DOI'
"10.1186/1471-2105-15-s10-p32"
"10.1186/1471-2105-15-s16-s13"
"10.1186/s12859-014-0411-1"
"10.1186/1471-2105-15-s10-p24"
"10.1186/1471-2105-15-318"
!cat dois_save.json | jq '.["message"]["items"][].DOI' | wc -l
619

What if we have more than 1000 results in a single query?

For example, if we wanted the DOIs from BMC Bioinformatics for years 2014 through 2016?

!./journal_doi -i "1471-2105/works?filter=from-pub-date:2014,until-pub-date:2016&select=DOI"| jq '.' | head -n 10
{
  "status": "ok",
  "message-type": "work-list",
  "message-version": "1.0.0",
  "message": {
    "facets": {},
    "total-results": 1773,
    "items": [
      {
        "DOI": "10.1186/s12859-015-0468-5"

For example, if we wanted the DOIs from BMC Bioinformatics for years 2014 through 2016, we see that there are 1772 DOIs:

!./journal_doi -i "1471-2105/works?filter=from-pub-date:2014,until-pub-date:2016&select=DOI"| jq '.["message"]["total-results"]'
1772

Here we see that the total results is over 1000 (total-results: 1772). An additional parameter that we can use with crossref API is called “offset”. The offset option allows us to select sets of records and define a starting position (e.g., the first 1000, and then the second set of up to 1000.)

We add the %%bash command run the whole loop

%%bash

# Retrieve the number of results
length=$(./journal_doi -i "1471-2105/works?filter=from-pub-date:2014,until-pub-date:2016&select=DOI" | jq '.["message"]["total-results"]')

# Sleep delay
sleep 1

# Iterate throught the results with for loop using the offset option
for ((n = 0; n < $length; n += 1000)); do
    
    # Retrieve the doi for each id and append to the dois_save2.txt
    ./journal_doi -i "1471-2105/works?filter=from-pub-date:2014,until-pub-date:2016&select=DOI&rows=1000&offset=$n" | jq '.["message"]["items"][].DOI' >> dois_save2.txt
    
    # Sleep delay
    sleep 1 

done
!head dois_save2.txt
"10.1186/s12859-015-0538-8"
"10.1186/1471-2105-16-s18-s5"
"10.1186/s12859-015-0621-1"
"10.1186/s12859-015-0468-5"
"10.1186/s12859-015-0717-7"
"10.1186/s12859-016-0985-x"
"10.1186/1471-2105-15-172"
"10.1186/s12859-014-0411-1"
"10.1186/1471-2105-16-s15-p13"
"10.1186/1471-2105-15-s10-p24"
!cat dois_save2.txt | wc -l
1772