Una API (Application Programming Interface, interfaz de programación de aplicaciones) es un conjunto de reglas y puntos de acceso que permite que dos programas se comuniquen entre sí sin intervención humana. En lugar de descargar manualmente hojas de cálculo desde un portal web, un cliente (por ejemplo, R) envía una solicitud a un servidor y recibe una respuesta estructurada, normalmente en formato JSON o XML, que puede procesarse de inmediato.
La analogía útil es la de un mesero en un restaurante: el comensal (nuestro programa) no entra a la cocina (la base de datos del Banco Mundial); le hace un pedido al mesero (la API) siguiendo un menú (la documentación), y este devuelve exactamente lo solicitado. El comensal no necesita saber cómo está organizada la cocina, solo cómo pedir.
Las APIs pueden clasificarse según distintos criterios. Para efectos prácticos, conviene distinguir:
La API del Banco Mundial es una API REST pública de datos: se consulta mediante URLs, no requiere clave de autenticación para la mayoría de sus series y devuelve resultados en JSON o XML.
Para la investigación económica aplicada, el acceso vía API aporta ventajas que la descarga manual no ofrece:
La API principal del Banco Mundial es la API de Indicadores (Indicators API, versión 2), cuya URL base es:
https://api.worldbank.org/v2/
Su gran valor está en la desagregación: cada observación se identifica por varias dimensiones combinables. Las principales son:
| Dimensión | Descripción | Ejemplo |
|---|---|---|
| País / economía | ~217 economías, más agregados regionales y por ingreso | SV (El Salvador), GT (Guatemala) |
| Indicador | Código único de cada serie estadística | NY.GDP.MKTP.CD (PIB, US$ corrientes) |
| Tiempo | Año (algunas series: trimestre o mes) | 2000:2024 |
| Tema | 20 temas: economía, salud, educación, pobreza… | Economy & Growth |
| Fuente / base | Más de 40 bases (WDI, deuda externa, etc.) | World Development Indicators |
| Región / ingreso | Agrupaciones geográficas y por nivel de ingreso | Latin America & Caribbean, Upper middle income |
El paquete wbstats incluye un catálogo precargado
(wb_cachelist) que permite inspeccionar sin
conexión toda esta estructura. Los siguientes bloques muestran
la información disponible desagregada por cada dimensión.
library(wbstats)
library(dplyr)
catalogo <- wb_cachelist
# ¿Cuántos elementos hay en cada dimensión del catálogo?
sapply(catalogo, NROW)#> countries indicators sources topics regions
#> 295 29533 71 21 43
#> income_levels lending_types languages
#> 7 4 23
# Países y economías de Centroamérica disponibles
catalogo$countries %>%
filter(region == "Latin America & Caribbean ") %>%
select(iso3c, iso2c, country, income_level, region) %>%
filter(iso3c %in% c("SLV", "GTM", "HND", "NIC", "CRI", "PAN", "BLZ")) # Los temas (topics) bajo los que se organizan los indicadores
catalogo$topics %>% select(topic_id, topic)# Algunas de las bases de datos (sources) accesibles por la misma API
catalogo$sources %>% select(source_id, source) %>% head(10)Con esto queda claro que la API no expone “una tabla”, sino un cubo de datos consultable por país, indicador, tiempo, tema y fuente de forma combinada.
Existen tres caminos, de mayor a menor nivel de abstracción:
WDI — el envoltorio (wrapper)
más popular, ideal para empezar.wbstats — más flexible (búsqueda
avanzada, valores más recientes, cache).httr +
jsonlite — control total de la petición HTTP.WDIPrimero se busca el código del indicador y luego se
descarga para los países y años deseados. La función
devuelve un data.frame en formato largo (país–año).
library(WDI)
# Buscar indicadores de PIB per cápita en dólares constantes
WDIsearch("gdp.*capita.*constant")[1:5, ]# PIB per cápita (US$ constantes) para el Triángulo Norte, 2010-2023
ca <- WDI(
country = c("SV", "GT", "HN"),
indicator = "NY.GDP.PCAP.KD",
start = 2010,
end = 2023
)
head(ca)wbstatsOfrece búsqueda tipo grep, salida en tibble
y utilidades como mrnev (traer los n valores más
recientes no vacíos). Es útil cuando se trabaja con paneles amplios.
library(wbstats)
# Crecimiento del PIB (% anual) para toda Centroamérica, 2015-2024
pib_ca <- wb_data(
indicator = "NY.GDP.MKTP.KD.ZG",
country = c("SV", "GT", "HN", "NI", "CR", "PA", "BZ"),
start_date = 2015,
end_date = 2024
)
head(pib_ca)library(ggplot2)
ggplot(pib_ca, aes(x = date, y = NY.GDP.MKTP.KD.ZG, color = country)) +
geom_line(linewidth = 0.8) +
geom_hline(yintercept = 0, linetype = "dashed", color = "grey50") +
labs(
title = "Crecimiento del PIB en Centroamérica",
subtitle = "Variación anual del PIB real (%), 2015-2024",
x = NULL, y = "% anual", color = "País",
caption = "Fuente: Banco Mundial (API de Indicadores) vía wbstats"
) +
theme_minimal()httr + jsonliteCuando se necesita entender qué ocurre “por debajo”, se puede llamar
a la API directamente. La respuesta JSON de la API de Indicadores tiene
dos partes: el elemento [[1]] contiene la
metadata de paginación (páginas, total de registros, última
actualización) y el [[2]] contiene los datos.
library(httr)
library(jsonlite)
# Construcción de la URL: PIB (US$ corrientes) de El Salvador, 2010-2023
url <- paste0(
"https://api.worldbank.org/v2/country/SV/indicator/NY.GDP.MKTP.CD",
"?format=json&date=2010:2023&per_page=100"
)
resp <- GET(url)
contenido <- fromJSON(content(resp, as = "text", encoding = "UTF-8"))
# Parte 1: metadata de paginación
str(contenido[[1]])#> List of 6
#> $ page : int 1
#> $ pages : int 1
#> $ per_page : int 100
#> $ total : int 14
#> $ sourceid : chr "2"
#> $ lastupdated: chr "2026-07-13"
# Parte 2: los datos (se aplanan las columnas anidadas indicator/country)
datos <- contenido[[2]]
datos[, c("countryiso3code", "date", "value")] |> head()Nota sobre paginación. La API devuelve por defecto 50 registros por página. Para descargas grandes conviene fijar
per_page(hasta 32 500) o recorrer las páginas con el parámetropage, usando el campopagesde la metadata para saber cuántas iteraciones hacen falta.
El ejemplo anterior descarga un indicador para
un país. Pero la pobreza
multidimensional es, por definición, un fenómeno de varias
dimensiones: privaciones monetarias, educativas y de acceso a servicios
básicos. Como la API sirve un indicador por llamada, construir un
dataset multivariable exige descargar cada serie por separado y
unirlas (join) por país y año. Y para acotar el
resultado a “toda Latinoamérica” se necesita un segundo tipo de
join contra el catálogo de países, que actúa como filtro
regional.
Combinamos el conjunto de indicadores del Multidimensional Poverty Measure (MPM) del Banco Mundial:
| Código | Variable | Papel en el análisis |
|---|---|---|
SI.POV.MDIM |
Tasa de pobreza multidimensional (% de población) | Indicador agregado (MPM) |
SI.POV.MDIM.IT |
Intensidad de la privación (% promedio entre los pobres) | Profundidad de la pobreza |
SI.POV.DDAY |
Pobreza monetaria (línea internacional; hoy US$ 3.00/día, PPA 2021) | Dimensión monetaria |
SI.POV.GINI |
Índice de Gini | Desigualdad (contexto) |
Paso 1 — Función reutilizable. Encapsulamos la
petición HTTP en una función que descarga un indicador para
todas las economías y devuelve un tibble ordenado.
La columna de valores toma el nombre del propio código, lo que luego
facilita el join.
library(httr)
library(jsonlite)
library(dplyr)
library(purrr)
library(stringr)
wb_indicador <- function(codigo, inicio = 2000, fin = 2024) {
url <- paste0(
"https://api.worldbank.org/v2/country/all/indicator/", codigo,
"?format=json&date=", inicio, ":", fin, "&per_page=20000"
)
resp <- GET(url)
stop_for_status(resp)
crudo <- fromJSON(content(resp, as = "text", encoding = "UTF-8"),
flatten = TRUE)
crudo[[2]] |>
as_tibble() |>
transmute(
# La API es inconsistente entre bases: unas dejan vacío countryiso3code y
# ponen el ISO-3 en country.id (caso de las series de pobreza), otras al
# revés. coalesce() toma el primero no vacío -> siempre queda el ISO-3.
iso3c = coalesce(na_if(countryiso3code, ""), country.id),
anio = as.integer(date),
!!codigo := value # la columna se nombra con el código
)
}Detalle clave para los
join. No todas las bases de la API rellenan los mismos campos: las series de pobreza dejan vacíocountryiso3codey colocan el código ISO-3 encountry.id, mientras que otras (como el PIB) hacen lo contrario. Por eso la llave se construye concoalesce(): si se usara solocountryiso3code, eljoinno encontraría coincidencias y el dataset final quedaría vacío. Conviene siempre inspeccionar las llaves antes de unir.
Paso 2 — El pipe con múltiples variables y
full_join. Recorremos los códigos con
map(), obtenemos una lista de tibbles (uno por
indicador) y los fusionamos con reduce(full_join, ...). El
full_join conserva toda combinación país–año presente en
cualquiera de las series, de modo que ningún dato se pierde en
la unión.
codigos <- c("SI.POV.MDIM", "SI.POV.MDIM.IT", "SI.POV.DDAY", "SI.POV.GINI")
panel <- codigos |>
map(wb_indicador) |> # lista: un tibble por serie
reduce(full_join, by = c("iso3c", "anio")) |> # une las 4 variables
rename( # nombres legibles
pobreza_multidim = "SI.POV.MDIM",
intensidad = "SI.POV.MDIM.IT",
pobreza_monetaria = "SI.POV.DDAY",
gini = "SI.POV.GINI"
)
glimpse(panel)#> Rows: 6,709
#> Columns: 6
#> $ iso3c <chr> "ARB", "ARB", "ARB", "ARB", "ARB", "ARB", "ARB", "AR…
#> $ anio <int> 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012…
#> $ pobreza_multidim <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
#> $ intensidad <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
#> $ pobreza_monetaria <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
#> $ gini <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
Paso 3 — Catálogo de países como tabla de filtro.
Descargamos los metadatos de países y nos quedamos solo con la región
Latin America & Caribbean. Este tibble aporta
el nombre, la región y el nivel de ingreso, y servirá para recortar el
panel mediante un inner_join.
meta <- fromJSON(
content(GET("https://api.worldbank.org/v2/country?format=json&per_page=400"),
as = "text", encoding = "UTF-8"),
flatten = TRUE
)
paises_lac <- meta[[2]] |>
as_tibble() |>
transmute(
iso3c = id,
pais = name,
region = region.value,
ingreso = incomeLevel.value
) |>
filter(str_detect(region, "Latin America")) # descarta agregados y otras regionesPaso 4 — Join final que filtra a Latinoamérica. Aquí
el inner_join cumple doble función: agrega los atributos de
cada país y, al conservar solo las filas con coincidencia en
paises_lac, filtra el panel mundial a la
región de interés (los agregados y las economías de otras regiones
quedan fuera).
pobreza_latam <- panel |>
inner_join(paises_lac, by = "iso3c") |> # une + filtra a la región
relocate(pais, region, ingreso, .after = iso3c) |>
arrange(pais, anio)
head(pobreza_latam)Paso 5 — Foto más reciente por país. Los datos del MPM provienen de encuestas de hogares y son escasos (un país no tiene un valor por año, sino uno cada varios años). Por eso construimos una “foto” con el último año disponible de pobreza multidimensional en cada país.
snapshot_latam <- pobreza_latam |>
filter(!is.na(pobreza_multidim)) |>
group_by(iso3c) |>
slice_max(anio, n = 1, with_ties = FALSE) |> # último año con dato por país
ungroup() |>
select(pais, anio, pobreza_multidim, intensidad, pobreza_monetaria, gini) |>
arrange(desc(pobreza_multidim))
snapshot_latamlibrary(ggplot2)
ggplot(snapshot_latam,
aes(x = reorder(pais, pobreza_multidim), y = pobreza_multidim)) +
geom_col(fill = "#2c7fb8") +
coord_flip() +
labs(
title = "Pobreza multidimensional en América Latina y el Caribe",
subtitle = "Incidencia (% de población), último año disponible por país",
x = NULL, y = "% de la población",
caption = "Fuente: Banco Mundial — Multidimensional Poverty Measure (API v2)"
) +
theme_minimal()En síntesis, el pipe articula dos lógicas de
join: full_join para ensamblar las
variables (nada se descarta) e inner_join para
acotar el universo a Latinoamérica. Ese mismo patrón —una
función de descarga, un reduce(full_join) sobre varios
indicadores y un inner_join con una tabla de referencia—
escala a cualquier conjunto de series y a cualquier recorte
geográfico.
cache=TRUE en los chunks o guardando
un .rds) para no golpear el servidor en cada compilación y
trabajar sin conexión.NY.GDP.MKTP.CD es más reproducible que “PIB
corriente”.NA.Los tres caminos consultan la misma API; la elección depende del
control que se necesite. Para la mayoría del trabajo aplicado,
WDI o wbstats bastan; el acceso directo con
httr queda como recurso cuando se requiere ajustar la
petición al detalle.
WDI (CRAN): https://cran.r-project.org/package=WDIwbstats (CRAN): https://cran.r-project.org/package=wbstats