library(tidyverse)
library(jsonlite)
library(httr2)Before we begin, let’s load a few R packages
Motivation
Today, we are going to talk about getting data from APIs and examples of common data formats.
First, let’s have a bit of a philosophical discussion about data.
“Raw” vs “Clean” data
As data analysts, this is what we wished data looked like whenever we start a project

However, the reality, is data is rarely in that form in comes in all types of “raw” formats that need to be transformed into a “clean” format.
For example, in field of genomics, raw data looks like something like this:

Or if you are interested in analyzing data from Twitter:

Or data from Electronic Healthcare Records (EHRs):

We all have our scary spreadsheet tales. Here is Jenny Bryan from Posit and UBC actually asking for some of those spreadsheet tales on twitter.

For example, this is an actual spreadsheet from Enron in 2001:

What do we mean by “raw” data?
From https://simplystatistics.org/posts/2016-07-20-relativity-raw-data/ raw data is defined as data…
…if you have done no processing, manipulation, coding, or analysis of the data. In other words, the file you received from the person before you is untouched. But it may not be the rawest version of the data. The person who gave you the raw data may have done some computations. They have a different “raw data set”.
Where do data live?
Data lives anywhere and everywhere. Data might be stored simply in a .csv or .txt file. Data might be stored in an Excel or Google Spreadsheet. Data might be stored in large databases that require users to write special functions to interact with to extract the data they are interested in.
For example, you may have heard of the terms mySQL or MongoDB.
From Wikipedia, MySQL is defined as an open-source relational database management system (RDBMS). Its name is a combination of “My”, the name of co-founder Michael Widenius’s daughter,[7] and “SQL”, the abbreviation for Structured Query Language.
From Wikipeda, MongoDB is defined as “a free and open-source cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with schemata.”
So after reading that, we get the sense that there are multiple ways large databases can be structured, data can be formatted and interacted with. In addition, we see that database programs (e.g. MySQL and MongoDB) can also interact with each other.

We will learn more about JSON today and learn about SQL in a later lecture more formally.
Best practices on sharing data
A great article in PeerJ was written titled How to share data for collaboration, in which the authors describe a set of guidelines for sharing data:
We highlight the need to provide raw data to the statistician, the importance of consistent formatting, and the necessity of including all essential experimental information and pre-processing steps carried out to the statistician. With these guidelines we hope to avoid errors and delays in data analysis. the importance of consistent formatting, and the necessity of including all essential experimental information and pre-processing steps carried out to the statistician.

It’s a great paper that describes the information you should pass to a statistician to facilitate the most efficient and timely analysis.
Specifically:
- The raw data (or the rawest form of the data to which you have access)
- Should not have modified, removed or summarized any data; Ran no software on data
- e.g. strange binary file your measurement machine spits out
- e.g. complicated JSON file you scrapped from Twitter Application Programming Interfaces (API)
- e.g. hand-entered numbers you collected looking through a microscope
- A clean data set
- This may or may not be transforming data into a
tidydataset, but possibly yes
- This may or may not be transforming data into a
- A code book describing each variable and its values in the clean or tidy data set.
- More detailed information about the measurements in the data set (e.g. units, experimental design, summary choices made)
- Doesn’t quite fit into the column names in the spreadsheet
- Often reported in a
.md,.txtor Word file.

- An explicit and exact recipe you used to go from 1 -> 2,3

Getting data
JSON files
JSON (or JavaScript Object Notation) is a file format that stores information in human-readable, organized, logical, easy-to-access manner.
For example, here is what a JSON file looks like:
var stephanie = {
"job-title" : "Associate Professor",
"hometown" : "Baltimore, MD",
"pronouns": "she/her",
"states-lived" : {
"state1" : "Louisiana",
"state2" : "Texas",
"state3" : "Massachusetts",
"state4" : "Maryland"
}
}Some features about JSON objects:
- JSON objects are surrounded by curly braces
{} - JSON objects are written in key/value pairs
- Keys must be strings, and values must be a valid JSON data type (string, number, object, array, boolean)
- Keys and values are separated by a colon
- Each key/value pair is separated by a comma
Overview of APIs
From AWS, API stands for Application Programming Interface.
- “Application” = any software with a distinct function
- “Interface” = a contract of service between two applications. This contract defines how the two communicate with each other using requests and responses.
The API documentation contains information on how developers are to structure those requests and responses.
The purpose of APIs is enable two software components to communicate with each other using a set of definitions and protocols.
For example, the weather bureau’s software system contains daily weather data. The weather app on your phone “talks” to this system via APIs and shows you daily weather updates on your phone.
How do APIs work?
To understand how APIs work, two terms that are important are
- client. This is the application sending the request.
- server. This is the application sending the response.
So in the weather example, the bureau’s weather database is the server, and the mobile app is the client.
Four types of API architectures
There are four different ways that APIs can work depending on when and why they were created.
SOAP APIs. These APIs use Simple Object Access Protocol. Client and server exchange messages using XML. This is a less flexible API that was more popular in the past.
RPC APIs. These APIs are called Remote Procedure Calls. The client completes a function (or procedure) on the server, and the server sends the output back to the client.
Websocket APIs. Websocket API is another modern web API development that uses JSON objects to pass data. A WebSocket API supports two-way communication between client apps and the server. The server can send callback messages to connected clients, making it more efficient than REST API.
REST APIs. REST stands for Representational State Transfer (and are the most popular and flexible APIs). The client sends requests to the server as data. The server uses this client input to start internal functions and returns output data back to the client. REST defines a set of functions like GET, PUT, DELETE, etc. that clients can use to access server data. Clients and servers exchange data using HTTP.
The main feature of REST API is statelessness (i.e. servers do not save client data between requests). Client requests to the server are similar to URLs you type in your browser to visit a website. The response from the server is plain data, without the typical graphical rendering of a web page.
How to use an API?
The basic steps to using an API are:
- Obtaining an API key. This is done by creating a verified account with the API provider.
- Set up an HTTP API client. This tool allows you to structure API requests easily using the API keys received. Here, we will use functions from the
httr2package (which is the next generation of thehttrpackage). - If you don’t have an API client, you can try to structure the request yourself in your browser by referring to the API documentation.
- Once you are comfortable with the new API syntax, you can start using it in your code.
Where can I find new APIs?
New web APIs can be found on API marketplaces and API directories, such as:
- Rapid API – One of the largest global API markets (10k+ public APIs). Users to test APIs directly on the platform before committing to purchase.
- Public REST APIs – Groups REST APIs into categories, making it easier to browse and find the right one to meet your needs.
- APIForThat and APIList – Both these websites have lists of 500+ web APIs, along with in-depth information on how to use them.
GitHub API
The GitHub REST API may be of interest when studying online communities, working methods, organizational structures, communication and discussions, etc. with a focus on (open-source) software development.
Many projects that are hosted on GitHub are open-source projects with a transparent development process and communications. For private projects, which can also be hosted on GitHub, there’s understandably only a few aggregate data available.
Let’s say we want to use the GitHub REST API to find out how many of my GitHub repositories have open issues?
The API can be used for free and you can send up to 60 requests per hour if you are not authenticated (i.e. if you don’t provide an API key).
For serious data collection, this is not much, so it is recommended to sign up on GitHub and generate a personal access token that acts as API key.
This token can then be used to authenticate your API requests. Your quota is then 5000 requests per hour.
Access the API from R
There are packages for many programming languages that provide convenient access for communicating with the GitHub API, but there are no such packages (that I’m aware of) for accessing the API from R.
This means we can only access the API directly, e.g. by using the jsonlite package to fetch the data and convert it to an R list or data.frame.
Specifically, we will use the jsonlite::read_json() function to read a JSON file into a data frame.
The JSON file is located at https://api.github.com/users/stephaniehicks/repos.
github_url <- "https://api.github.com/users/stephaniehicks/repos"
library(jsonlite)
library(tidyverse)
jsonData <- read_json(github_url, simplifyVector = TRUE)
glimpse(jsonData)Rows: 30
Columns: 79
$ id <int> 160194123, 132884754, 647539937, 225501707…
$ node_id <chr> "MDEwOlJlcG9zaXRvcnkxNjAxOTQxMjM=", "MDEwO…
$ name <chr> "2018-bioinfosummer-scrnaseq", "advdatasci…
$ full_name <chr> "stephaniehicks/2018-bioinfosummer-scrnase…
$ private <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ owner <df[,19]> <data.frame[26 x 19]>
$ html_url <chr> "https://github.com/stephaniehicks/201…
$ description <chr> NA, NA, "Repo to share code for the atlas-…
$ fork <lgl> FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FAL…
$ url <chr> "https://api.github.com/repos/stephaniehic…
$ forks_url <chr> "https://api.github.com/repos/stephaniehic…
$ keys_url <chr> "https://api.github.com/repos/stephaniehic…
$ collaborators_url <chr> "https://api.github.com/repos/stephaniehic…
$ teams_url <chr> "https://api.github.com/repos/stephaniehic…
$ hooks_url <chr> "https://api.github.com/repos/stephaniehic…
$ issue_events_url <chr> "https://api.github.com/repos/stephaniehic…
$ events_url <chr> "https://api.github.com/repos/stephaniehic…
$ assignees_url <chr> "https://api.github.com/repos/stephaniehic…
$ branches_url <chr> "https://api.github.com/repos/stephaniehic…
$ tags_url <chr> "https://api.github.com/repos/stephaniehic…
$ blobs_url <chr> "https://api.github.com/repos/stephaniehic…
$ git_tags_url <chr> "https://api.github.com/repos/stephaniehic…
$ git_refs_url <chr> "https://api.github.com/repos/stephaniehic…
$ trees_url <chr> "https://api.github.com/repos/stephaniehic…
$ statuses_url <chr> "https://api.github.com/repos/stephaniehic…
$ languages_url <chr> "https://api.github.com/repos/stephaniehic…
$ stargazers_url <chr> "https://api.github.com/repos/stephaniehic…
$ contributors_url <chr> "https://api.github.com/repos/stephaniehic…
$ subscribers_url <chr> "https://api.github.com/repos/stephaniehic…
$ subscription_url <chr> "https://api.github.com/repos/stephaniehic…
$ commits_url <chr> "https://api.github.com/repos/stephaniehic…
$ git_commits_url <chr> "https://api.github.com/repos/stephaniehic…
$ comments_url <chr> "https://api.github.com/repos/stephaniehic…
$ issue_comment_url <chr> "https://api.github.com/repos/stephaniehic…
$ contents_url <chr> "https://api.github.com/repos/stephaniehic…
$ compare_url <chr> "https://api.github.com/repos/stephaniehic…
$ merges_url <chr> "https://api.github.com/repos/stephaniehic…
$ archive_url <chr> "https://api.github.com/repos/stephaniehic…
$ downloads_url <chr> "https://api.github.com/repos/stephaniehic…
$ issues_url <chr> "https://api.github.com/repos/stephaniehic…
$ pulls_url <chr> "https://api.github.com/repos/stephaniehic…
$ milestones_url <chr> "https://api.github.com/repos/stephaniehic…
$ notifications_url <chr> "https://api.github.com/repos/stephaniehic…
$ labels_url <chr> "https://api.github.com/repos/stephaniehic…
$ releases_url <chr> "https://api.github.com/repos/stephaniehic…
$ deployments_url <chr> "https://api.github.com/repos/stephaniehic…
$ created_at <chr> "2018-12-03T13:20:45Z", "2018-05-10T10:22:…
$ updated_at <chr> "2019-08-08T02:18:17Z", "2018-05-10T10:22:…
$ pushed_at <chr> "2018-12-05T17:07:09Z", "2017-12-18T17:18:…
$ git_url <chr> "git://github.com/stephaniehicks/2018-bioi…
$ ssh_url <chr> "git@github.com:stephaniehicks/2018-bioinf…
$ clone_url <chr> "https://github.com/stephaniehicks/2018-bi…
$ svn_url <chr> "https://github.com/stephaniehicks/2018-bi…
$ homepage <chr> NA, NA, NA, NA, NA, "", NA, NA, NA, NA, NA…
$ size <int> 60296, 172353, 8866, 121, 675, 26688, 20, …
$ stargazers_count <int> 4, 0, 2, 1, 0, 0, 1, 8, 0, 1, 0, 15, 3, 0,…
$ watchers_count <int> 4, 0, 2, 1, 0, 0, 1, 8, 0, 1, 0, 15, 3, 0,…
$ language <chr> "TeX", "HTML", "R", NA, NA, "R", "R", "Jup…
$ has_issues <lgl> TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRU…
$ has_projects <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, …
$ has_downloads <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, …
$ has_wiki <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, …
$ has_pages <lgl> TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, F…
$ has_discussions <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ forks_count <int> 4, 0, 1, 0, 1, 0, 0, 2, 0, 0, 0, 4, 1, 1, …
$ mirror_url <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ archived <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ disabled <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ open_issues_count <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, …
$ license <df[,5]> <data.frame[26 x 5]>
$ allow_forking <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, …
$ is_template <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALS…
$ web_commit_signoff_required <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, …
$ topics <list> <>, <>, <>, <>, <>, <>, <>, <>, <>, <>, <>…
$ visibility <chr> "public", "public", "public", "public", "p…
$ forks <int> 4, 0, 1, 0, 1, 0, 0, 2, 0, 0, 0, 4, 1, 1,…
$ open_issues <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, …
$ watchers <int> 4, 0, 2, 1, 0, 0, 1, 8, 0, 1, 0, 15, 3, 0,…
$ default_branch <chr> "master", "master", "main", "master", "mas…
We see this has returned a data frame with the argument simplifyVector which converts the output from a list to a dataframe.
However, from here, we see that there are only 30 rows (or 30 repositories). If you look on my github page, you can see there are more than 30 repositories.
What’s happening is called pagination.
At a high-level, the API is limiting the amount of items a user gets and splitting it into pages.
Formally, pagination is the process of splitting the contents or a section of a website into discrete pages. Users tend to get lost when there’s bunch of data and with pagination splitting they can concentrate on a particular amount of content. Hierarchy and paginated structure improve the readability score of the content.
In this use case Github api splits the result into 30 items per resonse, depends on the request
Solution: You should explicitly specify in your request how many items you would like to receive from server pagination engine, using formula for Github pagination api:
?page=1&per_page=<numberOfItemsYouSpecify>"
You can read more about pagination here:
Here we can visit this website:
And see there are more than 30 repos. Let’s read it into R.
github_url = "https://api.github.com/users/stephaniehicks/repos?page=1&per_page=1000"
jsonDataAll <- read_json(github_url, simplifyVector = TRUE)
dim(jsonDataAll)[1] 93 79
We now get all the public repositories! yay!
Access APIs with httr2
There are a set of basic HTTP verbs that allow you access a set of endpoints.
The basic request patterns are:
- Retrieve a single item (GET)
- Retrieve a list of items (GET)
- Create an item (POST)
- Update an item (PUT)
- Delete an item (DELETE)
Example: GitHub commits
Let’s say you want to retrieve information about the latest commits from a GitHub repository. We will use httr2 to make a request to the GitHub API for a repository of your choice. Later on we will make this an authenticated HTTP response to the GitHub API.
First, we make sure we have the httr2 package installed and loaded. We’ll also need jsonlite package for handling JSON files and dplyr for data wrangling.
library(httr2)
library(jsonlite)
library(dplyr)Now we will set up our request to the GitHub API. The GitHub API endpoint for getting the latest commits in a repository is at https://api.github.com/repos/{owner}/{repo}/commits.
For this example, we’ll look at the latest commits for the tidyverse/dplyr repository. We will use httr2::request() function to set up the request, (and later on we will add authentication – optional, but recommended for higher rate limits), and parse the response.
owner <- "tidyverse"
repo <- "dplyr"
url <- paste0("https://api.github.com/repos/", owner, "/", repo, "/commits")
response <- request(url) %>%
req_perform()
response<httr2_response>
GET https://api.github.com/repos/tidyverse/dplyr/commits
Status: 200 OK
Content-Type: application/json
Body: In memory (151553 bytes)
Next, we can see if the response was successful.
# Check if the response was successful
if (resp_status(response) == 200) {
# Parse JSON response into an R list
commits <- resp_body_json(response, simplifyVector = TRUE)
# View the first few rows of the commits data
head(commits)
} else {
message("Failed to retrieve data. Status code: ", resp_status(response))
} sha
1 e4ad5d7dfc8e5e692996fec9fea82c14a73dbb25
2 77f646ce25180395d8e04495c251ecd14cbfeb08
3 823e5983bf00bc85ae2d32f3059ce28869e73423
4 11e633b0eebc9a205ceee5d18b965f2c31af24c9
5 36539cc783474dac8a1df2fae83097d1c0eee63b
6 0d6054f46e0e78ad378e1426b54571e93cce2e34
node_id
1 C_kwDOAGIUpdoAKGU0YWQ1ZDdkZmM4ZTVlNjkyOTk2ZmVjOWZlYTgyYzE0YTczZGJiMjU
2 C_kwDOAGIUpdoAKDc3ZjY0NmNlMjUxODAzOTVkOGUwNDQ5NWMyNTFlY2QxNGNiZmViMDg
3 C_kwDOAGIUpdoAKDgyM2U1OTgzYmYwMGJjODVhZTJkMzJmMzA1OWNlMjg4NjllNzM0MjM
4 C_kwDOAGIUpdoAKDExZTYzM2IwZWViYzlhMjA1Y2VlZTVkMThiOTY1ZjJjMzFhZjI0Yzk
5 C_kwDOAGIUpdoAKDM2NTM5Y2M3ODM0NzRkYWM4YTFkZjJmYWU4MzA5N2QxYzBlZWU2M2I
6 C_kwDOAGIUpdoAKDBkNjA1NGY0NmUwZTc4YWQzNzhlMTQyNmI1NDU3MWU5M2NjZTJlMzQ
commit.author.name commit.author.email
1 Tim Taylor tim.taylor@hiddenelephants.co.uk
2 Matt Nield 64328730+matthewjnield@users.noreply.github.com
3 Maëlle Salmon maelle.salmon@yahoo.se
4 Davis Vaughan davis@rstudio.com
5 Davis Vaughan davis@rstudio.com
6 Davis Vaughan davis@rstudio.com
commit.author.date commit.committer.name commit.committer.email
1 2025-10-27T13:19:45Z GitHub noreply@github.com
2 2025-10-27T13:10:21Z GitHub noreply@github.com
3 2025-10-27T13:00:23Z GitHub noreply@github.com
4 2025-10-24T17:56:26Z GitHub noreply@github.com
5 2025-10-23T17:29:10Z GitHub noreply@github.com
6 2025-10-23T15:55:07Z GitHub noreply@github.com
commit.committer.date
1 2025-10-27T13:19:45Z
2 2025-10-27T13:10:21Z
3 2025-10-27T13:00:23Z
4 2025-10-24T17:56:26Z
5 2025-10-23T17:29:10Z
6 2025-10-23T15:55:07Z
commit.message
1 clean up .onLoad() (#7034)\n\n* clean up .onLoad()\n\n.onLoad() seemed to be setting dplyr.show_progress in a users\noptions which didn't seem neccessary. This removes that and\nmaintains current logic (although AFAICT progress bars have\nbeen deprecated anyway).\n\n* Explicitly set `default = TRUE`\n\n---------\n\nCo-authored-by: Davis Vaughan <davis@posit.co>
2 Update mention of DuckDB in README (#7101)\n\n* Update mention of DuckDB in README\n\nThis commit makes the following changes to the README regarding the mentions of DuckDB:\n\n- Removes the mention of the `duckdb` R package, which is not a `dplyr` backend, but rather a package purely for connecting to and querying a DuckDB database, like the dozens of similar packages that are specific to various database programs, and would likely be used with `dbplyr`.\n\n- Corrects the broken link for the `duckplyr` package from https://duckdblabs.github.io/duckplyr/ to https://duckplyr.tidyverse.org/\n\n- Changes the language of the mention of the `duckplyr` package to be consistent with the rest of the backend packages, following this order: name of the backend R package, use case, and underlying technology that the backend translates `dplyr` code to.\n\n* Tweaks\n\n---------\n\nCo-authored-by: Davis Vaughan <davis@posit.co>
3 docs: typo fix (#7108)\n\n* docs: typo fix\n\n* Document\n\n---------\n\nCo-authored-by: DavisVaughan <DavisVaughan@users.noreply.github.com>
4 Use finalized version of string translation helpers (#7744)\n\n* Use finalized version of string translation helpers\n\n* Use exact version of vctrs utilities
5 Refresh `na_if()` and `coalesce()` docs (#7742)\n\n* Refresh `na_if()` docs\n\n* Refresh `coalesce()` docs\n\n* Also mention `replace_when()`\n\nAfter reading https://github.com/tidyverse/dplyr/issues/5711 and https://github.com/tidyverse/dplyr/issues/6511\n\n* Show how `na_if(x, <multiple>)` fails
6 Towards C API compliance (#7741)\n\n* Use `Rf_isObject()` not `OBJECT()`\n\n* Use `Rf_charIsUTF8()` not `LEVELS()`\n\n* Conditionally define `VECTOR_PTR_RO()`\n\n* Drop dead code\n\n* Use `R_shallow_duplicate()` over `R_shallow_duplicate_attr()`\n\nBeing able to make the ALTREP wrapper would have been nice, but since you need at least 64 columns for this to even kick in, it isn't worth fighting R Core on this\n\n* Fix deref issue revealed by stricter `VECTOR_PTR_RO()`\n\nIf `.rows` is not a list, we were still calling `VECTOR_PTR_RO()` on it mistakenly\n\n* NEWS
commit.tree.sha
1 b928756f28792c5fcf8b0c16994a73042517387a
2 45aebcfdb8d894b7007c90e7bff7ef76a5f925b5
3 f01800d6d4fcb437dae68236f50efc8929c40125
4 c057e015dda6d8ca57c8f858cf56c9636fc6f2c3
5 975fe05aa21deedfbb3addcd3f96bf3bb27eb644
6 77ef658b91450391e72114a4f421a76d33c0208a
commit.tree.url
1 https://api.github.com/repos/tidyverse/dplyr/git/trees/b928756f28792c5fcf8b0c16994a73042517387a
2 https://api.github.com/repos/tidyverse/dplyr/git/trees/45aebcfdb8d894b7007c90e7bff7ef76a5f925b5
3 https://api.github.com/repos/tidyverse/dplyr/git/trees/f01800d6d4fcb437dae68236f50efc8929c40125
4 https://api.github.com/repos/tidyverse/dplyr/git/trees/c057e015dda6d8ca57c8f858cf56c9636fc6f2c3
5 https://api.github.com/repos/tidyverse/dplyr/git/trees/975fe05aa21deedfbb3addcd3f96bf3bb27eb644
6 https://api.github.com/repos/tidyverse/dplyr/git/trees/77ef658b91450391e72114a4f421a76d33c0208a
commit.url
1 https://api.github.com/repos/tidyverse/dplyr/git/commits/e4ad5d7dfc8e5e692996fec9fea82c14a73dbb25
2 https://api.github.com/repos/tidyverse/dplyr/git/commits/77f646ce25180395d8e04495c251ecd14cbfeb08
3 https://api.github.com/repos/tidyverse/dplyr/git/commits/823e5983bf00bc85ae2d32f3059ce28869e73423
4 https://api.github.com/repos/tidyverse/dplyr/git/commits/11e633b0eebc9a205ceee5d18b965f2c31af24c9
5 https://api.github.com/repos/tidyverse/dplyr/git/commits/36539cc783474dac8a1df2fae83097d1c0eee63b
6 https://api.github.com/repos/tidyverse/dplyr/git/commits/0d6054f46e0e78ad378e1426b54571e93cce2e34
commit.comment_count commit.verification.verified commit.verification.reason
1 0 TRUE valid
2 0 TRUE valid
3 0 TRUE valid
4 0 TRUE valid
5 0 TRUE valid
6 0 TRUE valid
commit.verification.signature
1 -----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJo/3FxCRC1aQ7uu5UhlAAAXDoQAB9ehIwODovHBB58bvf7uwtr\nXSzME6TX9LEmoNHHostjZsuqmxU28kHLdP9QcccCjvH7jPM0xsHBoAFGSegDMgqy\nAXTyUbCxJgPZbnuSe34F44zPinz0gvzD9SJF0htILRmT0aOJ15zh+bvDs9P1LMdq\n1/dbUSzWODleWO2fVyeQpXCuulnWpcpZY6TJZUuCVhwPFOHqUe4LVNMdxLSBucF4\nZkN6mYoRDO+YchrxHSFKdN7o6MEmxYIucIPg316mBc0rG2E1IO5O5fajFBklGals\n52DH7o/RIk3nx2Ixb5Sq37ef2iLwaGP541BJXdXCR3/Yaoy0RrZFd3UZyqwhlOCR\nTXqDTQZPZgPh4ixWTzGb7IT9iRBEAZ+jVIiejw4l+ql3Q9lA3S1dJ0VfEPaQr6KA\n1S9XPx9yBOY4zUsZa/SbSlr0kb9g7MoFcMqXRv9mM3nD8gidx7TDuw8vxTMnWLsF\nRqLj8YwJyTe2bgGVznjH3Vh/Hy7Qho+7rVZO83EKSttsLYi/8xsh1JvP9qJtjChC\nulu64PVx9hmXOK47LfuQhQQBQ5p0FNkJMto72AGv/+Tb3X0+4LVFNP9tEGg5GMsK\ns01dbxEXhfd00R+pKjbTcwAsa/83Z/oM56VArMN6EvtncTre496FbsPRKKuDRLrF\nMDF8rOd8TI/PW1xUw/TR\n=LBHt\n-----END PGP SIGNATURE-----\n
2 -----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJo/289CRC1aQ7uu5UhlAAA3CYQAEXEbErWWd9K74my1qJ/XnCx\nF5UbnaAI/oCP+BK7Lm6GC0vBE9R/7CYke4Xu3xgW6X9nn2JMOZMRjSEWxR+AohvN\n2IM9zgtJvtYD2C4LTO4UBt6tSDcqViTl42MI+zzvuE14Izi9QxTst+1ipwHDwoLI\nvLSEgZB2QWtchw+OIQPkWebBlozjaBoTAThyuE0UKHZjEC0BPDVFVIuE8QSjanXs\nbI4ZFwLH4nVWgBztxGZRuOBg/nuStjphrmcSajFXGGUr5eaZ59MJIsaNxWuji+UD\nnZQVBhpa7eHlAbzWs0+R36Z0ZJ5qwoKA2VCaf+hKUEWIbUrlXcI+uA3mGML2Hrfc\ncDhhv9RJyyzChaGsPD+StEayLoQYDBmOo6aNhmcwVvRBPNpugRJSRCnBqHadmsu3\nrHkgNk08+z+5ulHLCwWaAEgm8axnJkgsXGof/5d7zQOXdBjEs9t2CXEilSFJgPvY\njL1TEiq6BmmCP+2k6mzVsNvpChYk9gNWwE8JSWocWeaTnzj/ZR3Sfpw8luOiTl4a\nu1AqILrpoQyI0VMEA+VbDKaqiZg1Q8zxNZ4nwVz4g3Y0zsFOsZOR1xCZ8H42C5Pu\nqk7OL3qFV+irSLEqpRubDGvGGzxcplQP+TXFDZ1ls3ktRHmrwixS9an0wQY8WU0V\n11PYXdboPhvI6Gy6omIP\n=o6De\n-----END PGP SIGNATURE-----\n
3 -----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJo/2znCRC1aQ7uu5UhlAAArA8QAHrqR3PmkYnQTGK4gWalilh4\nA1PM9PhoG8I0LBAHLmlMFAxU9HWzWxj4saWTToQ6zsTSvIxh/ULAh5L7KcZxIxH5\nmcAGIMR1tj3y0gTqvJlND7B2x37IISJ7MDEDv/NbjswguM/evZg8NxgLuGygPhJ+\ntfMtRAJxNP678p2UGKtymitXm1PoxCWdxEfkN7gRQod1a+LNSJLqYZ87B4LrYJVR\n+oH54VSFhASaDTFa4Cu9Aj+Bs+p0sETaqLMu6YLpoyHiR6GWN5VNgWspfCdgSrM6\nXfsUntDN1wJqlbatjwgB/2/lqDdyEI8WCBkUOKpVATK4WWykm2kFAQGjn+1aPGZQ\nCHia3f7/FqwzX0vUTXtVmLCSu5vbfQc7O0PdVyYgI6Il1i4c93WQn7nKwtPprLcS\nmH8ZrcoweAU5uoyBd6g7nBFD9Krnq5JRck071mI7aWctgBPdSQuq7g4M622X09HR\nVU/L7MyKhsK3REFKRVy+kOb+fd7GI+T6318uieJGL2kPabsBCh0mJXziY09ql6rg\niK2cNNd/iv5pZObZmx+fjNE1hPn0oi8Xp+H6/IXusXf7qQRPVKo/PCmyJyl2nkJq\nGf16Eysi4HHKKXwsYruO/AjWNME+y2Upm5+oaagdokXbM6IRztIkoavw3Ao0HyWC\nJcHH+tbUs4p83Ri6yZ6c\n=q++/\n-----END PGP SIGNATURE-----\n
4 -----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJo+73KCRC1aQ7uu5UhlAAA5zMQABaxYxTeC1alOa/hnoD+mOH+\nHhiOE4mW5HNwGc7II/iUCE9MiKVgPAvYXIUMRkWXpStsXfZvio4Ya5eSiN7LqiY2\nmnqNlHbJe/y2IYIKwabiLYrJoOfgFS+giOn2eQNJWMonGVh5aG7rhnqeBLB+Uspq\nt4lpCVTPlX1Am0Tm05TsiU4QHpGxnqK7dHmnvQ6VchSMqsnUubgS4gKhx2n0GILc\nnzI/W3TANjLy0Dqdsf+6al/YEGsSMlaxSX/TV+0+Pkod0einP57SejL9R7dX0Uc9\niVwutnudYlLhGsjz7yhEP1tJlC7QPGkl1/Cw8HV1kLCpdfhefLhjQiYBQs1hRGFP\nH7WsVpOsPiqiWYwjbmf/W+f9S+DqdpOp3pbx/VfDAGkwxZivla0cjP8N5DYGdQHN\nfmwHHbvDtDW1Zv58y4WXIqFPqOMdZ12P+Jd3gXvcCL5B3ELllbi4We0TyAqKJyzi\nOqJAZg0m/ieGp9/Mmc4shQcaHIvXSTx9BzFkt1eQU3zefAqTZmq4vk4SrXmotUZU\nTZy6Eru/YvxiiothzXf4OLnmbClbMobNL+C6u7nLGZmdA0Ri1ilsCelJ/RqY7GaK\nRwYVS2Qfl8/KxWkM6dyLpMpHbmOY6cXjkbAtVruKBHVZrYCQk/gYiGC5GtbG2Aok\n8FQAdArJbPVCVBPQOMtg\n=ZOD4\n-----END PGP SIGNATURE-----\n
5 -----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJo+mXmCRC1aQ7uu5UhlAAAqiMQAGRACCmNC8KrhZllG3SUkT4q\nh6xVfWBDYEAvRB3wc1tTKRl/gok1dtcJQ14RVKBTTZkymZvEeEJeVBHLkkOFUE1I\nsqVWEXC34Q+t5Ki5dihpsmZ+pMhyxXfCGdyz5Wdjz4gZiz8bMCo2Y4cbwmYPgtgJ\n1n65Igsmd9/+XNu18FRylQbpxNi8UEVGe8YJwd4lft87skCCeSyv1+aNpaxqkvuB\nxoEBzJQpEOqQKhLa4NbL5HyBi8uujfJXEah2fMxeIHzEuteocx6W0sy//iEzHH9m\nETi+yaB3r1IJDRINWU21a9P3itQnY06hc0M0aPgfrVGi30TuSnF6x4IJfWbVhVp+\nH4oaWIuWSyREKzMMPInVext92NUaltdVhqQGr5nHBsqn+BnFbpia6BBFF+zp922F\nhbztlhyzIvHsgRKMix31FVreAVVsQvxdockqUAx1wJAN7wE/AYnyt0rhiLeP3mRE\nX3nA+4lCeKCzyD8OwOw8VnGNenDxSNmjPtkpJ3zVbDX9xZDcDa0YCSFpqjZ4uHoW\npCIDCiLtFKwAKUu1tKg4OCxZb3fdh1f21JpApcKFTivsq60SWIHfR46loGTyvD9y\nlPGCjAdqFyfRpnSpkJ5YNq3hxaDXU6vAoQ75O0x7S5bUUb0FlA7QgEE1h60pMRDv\nXxf2GdTFQNPlzg0Y2rWu\n=ZqI2\n-----END PGP SIGNATURE-----\n
6 -----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJo+k/bCRC1aQ7uu5UhlAAAqGgQAAnFcgZWFLmFF5VSYjwFr78w\n+hoSjTrmhYOz25dtGkWpWyYYadZftvLG7RQtQXQ8rpUyT2pvnRni1kgiVtCxtaxu\nleYoZ9FfE4O02V1CMkTCpnWp9uc1mCalwpjk9W+1Pafzgn6jubfSlWoEyd0ZOhsV\n17hvN1Mq47z0h5+1jI1pX2dRKK/2gHrkkjl5+sRW3ldEqz3dMIv9b7LDDvz4DDtJ\n5CX3tI/dFwuPeDkyPA5flqwF4PrrohwzJBScWJ4uM/Vz/LYc6OKZ+d5XF2GqWacK\n1UyIkrpOPR/01FAh+XAA5UZnlDYdNixzoA5Xv5cjL91tIwXC/7/DgZ9l1QmaUDV/\ni5BZerH1Tw4leHmbjwSyonxoWr2loOtPiB6cG9w3ufo3tz4d9CXK4iAg7NNfqOal\nhnfooXM3tK0tcm/VG6yg+XvhlMpEfx6vKVJvBv/feoXeOffZImWsI7JVMBceOAM/\n6/Mabll4oeweUuSMZn+Pg9TSxEJtK8QJdlL2EpM1Nna7blXKbiXBjlQmdN8x+6vV\n5l3pxXZopHSsGn7aSpnou8oAUcKbHpf299ynXLgQHg1Ymp448K9iqUzKVNphlpeY\nlG7XMlWz59hSuPuLQLXjJpu6EWYMwoI0bHQadTP0PqNt7KcL1a7v4VMDmoK52LjR\nD7b803QIcV7qdj0+8WfW\n=7LRx\n-----END PGP SIGNATURE-----\n
commit.verification.payload
1 tree b928756f28792c5fcf8b0c16994a73042517387a\nparent 77f646ce25180395d8e04495c251ecd14cbfeb08\nauthor Tim Taylor <tim.taylor@hiddenelephants.co.uk> 1761571185 +0000\ncommitter GitHub <noreply@github.com> 1761571185 -0400\n\nclean up .onLoad() (#7034)\n\n* clean up .onLoad()\n\n.onLoad() seemed to be setting dplyr.show_progress in a users\noptions which didn't seem neccessary. This removes that and\nmaintains current logic (although AFAICT progress bars have\nbeen deprecated anyway).\n\n* Explicitly set `default = TRUE`\n\n---------\n\nCo-authored-by: Davis Vaughan <davis@posit.co>
2 tree 45aebcfdb8d894b7007c90e7bff7ef76a5f925b5\nparent 823e5983bf00bc85ae2d32f3059ce28869e73423\nauthor Matt Nield <64328730+matthewjnield@users.noreply.github.com> 1761570621 -0400\ncommitter GitHub <noreply@github.com> 1761570621 -0400\n\nUpdate mention of DuckDB in README (#7101)\n\n* Update mention of DuckDB in README\n\nThis commit makes the following changes to the README regarding the mentions of DuckDB:\n\n- Removes the mention of the `duckdb` R package, which is not a `dplyr` backend, but rather a package purely for connecting to and querying a DuckDB database, like the dozens of similar packages that are specific to various database programs, and would likely be used with `dbplyr`.\n\n- Corrects the broken link for the `duckplyr` package from https://duckdblabs.github.io/duckplyr/ to https://duckplyr.tidyverse.org/\n\n- Changes the language of the mention of the `duckplyr` package to be consistent with the rest of the backend packages, following this order: name of the backend R package, use case, and underlying technology that the backend translates `dplyr` code to.\n\n* Tweaks\n\n---------\n\nCo-authored-by: Davis Vaughan <davis@posit.co>
3 tree f01800d6d4fcb437dae68236f50efc8929c40125\nparent 11e633b0eebc9a205ceee5d18b965f2c31af24c9\nauthor Maëlle Salmon <maelle.salmon@yahoo.se> 1761570023 +0100\ncommitter GitHub <noreply@github.com> 1761570023 -0400\n\ndocs: typo fix (#7108)\n\n* docs: typo fix\n\n* Document\n\n---------\n\nCo-authored-by: DavisVaughan <DavisVaughan@users.noreply.github.com>
4 tree c057e015dda6d8ca57c8f858cf56c9636fc6f2c3\nparent 36539cc783474dac8a1df2fae83097d1c0eee63b\nauthor Davis Vaughan <davis@rstudio.com> 1761328586 -0400\ncommitter GitHub <noreply@github.com> 1761328586 -0400\n\nUse finalized version of string translation helpers (#7744)\n\n* Use finalized version of string translation helpers\n\n* Use exact version of vctrs utilities
5 tree 975fe05aa21deedfbb3addcd3f96bf3bb27eb644\nparent 0d6054f46e0e78ad378e1426b54571e93cce2e34\nauthor Davis Vaughan <davis@rstudio.com> 1761240550 -0400\ncommitter GitHub <noreply@github.com> 1761240550 -0400\n\nRefresh `na_if()` and `coalesce()` docs (#7742)\n\n* Refresh `na_if()` docs\n\n* Refresh `coalesce()` docs\n\n* Also mention `replace_when()`\n\nAfter reading https://github.com/tidyverse/dplyr/issues/5711 and https://github.com/tidyverse/dplyr/issues/6511\n\n* Show how `na_if(x, <multiple>)` fails
6 tree 77ef658b91450391e72114a4f421a76d33c0208a\nparent 1a62a6a103165e859632acef0fa7c421d88f0994\nauthor Davis Vaughan <davis@rstudio.com> 1761234907 -0400\ncommitter GitHub <noreply@github.com> 1761234907 -0400\n\nTowards C API compliance (#7741)\n\n* Use `Rf_isObject()` not `OBJECT()`\n\n* Use `Rf_charIsUTF8()` not `LEVELS()`\n\n* Conditionally define `VECTOR_PTR_RO()`\n\n* Drop dead code\n\n* Use `R_shallow_duplicate()` over `R_shallow_duplicate_attr()`\n\nBeing able to make the ALTREP wrapper would have been nice, but since you need at least 64 columns for this to even kick in, it isn't worth fighting R Core on this\n\n* Fix deref issue revealed by stricter `VECTOR_PTR_RO()`\n\nIf `.rows` is not a list, we were still calling `VECTOR_PTR_RO()` on it mistakenly\n\n* NEWS
commit.verification.verified_at
1 2025-10-27T13:19:45Z
2 2025-10-27T13:10:21Z
3 2025-10-27T13:00:24Z
4 2025-10-24T17:56:27Z
5 2025-10-23T17:29:11Z
6 2025-10-23T15:55:08Z
url
1 https://api.github.com/repos/tidyverse/dplyr/commits/e4ad5d7dfc8e5e692996fec9fea82c14a73dbb25
2 https://api.github.com/repos/tidyverse/dplyr/commits/77f646ce25180395d8e04495c251ecd14cbfeb08
3 https://api.github.com/repos/tidyverse/dplyr/commits/823e5983bf00bc85ae2d32f3059ce28869e73423
4 https://api.github.com/repos/tidyverse/dplyr/commits/11e633b0eebc9a205ceee5d18b965f2c31af24c9
5 https://api.github.com/repos/tidyverse/dplyr/commits/36539cc783474dac8a1df2fae83097d1c0eee63b
6 https://api.github.com/repos/tidyverse/dplyr/commits/0d6054f46e0e78ad378e1426b54571e93cce2e34
html_url
1 https://github.com/tidyverse/dplyr/commit/e4ad5d7dfc8e5e692996fec9fea82c14a73dbb25
2 https://github.com/tidyverse/dplyr/commit/77f646ce25180395d8e04495c251ecd14cbfeb08
3 https://github.com/tidyverse/dplyr/commit/823e5983bf00bc85ae2d32f3059ce28869e73423
4 https://github.com/tidyverse/dplyr/commit/11e633b0eebc9a205ceee5d18b965f2c31af24c9
5 https://github.com/tidyverse/dplyr/commit/36539cc783474dac8a1df2fae83097d1c0eee63b
6 https://github.com/tidyverse/dplyr/commit/0d6054f46e0e78ad378e1426b54571e93cce2e34
comments_url
1 https://api.github.com/repos/tidyverse/dplyr/commits/e4ad5d7dfc8e5e692996fec9fea82c14a73dbb25/comments
2 https://api.github.com/repos/tidyverse/dplyr/commits/77f646ce25180395d8e04495c251ecd14cbfeb08/comments
3 https://api.github.com/repos/tidyverse/dplyr/commits/823e5983bf00bc85ae2d32f3059ce28869e73423/comments
4 https://api.github.com/repos/tidyverse/dplyr/commits/11e633b0eebc9a205ceee5d18b965f2c31af24c9/comments
5 https://api.github.com/repos/tidyverse/dplyr/commits/36539cc783474dac8a1df2fae83097d1c0eee63b/comments
6 https://api.github.com/repos/tidyverse/dplyr/commits/0d6054f46e0e78ad378e1426b54571e93cce2e34/comments
author.login author.id author.node_id
1 TimTaylor 43499035 MDQ6VXNlcjQzNDk5MDM1
2 matthewjnield 64328730 MDQ6VXNlcjY0MzI4NzMw
3 maelle 8360597 MDQ6VXNlcjgzNjA1OTc=
4 DavisVaughan 19150088 MDQ6VXNlcjE5MTUwMDg4
5 DavisVaughan 19150088 MDQ6VXNlcjE5MTUwMDg4
6 DavisVaughan 19150088 MDQ6VXNlcjE5MTUwMDg4
author.avatar_url author.gravatar_id
1 https://avatars.githubusercontent.com/u/43499035?v=4
2 https://avatars.githubusercontent.com/u/64328730?v=4
3 https://avatars.githubusercontent.com/u/8360597?v=4
4 https://avatars.githubusercontent.com/u/19150088?v=4
5 https://avatars.githubusercontent.com/u/19150088?v=4
6 https://avatars.githubusercontent.com/u/19150088?v=4
author.url author.html_url
1 https://api.github.com/users/TimTaylor https://github.com/TimTaylor
2 https://api.github.com/users/matthewjnield https://github.com/matthewjnield
3 https://api.github.com/users/maelle https://github.com/maelle
4 https://api.github.com/users/DavisVaughan https://github.com/DavisVaughan
5 https://api.github.com/users/DavisVaughan https://github.com/DavisVaughan
6 https://api.github.com/users/DavisVaughan https://github.com/DavisVaughan
author.followers_url
1 https://api.github.com/users/TimTaylor/followers
2 https://api.github.com/users/matthewjnield/followers
3 https://api.github.com/users/maelle/followers
4 https://api.github.com/users/DavisVaughan/followers
5 https://api.github.com/users/DavisVaughan/followers
6 https://api.github.com/users/DavisVaughan/followers
author.following_url
1 https://api.github.com/users/TimTaylor/following{/other_user}
2 https://api.github.com/users/matthewjnield/following{/other_user}
3 https://api.github.com/users/maelle/following{/other_user}
4 https://api.github.com/users/DavisVaughan/following{/other_user}
5 https://api.github.com/users/DavisVaughan/following{/other_user}
6 https://api.github.com/users/DavisVaughan/following{/other_user}
author.gists_url
1 https://api.github.com/users/TimTaylor/gists{/gist_id}
2 https://api.github.com/users/matthewjnield/gists{/gist_id}
3 https://api.github.com/users/maelle/gists{/gist_id}
4 https://api.github.com/users/DavisVaughan/gists{/gist_id}
5 https://api.github.com/users/DavisVaughan/gists{/gist_id}
6 https://api.github.com/users/DavisVaughan/gists{/gist_id}
author.starred_url
1 https://api.github.com/users/TimTaylor/starred{/owner}{/repo}
2 https://api.github.com/users/matthewjnield/starred{/owner}{/repo}
3 https://api.github.com/users/maelle/starred{/owner}{/repo}
4 https://api.github.com/users/DavisVaughan/starred{/owner}{/repo}
5 https://api.github.com/users/DavisVaughan/starred{/owner}{/repo}
6 https://api.github.com/users/DavisVaughan/starred{/owner}{/repo}
author.subscriptions_url
1 https://api.github.com/users/TimTaylor/subscriptions
2 https://api.github.com/users/matthewjnield/subscriptions
3 https://api.github.com/users/maelle/subscriptions
4 https://api.github.com/users/DavisVaughan/subscriptions
5 https://api.github.com/users/DavisVaughan/subscriptions
6 https://api.github.com/users/DavisVaughan/subscriptions
author.organizations_url
1 https://api.github.com/users/TimTaylor/orgs
2 https://api.github.com/users/matthewjnield/orgs
3 https://api.github.com/users/maelle/orgs
4 https://api.github.com/users/DavisVaughan/orgs
5 https://api.github.com/users/DavisVaughan/orgs
6 https://api.github.com/users/DavisVaughan/orgs
author.repos_url
1 https://api.github.com/users/TimTaylor/repos
2 https://api.github.com/users/matthewjnield/repos
3 https://api.github.com/users/maelle/repos
4 https://api.github.com/users/DavisVaughan/repos
5 https://api.github.com/users/DavisVaughan/repos
6 https://api.github.com/users/DavisVaughan/repos
author.events_url
1 https://api.github.com/users/TimTaylor/events{/privacy}
2 https://api.github.com/users/matthewjnield/events{/privacy}
3 https://api.github.com/users/maelle/events{/privacy}
4 https://api.github.com/users/DavisVaughan/events{/privacy}
5 https://api.github.com/users/DavisVaughan/events{/privacy}
6 https://api.github.com/users/DavisVaughan/events{/privacy}
author.received_events_url author.type
1 https://api.github.com/users/TimTaylor/received_events User
2 https://api.github.com/users/matthewjnield/received_events User
3 https://api.github.com/users/maelle/received_events User
4 https://api.github.com/users/DavisVaughan/received_events User
5 https://api.github.com/users/DavisVaughan/received_events User
6 https://api.github.com/users/DavisVaughan/received_events User
author.user_view_type author.site_admin committer.login committer.id
1 public FALSE web-flow 19864447
2 public FALSE web-flow 19864447
3 public FALSE web-flow 19864447
4 public FALSE web-flow 19864447
5 public FALSE web-flow 19864447
6 public FALSE web-flow 19864447
committer.node_id committer.avatar_url
1 MDQ6VXNlcjE5ODY0NDQ3 https://avatars.githubusercontent.com/u/19864447?v=4
2 MDQ6VXNlcjE5ODY0NDQ3 https://avatars.githubusercontent.com/u/19864447?v=4
3 MDQ6VXNlcjE5ODY0NDQ3 https://avatars.githubusercontent.com/u/19864447?v=4
4 MDQ6VXNlcjE5ODY0NDQ3 https://avatars.githubusercontent.com/u/19864447?v=4
5 MDQ6VXNlcjE5ODY0NDQ3 https://avatars.githubusercontent.com/u/19864447?v=4
6 MDQ6VXNlcjE5ODY0NDQ3 https://avatars.githubusercontent.com/u/19864447?v=4
committer.gravatar_id committer.url
1 https://api.github.com/users/web-flow
2 https://api.github.com/users/web-flow
3 https://api.github.com/users/web-flow
4 https://api.github.com/users/web-flow
5 https://api.github.com/users/web-flow
6 https://api.github.com/users/web-flow
committer.html_url committer.followers_url
1 https://github.com/web-flow https://api.github.com/users/web-flow/followers
2 https://github.com/web-flow https://api.github.com/users/web-flow/followers
3 https://github.com/web-flow https://api.github.com/users/web-flow/followers
4 https://github.com/web-flow https://api.github.com/users/web-flow/followers
5 https://github.com/web-flow https://api.github.com/users/web-flow/followers
6 https://github.com/web-flow https://api.github.com/users/web-flow/followers
committer.following_url
1 https://api.github.com/users/web-flow/following{/other_user}
2 https://api.github.com/users/web-flow/following{/other_user}
3 https://api.github.com/users/web-flow/following{/other_user}
4 https://api.github.com/users/web-flow/following{/other_user}
5 https://api.github.com/users/web-flow/following{/other_user}
6 https://api.github.com/users/web-flow/following{/other_user}
committer.gists_url
1 https://api.github.com/users/web-flow/gists{/gist_id}
2 https://api.github.com/users/web-flow/gists{/gist_id}
3 https://api.github.com/users/web-flow/gists{/gist_id}
4 https://api.github.com/users/web-flow/gists{/gist_id}
5 https://api.github.com/users/web-flow/gists{/gist_id}
6 https://api.github.com/users/web-flow/gists{/gist_id}
committer.starred_url
1 https://api.github.com/users/web-flow/starred{/owner}{/repo}
2 https://api.github.com/users/web-flow/starred{/owner}{/repo}
3 https://api.github.com/users/web-flow/starred{/owner}{/repo}
4 https://api.github.com/users/web-flow/starred{/owner}{/repo}
5 https://api.github.com/users/web-flow/starred{/owner}{/repo}
6 https://api.github.com/users/web-flow/starred{/owner}{/repo}
committer.subscriptions_url
1 https://api.github.com/users/web-flow/subscriptions
2 https://api.github.com/users/web-flow/subscriptions
3 https://api.github.com/users/web-flow/subscriptions
4 https://api.github.com/users/web-flow/subscriptions
5 https://api.github.com/users/web-flow/subscriptions
6 https://api.github.com/users/web-flow/subscriptions
committer.organizations_url
1 https://api.github.com/users/web-flow/orgs
2 https://api.github.com/users/web-flow/orgs
3 https://api.github.com/users/web-flow/orgs
4 https://api.github.com/users/web-flow/orgs
5 https://api.github.com/users/web-flow/orgs
6 https://api.github.com/users/web-flow/orgs
committer.repos_url
1 https://api.github.com/users/web-flow/repos
2 https://api.github.com/users/web-flow/repos
3 https://api.github.com/users/web-flow/repos
4 https://api.github.com/users/web-flow/repos
5 https://api.github.com/users/web-flow/repos
6 https://api.github.com/users/web-flow/repos
committer.events_url
1 https://api.github.com/users/web-flow/events{/privacy}
2 https://api.github.com/users/web-flow/events{/privacy}
3 https://api.github.com/users/web-flow/events{/privacy}
4 https://api.github.com/users/web-flow/events{/privacy}
5 https://api.github.com/users/web-flow/events{/privacy}
6 https://api.github.com/users/web-flow/events{/privacy}
committer.received_events_url committer.type
1 https://api.github.com/users/web-flow/received_events User
2 https://api.github.com/users/web-flow/received_events User
3 https://api.github.com/users/web-flow/received_events User
4 https://api.github.com/users/web-flow/received_events User
5 https://api.github.com/users/web-flow/received_events User
6 https://api.github.com/users/web-flow/received_events User
committer.user_view_type committer.site_admin
1 public FALSE
2 public FALSE
3 public FALSE
4 public FALSE
5 public FALSE
6 public FALSE
parents
1 77f646ce25180395d8e04495c251ecd14cbfeb08, https://api.github.com/repos/tidyverse/dplyr/commits/77f646ce25180395d8e04495c251ecd14cbfeb08, https://github.com/tidyverse/dplyr/commit/77f646ce25180395d8e04495c251ecd14cbfeb08
2 823e5983bf00bc85ae2d32f3059ce28869e73423, https://api.github.com/repos/tidyverse/dplyr/commits/823e5983bf00bc85ae2d32f3059ce28869e73423, https://github.com/tidyverse/dplyr/commit/823e5983bf00bc85ae2d32f3059ce28869e73423
3 11e633b0eebc9a205ceee5d18b965f2c31af24c9, https://api.github.com/repos/tidyverse/dplyr/commits/11e633b0eebc9a205ceee5d18b965f2c31af24c9, https://github.com/tidyverse/dplyr/commit/11e633b0eebc9a205ceee5d18b965f2c31af24c9
4 36539cc783474dac8a1df2fae83097d1c0eee63b, https://api.github.com/repos/tidyverse/dplyr/commits/36539cc783474dac8a1df2fae83097d1c0eee63b, https://github.com/tidyverse/dplyr/commit/36539cc783474dac8a1df2fae83097d1c0eee63b
5 0d6054f46e0e78ad378e1426b54571e93cce2e34, https://api.github.com/repos/tidyverse/dplyr/commits/0d6054f46e0e78ad378e1426b54571e93cce2e34, https://github.com/tidyverse/dplyr/commit/0d6054f46e0e78ad378e1426b54571e93cce2e34
6 1a62a6a103165e859632acef0fa7c421d88f0994, https://api.github.com/repos/tidyverse/dplyr/commits/1a62a6a103165e859632acef0fa7c421d88f0994, https://github.com/tidyverse/dplyr/commit/1a62a6a103165e859632acef0fa7c421d88f0994
Then, we can extract specific data from the commits including details like the commit message, author, and date. We will create a simplified data frame with just these columns.
commits_df <- tibble(
sha = commits$sha,
author = commits$commit$author$name,
date = commits$commit$author$date,
message = commits$commit$message)
commits_df# A tibble: 30 × 4
sha author date message
<chr> <chr> <chr> <chr>
1 e4ad5d7dfc8e5e692996fec9fea82c14a73dbb25 Tim Taylor 2025-10-27T… "clean…
2 77f646ce25180395d8e04495c251ecd14cbfeb08 Matt Nield 2025-10-27T… "Updat…
3 823e5983bf00bc85ae2d32f3059ce28869e73423 Maëlle Salmon 2025-10-27T… "docs:…
4 11e633b0eebc9a205ceee5d18b965f2c31af24c9 Davis Vaughan 2025-10-24T… "Use f…
5 36539cc783474dac8a1df2fae83097d1c0eee63b Davis Vaughan 2025-10-23T… "Refre…
6 0d6054f46e0e78ad378e1426b54571e93cce2e34 Davis Vaughan 2025-10-23T… "Towar…
7 1a62a6a103165e859632acef0fa7c421d88f0994 Davis Vaughan 2025-10-23T… "Regen…
8 9509c4d77c3ff7db4990984848fa457b1f415d50 Davis Vaughan 2025-10-22T… "`uset…
9 086180c08183551f3161166a510d5ffd24c94050 Jeroen Janssens 2025-10-16T… "Inclu…
10 c5fefa22da8601f486bb20f783859200dd8a6f9d Davis Vaughan 2025-10-14T… "Fix `…
# ℹ 20 more rows
Authentication
Authenticating with the GitHub API via an API key allows you to send much more requests to the API.
API access keys for the GitHub API are called personal access tokens (PAT) and the documentation explains how to generate a PAT once you have logged into your GitHub account.
To create a PAT: You can create a PAT from your GitHub account (Settings > Developer settings > Personal access tokens). It’s a good idea to only grant “read” permissions.
First, please be careful with your PATs and never publish them.
It is suggested you keep them in your .Renviron file which looks something like this on the inside:
GITHUB_PAT = <add my GitHub PAT here>
If you do not have an .Renviron file in your home directory, you can make one:
cd ~
touch .RenvironIf you want additional guidance on where you should store them, I like this post:
Assuming you have created and stored an API key in the .Renviron file in your home directory, you can fetch it with the Sys.getenv() function and use the PAT in our httr2 request.
# Read the PAT from environment variables
github_pat <- Sys.getenv("GITHUB_PAT")
# Make the GET request with PAT for authentication
response <- request(url) %>%
req_auth_bearer_token(github_pat) %>%
req_perform()Now, we check the response as before
if (resp_status(response) == 200) {
commits <- resp_body_json(response, simplifyVector = TRUE)
commits_df <- tibble(
sha = commits$sha,
author = commits$commit$author$name,
date = commits$commit$author$date,
message = commits$commit$message)
commits_df
} else {
message("Failed to retrieve data. Status code: ", resp_status(response))
}# A tibble: 30 × 4
sha author date message
<chr> <chr> <chr> <chr>
1 e4ad5d7dfc8e5e692996fec9fea82c14a73dbb25 Tim Taylor 2025-10-27T… "clean…
2 77f646ce25180395d8e04495c251ecd14cbfeb08 Matt Nield 2025-10-27T… "Updat…
3 823e5983bf00bc85ae2d32f3059ce28869e73423 Maëlle Salmon 2025-10-27T… "docs:…
4 11e633b0eebc9a205ceee5d18b965f2c31af24c9 Davis Vaughan 2025-10-24T… "Use f…
5 36539cc783474dac8a1df2fae83097d1c0eee63b Davis Vaughan 2025-10-23T… "Refre…
6 0d6054f46e0e78ad378e1426b54571e93cce2e34 Davis Vaughan 2025-10-23T… "Towar…
7 1a62a6a103165e859632acef0fa7c421d88f0994 Davis Vaughan 2025-10-23T… "Regen…
8 9509c4d77c3ff7db4990984848fa457b1f415d50 Davis Vaughan 2025-10-22T… "`uset…
9 086180c08183551f3161166a510d5ffd24c94050 Jeroen Janssens 2025-10-16T… "Inclu…
10 c5fefa22da8601f486bb20f783859200dd8a6f9d Davis Vaughan 2025-10-14T… "Fix `…
# ℹ 20 more rows
Example: Learn about Stephanie
Let’s start by using the GitHub API to learn information about myself (Stephanie Hicks). First, let’s check out https://api.github.com/users/stephaniehicks.
Now, we have decided to explore https://api.github.com/users/stephaniehicks/repos.
To use httr2, start by creating a request:
owner <- "stephaniehicks"
url <- paste0("https://api.github.com/users/", owner,"/repos")
# Make the GET request with PAT for authentication
response <- request(url) %>%
req_auth_bearer_token(github_pat) %>%
req_perform()
stephanie <- resp_body_json(response, simplifyVector = TRUE)We convert the response to a parsed JSON file (or a list).
A bit of EDA fun
Let’s have a bit of fun and explore some questions:
- How many public repositories do I have that people have forked?
stephanie$forks [1] 4 0 1 0 1 0 0 2 0 0 0 4 1 1 0 1 11 0 0 3 0 3 0 1 1
[26] 0 0 0 0 0
What’s the most popular language?
table(stephanie$language)
HTML Jupyter Notebook R Ruby
7 1 12 2
TeX
1
To find out how many repos that I have with open issues, we can just create a table:
# how many repos have open issues?
table(stephanie$open_issues)
0 1
26 4
Whew! Not as many as I thought.
Finally, I will leave you with a few other examples of using GitHub API: