Bureau of Economic Analysis’ API

Data - BEA

Info

source dataset .html .RData

bea

api

2024-06-17 NA

List of APIs

source dataset .html .RData

bdf

api

2024-06-19 NA

bea

api

2024-06-17 NA

bis

api

2024-04-19 NA

bls

api

2024-06-17 NA

ecb

api

2024-06-19 NA

eurostat

api

2024-06-08 NA

imf

api

2024-06-18 NA

insee

api

2024-06-18 NA

oecd

api

2024-05-07 2024-04-16

rdb

api

NA NA

wdi

api

2024-04-14 NA

LAST_COMPILE

LAST_COMPILE
2024-06-19

API Key

The BEA API key should be obtained from https://apps.bea.gov/API/signup/index.cfm. This data API key will be of the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, which you’ll declare as a string variable into bea_key.

NIPA

  • NIPA Website. html
  • NIPA Handbook. html
  • NIPA Glossary. pdf
  • Fundamental Concepts. pdf

List of Main Tables

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetParameterValues&",
       "datasetname=NIPA&",
       "ParameterName=TableName&") %>%
  fromJSON(.) %>%
  pluck("BEAAPI", "Results", "ParamValue") %>%
  select(TableName, Description) %>%
  mutate(N = 1:n()) %>%
  filter(TableName %in% (list.files(pattern = "\\.qmd$") %>% gsub(".qmd$", "", .))) %>%
  mutate(html = paste0('<a  target=_blank href=', TableName, '.html > html </a>')) %>%
  mutate(bea = paste0('<a  target=_blank href=https://apps.bea.gov/iTable/iTable.cfm?reqid=19&step=3&isuri=1&nipa_table_list=', N, '&categories=survey > bea </a>')) %>%
  mutate(Last_compile = as.Date(file.info(paste0("~/Library/Mobile\ Documents/com~apple~CloudDocs/website/data/bea/", TableName, ".html"))$mtime)) %>%
  select(-N) %>%
  {if (is_html_output()) datatable(., filter = 'top', rownames = F, escape = F) else .}

List of Other Tables

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetParameterValues&",
       "datasetname=NIPA&",
       "ParameterName=TableName&") %>%
  fromJSON(.) %>%
  pluck("BEAAPI", "Results", "ParamValue") %>%
  select(TableName, Description) %>%
  mutate(N = 1:n()) %>%
  filter(!(TableName %in% (list.files(pattern = "\\.qmd$") %>% gsub(".qmd$", "", .)))) %>%
  mutate(bea = paste0('<a  target=_blank href=https://apps.bea.gov/iTable/iTable.cfm?reqid=19&step=3&isuri=1&nipa_table_list=', N, '&categories=survey > bea </a>')) %>%
  select(-N) %>%
  {if (is_html_output()) datatable(., filter = 'top', rownames = F, escape = F) else .}

List of Parameters

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetParameterList&",
       "DataSetName=NIPA&") %>%
  fromJSON(.) %>%
  pluck("BEAAPI", "Results", "Parameter") %>% 
  select(ParameterName, ParameterDataType, ParameterDescription) %>%
  {if (is_html_output()) print_table(.) else .}
ParameterName ParameterDataType ParameterDescription
Frequency string A - Annual, Q-Quarterly, M-Monthly
ShowMillions string A flag indicating that million-dollar data should be returned.
TableID integer The standard NIPA table identifier
TableName string The new NIPA table identifier
Year integer List of year(s) of data to retrieve (X for All)

Ex 1: gdp_adjustment

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetData&",
       "DataSetName=NIPA&",
       "TableName=T10105&",
       "Frequency=A&",
       "Year=ALL&",
       "ResultFormat=JSON") %>%
  fromJSON(.) %>% 
  pluck("BEAAPI", "Results", "Data") %>% 
  select(TableName, LineDescription, TimePeriod, SeriesCode, DataValue, LineNumber) %>%
  mutate_at(vars(DataValue, LineNumber), funs(gsub(",", "", .) %>% as.numeric)) %>%
  mutate(date = TimePeriod %>% paste0("-01-01") %>% as.Date) %>%
  select(LineNumber, LineDescription, SeriesCode, date, DataValue) %>%
  arrange(date, LineNumber) %>%
  filter(date == as.Date("2019-01-01")) %>%
  {if (is_html_output()) datatable(., filter = 'top', rownames = F) else .}

Standard NI underlying detail tables

Ex 1

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetData&",
       "DataSetName=NIUnderlyingDetail&",
       "TableName=U20405&",
       "Frequency=A&",
       "Year=ALL&",
       "ResultFormat=JSON") %>%
  fromJSON(.) %>% 
  pluck("BEAAPI", "Results", "Data") %>% 
  select(TableName, LineDescription, TimePeriod, SeriesCode, DataValue, LineNumber) %>%
  mutate_at(vars(DataValue, LineNumber), funs(gsub(",", "", .) %>% as.numeric)) %>%
  mutate(date = TimePeriod %>% paste0("-01-01") %>% as.Date) %>%
  select(LineNumber, LineDescription, SeriesCode, date, DataValue) %>%
  arrange(date, LineNumber) %>%
  filter(date == as.Date("2018-01-01")) %>%
  select(-date) %>%
  mutate(`Share (%)` = (100*DataValue / DataValue[1]) %>% round(., digits = 2)) %>%
  {if (is_html_output()) datatable(., filter = 'top', rownames = F) else .}

Ex 2

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetData&",
       "DataSetName=NIUnderlyingDetail&",
       "TableName=U20405&",
       "Frequency=Q&",
       "Year=ALL&",
       "ResultFormat=JSON") %>%
  fromJSON(.) %>% 
  pluck("BEAAPI", "Results", "Data") %>% 
  mutate(DataValue = DataValue %>% gsub(",", "", .) %>% as.numeric) %>%
  mutate(year = substr(TimePeriod, 1, 4),
         qtr = substr(TimePeriod, 6, 6) %>% as.numeric,
         month = ((qtr-1)*3+1) %>% str_pad(., 2, pad = "0"),
         date = paste0(year, "-", month, "-01") %>% as.Date) %>%
  filter(LineNumber == 1,
         date >= as.Date("2006-01-01"), 
         date <= as.Date("2010-01-01")) %>%
  mutate(DataValue = DataValue/1000) %>%
  ggplot(.) + geom_line(aes(x = date, y = DataValue)) + theme_minimal() +
  scale_x_date(breaks = seq(1870, 2020, 1) %>% paste0("-01-01") %>% as.Date,
               labels = date_format("%Y")) +
  scale_y_continuous(breaks = function(x) seq(1000*floor(min(x)/1000), max(x), 100),
                     labels = dollar_format(suffix = "Bn", prefix = "$")) + 
  xlab("") + ylab("Total Consumption") + 
  geom_vline(xintercept = as.Date("2008-09-15"), linetype = "dashed", color = viridis(3)[2])

Fixed Asset Tables

List of Main Tables

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetParameterValues&",
       "datasetname=FixedAssets&",
       "ParameterName=TableName&") %>%
  fromJSON(.) %>%
  pluck("BEAAPI", "Results", "ParamValue") %>%
  select(TableName, Description) %>%
  mutate(N = 1:n()) %>%
  filter(TableName %in% (list.files(pattern = "\\.qmd$") %>% gsub(".qmd$", "", .))) %>%
  mutate(html = paste0('<a  target=_blank href=', TableName, '.html > html </a>')) %>%
  mutate(bea = paste0('<a  target=_blank href=https://apps.bea.gov/iTable/iTable.cfm?reqid=10&step=3&isuri=1&table_list=', N, '&categories=survey > bea </a>')) %>%
  select(-N) %>%
  {if (is_html_output()) datatable(., filter = 'top', rownames = F, escape = F) else .}

List of Other Tables

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetParameterValues&",
       "datasetname=FixedAssets&",
       "ParameterName=TableName&") %>%
  fromJSON(.) %>%
  pluck("BEAAPI", "Results", "ParamValue") %>%
  select(TableName, Description) %>%
  mutate(N = 1:n()) %>%
  filter(!(TableName %in% (list.files(pattern = "\\.qmd$") %>% gsub(".qmd$", "", .)))) %>%
  mutate(bea = paste0('<a  target=_blank href=https://apps.bea.gov/iTable/iTable.cfm?reqid=10&step=3&isuri=1&table_list=', N, '&categories=survey > bea </a>')) %>%
  select(-N) %>%
  {if (is_html_output()) datatable(., filter = 'top', rownames = F, escape = F) else .}

List of Parameters

What is the list of parameters in the Fixed Asset Tables? The answer is found by typing:

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetParameterList&",
       "DataSetName=FixedAssets&") %>%
  fromJSON(.) %>%
  pluck("BEAAPI", "Results", "Parameter") %>% 
  select(ParameterName, ParameterDataType, ParameterDescription) %>%
  {if (is_html_output()) print_table(.) else .}
ParameterName ParameterDataType ParameterDescription
TableName string The new Fixed Assets identifier
Year integer List of year(s) of data to retrieve (X for All)

Ex 1

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetData&",
       "DataSetName=FixedAssets&",
       "TableName=FAAt101&",
       "Frequency=A&",
       "Year=ALL&",
       "ResultFormat=JSON") %>%
  fromJSON(.) %>% 
  pluck("BEAAPI", "Results", "Data") %>% 
  select(TableName, LineDescription, TimePeriod, SeriesCode, DataValue, LineNumber) %>%
  mutate_at(vars(DataValue, LineNumber), funs(gsub(",", "", .) %>% as.numeric)) %>%
  mutate(date = TimePeriod %>% paste0("-01-01") %>% as.Date) %>%
  select(LineNumber, LineDescription, SeriesCode, date, DataValue) %>%
  arrange(date, LineNumber) %>%
  filter(date == as.Date("2018-01-01")) %>%
  {if (is_html_output()) datatable(., filter = 'top', rownames = F) else .}

Ex 2A

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetData&",
       "DataSetName=FixedAssets&",
       "TableName=FAAt101&",
       "Frequency=A&",
       "Year=ALL&",
       "ResultFormat=JSON") %>%
  fromJSON(.) %>% 
  pluck("BEAAPI", "Results", "Data") %>% 
  select(TableName, LineDescription, TimePeriod, SeriesCode, DataValue, LineNumber) %>%
  mutate_at(vars(DataValue, LineNumber), funs(gsub(",", "", .) %>% as.numeric)) %>%
  mutate(date = TimePeriod %>% paste0("-01-01") %>% as.Date) %>%
  arrange(date, LineNumber) %>%
  left_join(gdp_adjustment, by = "date") %>%
  mutate(value = 1000 * `Real GDP / Real GDP Trend (Log Linear)` * DataValue / GDP) %>%
  filter(!is.na(value)) %>%
  filter(date == as.Date("2018-01-01")) %>%
  mutate(value = (100*value) %>% round(., 1),
         year = date %>% year) %>%
  select(LineNumber, LineDescription, year, value) %>%
  spread(year, value) %>%
  mutate_at(vars(-LineDescription, -LineNumber), funs(paste0(., "%"))) %>%
  as.data.frame %>%
  arrange(LineNumber) %>%
  filter(LineNumber <= 15) %>%
  select(-LineNumber) %>%
  knitr::kable(booktabs = T, linesep = "") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                latex_options = c("striped", "hold_position", "repeat_header")) %>%
  add_indent(c(3:14)) %>%
  add_indent(c(4:8, 10:14)) %>%
  add_indent(c(5:7, 11:13))
LineDescription 2018
Fixed assets and consumer durable goods 265332.3%
Fixed assets 244061.2%
Private 185131.7%
Nonresidential 98072.5%
Equipment 27549.1%
Structures 57434.5%
Intellectual property products 13088.9%
Residential 87059.1%
Government 58929.5%
Nonresidential 57184.3%
Equipment 4063.7%
Structures 48280.8%
Intellectual property products 4839.7%
Residential 1745.3%
Consumer durable goods 21271.2%

Ex 2B

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetData&",
       "DataSetName=FixedAssets&",
       "TableName=FAAt101&",
       "Frequency=A&",
       "Year=ALL&",
       "ResultFormat=JSON") %>%
  fromJSON(.) %>% 
  pluck("BEAAPI", "Results", "Data") %>% 
  select(TableName, LineDescription, TimePeriod, SeriesCode, DataValue, LineNumber) %>%
  mutate_at(vars(DataValue, LineNumber), funs(gsub(",", "", .) %>% as.numeric)) %>%
  mutate(date = TimePeriod %>% paste0("-01-01") %>% as.Date) %>%
  arrange(date, LineNumber) %>%
  left_join(gdp_adjustment, by = "date") %>%
  mutate(value = 1000 * `Real GDP / Real GDP Trend (Log Linear)` * DataValue / GDP) %>%
  filter(!is.na(value)) %>%
  filter(date == as.Date("2018-01-01")) %>%
  mutate(value = (100*value) %>% round(., 1),
         year = date %>% year) %>%
  select(LineNumber, LineDescription, year, value) %>%
  spread(year, value) %>%
  mutate_at(vars(-LineDescription, -LineNumber), funs(paste0(., "%"))) %>%
  as.data.frame %>%
  arrange(LineNumber) %>%
  filter(LineNumber <= 15) %>%
  select(-LineNumber) %>%
  knitr::kable(booktabs = T, linesep = "") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                latex_options = c("striped", "hold_position", "repeat_header")) %>%
  add_indent(c(3:14)) %>%
  add_indent(c(4:8, 10:14)) %>%
  add_indent(c(5:7, 11:13)) %>%
  row_spec(1, bold = T, color = "#000000BB", background = "#44015422") %>%
  row_spec(c(2, 15), bold = T, color = "#000000BB", background = "#21908C22") %>%
  row_spec(c(3, 9), bold = T, color = "#000000BB", background = "#35B77922") %>%
  row_spec(c(4, 8, 10, 14), bold = T, color = "#000000BB", background = "#FDE72522")
LineDescription 2018
Fixed assets and consumer durable goods 265332.3%
Fixed assets 244061.2%
Private 185131.7%
Nonresidential 98072.5%
Equipment 27549.1%
Structures 57434.5%
Intellectual property products 13088.9%
Residential 87059.1%
Government 58929.5%
Nonresidential 57184.3%
Equipment 4063.7%
Structures 48280.8%
Intellectual property products 4839.7%
Residential 1745.3%
Consumer durable goods 21271.2%

Ex 3

Code
paste0("https://apps.bea.gov/api/data/?&",
       "UserID=", bea_key, "&",
       "method=GetData&",
       "DataSetName=FixedAssets&",
       "TableName=FAAt101&",
       "Frequency=A&",
       "Year=ALL&",
       "ResultFormat=JSON") %>%
  fromJSON(.) %>% 
  pluck("BEAAPI", "Results", "Data") %>% 
  select(TableName, LineDescription, TimePeriod, SeriesCode, DataValue, LineNumber) %>%
  mutate_at(vars(DataValue, LineNumber), funs(gsub(",", "", .) %>% as.numeric)) %>%
  mutate(date = TimePeriod %>% paste0("-01-01") %>% as.Date) %>%
  arrange(date, LineNumber) %>%
  filter(LineNumber %in% c(5, 6, 8, 15)) %>%
  left_join(gdp_adjustment, by = "date") %>%
  mutate(value = 1000 * `Real GDP / Real GDP Trend (Log Linear)` * DataValue / GDP) %>%
  ggplot + geom_line(aes(x = date, y = value, color = LineDescription)) + 
  ylab("% of GDP") + xlab("") + 
  theme_minimal()+
  geom_rect(data = nber_recessions %>%
              filter(Peak > as.Date("1927-01-01")),
            aes(xmin = Peak, xmax = Trough, ymin = -Inf, ymax = +Inf), 
            fill = 'grey', alpha = 0.5) +
  scale_x_date(breaks = nber_recessions$Peak,
               minor_breaks = "5 years",
               labels = date_format("%y"),
               limits = c(1928, 2019) %>% paste0("-01-01") %>% as.Date) + 
  scale_y_continuous(breaks = 0.01*seq(0, 160, 10),
                     labels = scales::percent_format(accuracy = 1)) +
  scale_color_manual(values = viridis(5)[1:4]) +
  theme(legend.position = c(0.2, 0.3),
        legend.title = element_blank(),
        legend.text = element_text(size = 8),
        legend.key.size = unit(0.9, 'lines'))