The CUSTOS API
(https://apidatalake.tesouro.gov.br/docs/custos/) provides
cost data from the Federal Government Cost Portal (Portal de Custos do
Governo Federal). It breaks down costs into six categories: active
staff, retired staff, pensioners, depreciation, transfers, and other
costs.
All parameters in this API are optional — you can call any function without arguments to retrieve the full dataset.
The CUSTOS API is slow. Its server default is only 250 rows per page; the package raises this to 500 by default (lowered from 1000 in 0.2.1 after the upstream load balancer started cutting broader queries). Even with 500-row pages, unfiltered queries routinely hit HTTP 504 timeouts. Always filter your queries by at least:
yearandmonth— year-only queries are the single most common cause of 504s; always pin a single month for production workorg_level1+org_level2(reduce to a specific organization)legal_nature(reduce to a legal nature category)max_rows(set a hard cap for testing)The package retries automatically on 504s (up to 5 attempts with progressive backoff). When pagination fails after the first page, the rows already fetched are not discarded — you receive a partial tibble with
attr(result, "partial") = TRUEandattr(result, "last_page_error")describing the failure. Always check these attributes when working with broad queries.
| Portuguese | English | Description |
|---|---|---|
get_custos_pessoal_ativo() |
get_costs_active_staff() |
Active staff costs |
get_custos_pessoal_inativo() |
get_costs_retired_staff() |
Retired staff costs |
get_custos_pensionistas() |
get_costs_pensioners() |
Pensioner costs |
get_custos_demais() |
get_costs_other() |
Other costs |
get_custos_depreciacao() |
get_costs_depreciation() |
Depreciation costs |
get_custos_transferencias() |
get_costs_transfers() |
Transfer costs |
All six functions share the same optional filters:
| Portuguese (API) | English | Description |
|---|---|---|
ano |
year |
Year of the record |
mes |
month |
Month (1-12) |
natureza_juridica |
legal_nature |
Legal nature: 1=Public Company, 2=Foundation, 3=Direct Admin, 4=Autarchy, 6=Mixed Economy |
organizacao_n1 |
org_level1 |
Top-level SIORG code (Ministry). See
get_siorg_orgaos(). Auto-padded. |
organizacao_n2 |
org_level2 |
Second-level SIORG code. See
get_siorg_estrutura(). Auto-padded. |
organizacao_n3 |
org_level3 |
Third-level SIORG code. See
get_siorg_estrutura(). Auto-padded. |
SIORG codes are automatically zero-padded: you can pass
244, "244", or "000244" — all
produce the same query.
library(tesouror)
library(dplyr)
# Step 1: Look up SIORG codes for the organization you want
orgaos <- get_siorg_organizations(power_code = 1, sphere_code = 1)
mec <- orgaos |> filter(sigla == "MEC") # code 244
inep <- orgaos |> filter(sigla == "INEP") # code 249
# Step 2: Query CUSTOS with org AND month filters (year-only is unsafe!)
# Active staff costs for INEP, June 2023
ativos_inep <- get_costs_active_staff(
year = 2023, month = 6,
org_level1 = 244, # MEC — auto-padded to "000244"
org_level2 = 249 # INEP — auto-padded to "000249"
)
# Always check whether pagination completed; on 504 mid-stream the
# package returns a partial tibble rather than dropping the data.
if (isTRUE(attr(ativos_inep, "partial"))) {
message("Partial result — last page failed: ",
attr(ativos_inep, "last_page_error"))
}
# Pensioner costs for INEP, June 2023 only
pensionistas_inep <- get_costs_pensioners(
year = 2023, month = 6,
org_level1 = 244,
org_level2 = 249
)
# Quick test: just grab the first 100 rows
sample <- get_costs_active_staff(
year = 2023, month = 6,
legal_nature = 3,
max_rows = 100
)The CUSTOS API returns organization hierarchy down to 6 levels:
| Column | Description |
|---|---|
co_organizacao_n0 /
ds_organizacao_n0 |
Top authority (e.g., Presidência) |
co_organizacao_n1 /
ds_organizacao_n1 |
Ministry level |
co_organizacao_n2 /
ds_organizacao_n2 |
Entity/secretariat |
co_organizacao_n3 /
ds_organizacao_n3 |
Department |
co_organizacao_n4 to n6 |
Deeper sub-units ("-9" = not
applicable) |
an_lanc / me_lanc |
Year and month of the accounting entry |
ds_area_atuacao |
Area: "FINALISTICA" or
"SUPORTE" |
ds_escolaridade |
Education level of the staff member |
ds_faixa_etaria |
Age range |
in_sexo |
Sex: "F" or "M" |
in_forca_trabalho |
Workforce count |
va_custo_de_pessoal |
Cost value (R$) |