Consumo de API REST en R
Autentíquese con claves de API, pagine los resultados y almacene las respuestas de la API.
Consumo de API REST en R es una lección gratuita de R Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de R Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de R Academy incluye 4 lecciones en total.
Conceptos de las API REST
Las API REST utilizan métodos HTTP (GET, POST, PUT, DELETE) sobre URL de recursos. Las respuestas suelen estar en formato JSON. Las API pueden requerir autenticación, gestionar la paginación y aplicar límites de frecuencia. Un buen cliente de API en R gestiona los tres aspectos.
library(httr2)
# REST API anatomy:
# Base URL: https://api.example.com/v1
# Resources: /users, /products, /orders
# Methods:
# GET /users -> list users
# POST /users -> create user
# GET /users/42 -> get user 42
# PUT /users/42 -> update user 42
# DELETE /users/42 -> delete user 42
# Query parameters for filtering/pagination:
# GET /users?page=2&size=20&sort=name
cat('REST = stateless + resource-based + HTTP methods')Autenticación con tokens Bearer
La mayoría de las API modernas utilizan tokens Bearer (OAuth 2.0). Guarde el token en una variable de entorno mediante Sys.setenv() o en un archivo .Renviron. Nunca escriba tokens directamente en los scripts.
library(httr2)
# Store token securely in .Renviron:
# GITHUB_PAT=ghp_your_token_here
# Access at runtime:
token <- Sys.getenv('GITHUB_PAT')
if (nchar(token) == 0) token <- 'demo_token'
# Use in requests:
# resp <- request('https://api.github.com/user') |>
# req_auth_bearer_token(token) |>
# req_headers('Accept' = 'application/vnd.github.v3+json') |>
# req_perform() |>
# resp_check_status()
# result <- resp_body_json(resp)
# result$login # your GitHub username
cat('Token from env:', if(nchar(token)>0) 'found' else 'missing')Construcción de un cliente de API reutilizable
Encapsule la URL base, la autenticación y la gestión de errores en una función constructora. Cada endpoint de la API se convierte en un método que llama a esta función base; este es el patrón estándar para los paquetes de API de R.
library(httr2)
# API client constructor
new_api_client <- function(base_url, token) {
list(
base_req = request(base_url) |>
req_auth_bearer_token(token) |>
req_headers('Accept' = 'application/json') |>
req_retry(max_tries = 3)
)
}
# Method: GET /users
get_users <- function(client, page = 1, size = 20) {
resp <- client$base_req |>
req_url_path_append('users') |>
req_url_query(page = page, size = size) |>
req_perform() |>
resp_check_status()
resp_body_json(resp, simplifyVector = TRUE)
}
# client <- new_api_client('https://api.example.com', token)
# users <- get_users(client, page = 1)
cat('Reusable client pattern: base request + methods')Paginación con resp_link_url()
Muchas API utilizan encabezados Link para la paginación (RFC 5988): la respuesta incluye un encabezado Link: <url>; rel="next". resp_link_url(resp, 'next') extrae automáticamente la URL de la página siguiente.
library(httr2)
# Generic paginator using Link headers
fetch_all_pages <- function(initial_url, token, max_pages = 50) {
all_results <- list()
next_url <- initial_url
page <- 1
while (!is.null(next_url) && page <= max_pages) {
resp <- request(next_url) |>
req_auth_bearer_token(token) |>
req_perform() |>
resp_check_status()
all_results[[page]] <- resp_body_json(resp, simplifyVector = TRUE)
# Follow Link: <url>; rel='next' header
next_url <- tryCatch(
resp_link_url(resp, 'next'),
error = function(e) NULL
)
page <- page + 1
}
do.call(rbind, all_results)
}
cat('resp_link_url() follows RFC 5988 pagination')Paginación basada en cursores
Algunas API, como Twitter y Slack, utilizan cursores en lugar de números de página. La respuesta incluye un campo next_cursor o next_page_token. Pase este valor como parámetro de consulta en la siguiente solicitud.
library(httr2)
# Cursor-based pagination pattern
fetch_cursor_pages <- function(base_url, token, max_pages = 100) {
all_data <- list()
cursor <- NULL
page <- 1
repeat {
req <- request(base_url) |>
req_auth_bearer_token(token)
if (!is.null(cursor))
req <- req |> req_url_query(cursor = cursor)
resp <- req |> req_perform() |> resp_check_status()
body <- resp_body_json(resp)
all_data[[page]] <- body$results
cursor <- body$next_cursor # NULL if last page
if (is.null(cursor) || page >= max_pages) break
page <- page + 1
}
do.call(c, all_data)
}
cat('Cursor pagination: safer for large/changing datasets')Gestión adecuada de errores
Un cliente de API preparado para producción captura por separado los errores HTTP y los fallos de red. Use tryCatch() alrededor de req_perform() e inspeccione la condición de error httr2_http_* para gestionar cada estado de forma específica.
library(httr2)
safe_api_call <- function(req) {
tryCatch(
req |> req_perform() |> resp_check_status(),
httr2_http_401 = function(e) {
stop('Authentication failed. Check your token.')
},
httr2_http_403 = function(e) {
stop('Forbidden. Insufficient permissions.')
},
httr2_http_404 = function(e) {
message('Resource not found, returning NULL')
return(NULL)
},
httr2_http_429 = function(e) {
stop('Rate limit exceeded. Try again later.')
},
error = function(e) {
stop(paste('Request failed:', conditionMessage(e)))
}
)
}
cat('Match on specific httr2_http_NNN conditions')Almacenamiento en caché de respuestas de API
Almacene en caché las respuestas de API para evitar solicitudes innecesarias durante el desarrollo. req_cache() de httr2 almacena las respuestas en el disco y respeta los encabezados Cache-Control. El almacenamiento manual en caché funciona con cualquier API.
library(httr2)
# httr2 built-in disk cache
# resp <- request('https://api.example.com/static-data') |>
# req_cache(tempdir(), max_age = 3600) |> # 1 hour TTL
# req_perform()
# Manual cache pattern
cached_api_call <- function(url, cache_file, max_age = 3600) {
if (file.exists(cache_file)) {
age <- as.numeric(Sys.time() - file.mtime(cache_file))
if (age < max_age) {
cat('Cache hit\n')
return(readRDS(cache_file))
}
}
cat('Cache miss, fetching...\n')
# result <- resp_body_json(request(url) |> req_perform())
# saveRDS(result, cache_file)
# result
}
cached_api_call('https://example.com/api', 'cache.rds')Solicitudes paralelas con req_perform_parallel()
req_perform_parallel() envía varias solicitudes de forma simultánea, lo que reduce considerablemente el tiempo total de las operaciones por lotes. Combínela con req_throttle() para respetar los límites de frecuencia durante la ejecución paralela.
library(httr2)
# Build a list of requests
item_ids <- 1:5
reqs <- lapply(item_ids, function(id) {
request(paste0('https://jsonplaceholder.typicode.com/todos/', id))
})
# Execute all in parallel (requires internet)
# resps <- req_perform_parallel(
# reqs,
# on_error = 'continue', # skip failures
# progress = TRUE
# )
# results <- lapply(resps, resp_body_json)
# titles <- sapply(results, function(r) r$title)
# print(titles)
# on_error options:
# 'stop' -> abort on first failure
# 'continue' -> collect errors, keep going
cat('Parallel: much faster for many independent calls')Trabajo con límites de frecuencia
Las API comunican el estado de los límites de frecuencia mediante encabezados de respuesta: X-RateLimit-Remaining, X-RateLimit-Reset y Retry-After. Léalos para implementar una espera progresiva inteligente.
library(httr2)
respect_rate_limit <- function(resp) {
# Check remaining calls
remaining <- resp_header(resp, 'x-ratelimit-remaining')
if (!is.na(remaining) && as.integer(remaining) < 5) {
reset_at <- as.integer(
resp_header(resp, 'x-ratelimit-reset')
)
wait_secs <- max(0, reset_at - as.integer(Sys.time()))
cat(sprintf('Rate limit nearly exhausted. Waiting %ds\n', wait_secs))
# Sys.sleep(wait_secs)
}
# Handle 429 Retry-After header
if (resp_status(resp) == 429) {
retry_after <- resp_header(resp, 'retry-after')
cat(sprintf('Rate limited. Retry after %s seconds\n', retry_after))
}
resp
}
cat('Always respect X-RateLimit-* headers')Cliente de API completo: ejemplo con GitHub
Un ejemplo que reúne todos los conceptos: un cliente completo de la API de GitHub que se autentica, obtiene listas paginadas de repositorios y gestiona los errores, demostrando todos los patrones aprendidos hasta ahora.
library(httr2)
# GitHub API client
github_repos <- function(username, token = NULL, n_pages = 3) {
base <- 'https://api.github.com'
req_base <- request(base) |>
req_headers(
'Accept' = 'application/vnd.github.v3+json',
'User-Agent' = 'R-API-Client/1.0'
)
if (!is.null(token))
req_base <- req_base |> req_auth_bearer_token(token)
all_repos <- list()
for (page in seq_len(n_pages)) {
# resp <- req_base |>
# req_url_path_append('users', username, 'repos') |>
# req_url_query(page = page, per_page = 30, sort = 'updated') |>
# req_perform() |> resp_check_status()
# repos <- resp_body_json(resp, simplifyVector = TRUE)
# if (length(repos) == 0) break
# all_repos[[page]] <- repos
cat(sprintf('Would fetch page %d for %s\n', page, username))
}
do.call(rbind, all_repos)
}
github_repos('hadley')Credenciales de cliente de OAuth 2.0
Algunas API requieren el flujo de credenciales de cliente de OAuth 2.0: intercambiar client_id + client_secret por un token de acceso. oauth_client() y req_oauth_client_credentials() de httr2 gestionan este proceso automáticamente.
library(httr2)
# OAuth 2.0 Client Credentials flow:
# client <- oauth_client(
# id = Sys.getenv('CLIENT_ID'),
# secret = Sys.getenv('CLIENT_SECRET'),
# token_url = 'https://auth.example.com/oauth/token'
# )
# Automatic token management:
# resp <- request('https://api.example.com/data') |>
# req_oauth_client_credentials(client) |>
# req_perform()
# httr2 automatically:
# 1. Gets access token using client credentials
# 2. Adds 'Authorization: Bearer <token>' header
# 3. Refreshes token when expired
cat('req_oauth_client_credentials() handles token lifecycle')
cat('Token is cached in memory automatically')Comprobación rápida
Compruebe su comprensión de la construcción de clientes de API REST en R con httr2.
Resumen: consumo de API REST
Ideas clave: Construya clientes reutilizables encapsulando la URL base, la autenticación y los reintentos en una función constructora. Use req_auth_bearer_token() para la autenticación y guarde los tokens en variables de entorno. Gestione la paginación mediante encabezados Link con resp_link_url() o mediante patrones basados en cursores. Gestione siempre los errores HTTP con resp_check_status() y tryCatch(). Use req_perform_parallel() para llamadas por lotes. Almacene los resultados en caché durante el desarrollo.
library(httr2)
# REST API client template:
make_api_call <- function(url, token,
method = 'GET',
body = NULL,
query = list()) {
req <- request(url) |>
req_method(method) |>
req_auth_bearer_token(token) |>
req_headers('Accept' = 'application/json') |>
req_retry(max_tries = 3) |>
req_throttle(rate = 10/60)
if (length(query) > 0)
req <- do.call(req_url_query, c(list(req), query))
if (!is.null(body))
req <- req |> req_body_json(body)
req |> req_perform() |> resp_check_status()
}
cat('Template: auth + retry + throttle + error check')Preguntas frecuentes
¿La lección «Consumo de API REST en R» es gratis?
Sí — el texto completo de «Consumo de API REST en R» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de R Academy, actualiza a CoddyKit PRO. El curso de R Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Consumo de API REST en R»?
Autentíquese con claves de API, pagine los resultados y almacene las respuestas de la API. Practicas R Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar R Academy?
No se requiere experiencia previa. R Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Consumo de API REST en R»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de R Academy?
Sí. Cada lección de R Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Análisis de JSON con jsonlite
- Realización de solicitudes HTTP con httr2
- Consumo de API REST en R
- Gestión de estructuras JSON anidadas