misocialr

License R-CMD-check

Tidyverse-friendly R interface to the MI Social API (Matriz de Informação Social) of the Brazilian Ministry of Development and Social Assistance (MDS/SAGI): https://aplicacoes.mds.gov.br/sagi/servicos/misocial.

The package follows the architecture of ibger: a small English public API, long-format tibble output, validation before any request, in-memory per-session cache and offline tests with httptest2 fixtures. The sibling Python package, misocialpy, mirrors the same functions, name by name.

Themes

Theme Function Content
cadunico mds_cadunico() Cadastro Único: registered families and people, by income bracket
bolsa_familia mds_bolsa_familia() Bolsa Família programme: beneficiary families, benefits and transfers
bpc_suas mds_bpc_suas() BPC benefit and the social assistance network (CRAS, CREAS)
suas_rede mds_suas_rede() SUAS network (CadSUAS): CRAS, CREAS, Centro POP, day centres, shelters and staff per unit
suas_financiamento mds_suas_financiamento() FNAS transfers and balances of the municipal funds, and IGD-M
pbf_condicionalidades mds_pbf_condicionalidades() Education and health conditionality monitoring (SICON) and sanctions
seguranca_alimentar mds_seguranca_alimentar() PAA, Fomento Rural and cisterns

The fields of each theme are in mds_fields(). Any other field of the API (mds_api_fields()) can be requested by name in mds_data().

Installation

# install.packages("remotes")
remotes::install_github("StrategicProjects/misocial", subdir = "misocialr")

Requires R >= 4.1, httr2 >= 1.0.4, cli >= 3.6.1, dplyr >= 1.1.1 and purrr >= 1.0.0 (tests: testthat >= 3.2.1).

Usage

library(misocialr)

mds_bolsa_familia(
  periods = c(202508, 202509),
  localities = 2611606,            # Recife (6 or 7 digits)
  fields = c("qtd_familias_beneficiarias_bolsa_familia_i",
             "valor_repassado_bolsa_familia_f")
)
#> # A tibble: 4 × 9  (selected columns)
#>   ibge_code locality_name period field                                      unit        value
#> 1 2611606   RECIFE        202508 qtd_familias_beneficiarias_bolsa_familia_i Famílias   140350
#> 2 2611606   RECIFE        202509 qtd_familias_beneficiarias_bolsa_familia_i Famílias   139452
#> 3 2611606   RECIFE        202508 valor_repassado_bolsa_familia_f            R$       92124240
#> 4 2611606   RECIFE        202509 valor_repassado_bolsa_familia_f            R$       93354456

Accepted formats:

Output columns: locality_id (6 digits, as in the API), ibge_code (7 digits), locality_name, state, period, field, label, unit, value.

Months not yet published

The API answers 0, not “missing”, for months that were not published yet. mds_periods() shows this: n_nonzero counts only the municipalities with a non-zero value.

mds_periods("bpc_ben_i", localities = "PE") |> tail(5)
#>   period n_localities n_nonzero
#> 1 202608          185       185
#> 2 202609          185         0
#> 3 202610          185         0
#> 4 202611          185         0
#> 5 202612          185         0

mds_drop_unpublished() removes those zeros explicitly: future months and months after the last month with a non-zero value. A zero in the middle of the series, followed by a month with a value, is kept. The outputs above come from queries made on 2026-10-19.

The “last month with a value” can come from two places:

Validation and errors

The query is checked before any data request, and the cases below are errors with a message, instead of an empty or silently different result:

Every response is checked before it is used or cached: a failure of the source does not become “no data” for the rest of the session.

Errors are classed, for programmatic handling: misocialr_error_validation (input), misocialr_error_response (incomplete response), misocialr_error_conflict (the source contradicts itself) and misocialr_error_http (network, with status and the original error in parent); all inherit from misocialr_error. A requested municipality with no document raises the warning misocialr_warning_missing.

Unpublished months: remove or flag

mds_drop_unpublished() never deletes a non-zero value. With reference = "brazil", if the national reference says that a month with a value was not published, it is queried again; if the contradiction remains, the month is kept with a warning. To inspect before removing:

mds_drop_unpublished(x, action = "flag")
# adds publication_status ("published", "future", "unpublished",
# "missing"), publication_reason and publication_reference

This is an inference from the published values, not an official publication date.

Options

Summing safely

mds_fields() tells the nature of each field (nature) and where that classification comes from (nature_basis):

nature Sum across municipalities Sum across months
estoque (count in the month) yes no
fluxo (value of the month) yes yes
fluxo anual (one value per year, in December) yes one value per year
acumulado (running total) yes no
taxa, média, índice no no

nature_basis = "medido" means the monthly series was inspected (a running total only grows; a monthly value oscillates and restarts); the others are inferences from the group or from the label and unit.

Known limits

Notes on the fields

Development

Rscript -e 'testthat::test_local(".")'   # tests, offline
Rscript data-raw/record_fixtures.R        # re-records fixtures (network)
Rscript data-raw/check_dictionary.R       # checks the dictionary against the API (network)