curl --request POST \
--url https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees \
--header 'Content-Type: application/json' \
--header 'apikey: <api-key>' \
--data '
{
"p_cnpjs": [
"<string>"
],
"p_month": null
}
'import requests
url = "https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees"
payload = {
"p_cnpjs": ["<string>"],
"p_month": None
}
headers = {
"apikey": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {apikey: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({p_cnpjs: ['<string>'], p_month: null})
};
fetch('https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'p_cnpjs' => [
'<string>'
],
'p_month' => null
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"apikey: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees"
payload := strings.NewReader("{\n \"p_cnpjs\": [\n \"<string>\"\n ],\n \"p_month\": null\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("apikey", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees")
.header("apikey", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"p_cnpjs\": [\n \"<string>\"\n ],\n \"p_month\": null\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["apikey"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"p_cnpjs\": [\n \"<string>\"\n ],\n \"p_month\": null\n}"
response = http.request(request)
puts response.read_body[
{
"cnpj": "<string>",
"fund_name": "<string>",
"month": "2023-12-25",
"nav": 123,
"adm_fee_flow": 123,
"adm_fee_pct_annual_est": 123,
"perf_fee_flow": 123,
"perf_fee_pct_annual_est": 123,
"fiscal_reset_suspect": true,
"disclosed_taxa_adm": 123,
"disclosed_taxa_adm_min": 123,
"disclosed_taxa_adm_max": 123,
"disclosed_taxa_perfm": "<string>",
"disclosed_taxa_adm_info": "<string>",
"disclosed_taxa_perfm_info": "<string>",
"disclosed_source": "<string>",
"disclosed_as_of": "2023-12-25",
"disclosed_age_months": 123,
"disclosed_n_classes": 123,
"disclosed_note": "<string>",
"estimate_label": "<string>",
"disclosed_origin": "<string>",
"disclosed_age_days": 123,
"filed_zero": true,
"implausible_filed": true,
"taxa_adm_filed_raw": 123,
"extrato_tp_fundo_classe": "<string>",
"extrato_classe_anbima": "<string>",
"extrato_class_note": "<string>",
"extrato_existe_taxa_perfm": "<string>",
"extrato_taxa_perfm": 123,
"extrato_param_taxa_perfm": "<string>",
"extrato_calc_taxa_perfm": "<string>",
"extrato_inf_taxa_perfm": "<string>",
"extrato_existe_taxa_ingresso": "<string>",
"extrato_taxa_ingresso_pr": 123,
"extrato_taxa_ingresso_real": 123,
"extrato_existe_taxa_saida": "<string>",
"extrato_taxa_saida_pr": 123,
"extrato_taxa_saida_real": 123,
"extrato_taxa_custodia_max": 123,
"lamina_pr_pl_despesa": 123,
"lamina_dt_ini_despesa": "2023-12-25",
"lamina_dt_fim_despesa": "2023-12-25",
"lamina_as_of": "2023-12-25",
"lamina_expense_note": "<string>",
"fee_resolution": "<string>",
"lamina_taxa_adm": 123,
"lamina_taxa_adm_min": 123,
"lamina_taxa_adm_max": 123,
"lamina_n_classes": 123,
"lamina_age_months": 123,
"extrato_taxa_adm_filed": 123,
"extrato_as_of": "2023-12-25",
"extrato_lamina_ratio": 123,
"extrato_scale_factor": 123,
"etf_ticker": "<string>",
"etf_site_taxa_adm": 123,
"etf_site_as_of": "2023-12-25",
"etf_site_source": "<string>",
"etf_site_note": "<string>",
"etf_site_nr_cotistas": 123,
"etf_site_pl": 123,
"benchmark_extrato": "<string>",
"benchmark_lamina": "<string>",
"benchmark_lamina_n": 123
}
]{
"code": "22023",
"message": "<string>",
"details": "<string>",
"hint": "<string>"
}{
"code": "22023",
"message": "<string>",
"details": "<string>",
"hint": "<string>"
}{
"code": "22023",
"message": "<string>",
"details": "<string>",
"hint": "<string>"
}portfolio_fees
Fees per fund, two kinds of number that are never mixed. DISCLOSED (disclosed_): the fee the fund published, ONE source per fund in this order: the CVM Extrato das Informacoes (cvm_fi_extrato, newest version, one row per fund or class), else the lâmina (cvm_fi_lamina, newest reference month), else cad_fi (cvm_fund_registry taxa_adm / taxa_perfm / inf_taxa_); disclosed_origin (extrato | lamina | cad_fi), disclosed_source, disclosed_as_of (the filing date), disclosed_age_months and disclosed_age_days say which and how old. Two reading rules on the single administration fee, % a year as filed: a filed 0 is returned as 0 with filed_zero TRUE (read it as not informed, never as a zero cost); a filed value above 5 (or below 0) is NOT returned as the fee: disclosed_taxa_adm is NULL, implausible_filed is TRUE and the value as filed is in taxa_adm_filed_raw. The stored value is never rewritten. A NULL disclosed part is not a zero fee; when the lâmina’s classes disclose different fees the single value is NULL and the min / max and disclosed_note say so. An Extrato row that exists is the source, even when its fee is 0 or above 5: it does not fall through to an OLDER source. One exception (v55): when the Extrato filed exactly 0 or above 5, the lâmina’s single fee is in (0, 5] and the lâmina is NEWER than the Extrato, the newer lâmina is the source. fee_resolution names the rule: extrato, extrato_lamina_beside (Extrato 0 or above 5, a lâmina fee beside it), extrato_to_check (the same with no lâmina fee), lamina_newer, lamina, cad_fi. The other document’s fee is returned as filed whatever the source (lamina_taxa_adm, _min, max, lamina_n_classes, lamina_age_months; extrato_taxa_adm_filed with extrato_as_of), never rescaled and never a fee to sum; extrato_lamina_ratio is the Extrato over the lâmina when both are above 0, and extrato_scale_factor is 10 or 100 when an Extrato above 5 equals that factor times the lâmina within the two-decimal rounding of both, a flag only. The Extrato’s performance fee (extrato_taxa_perfm numeric, extrato_param_taxa_perfm, extrato_calc_taxa_perfm, extrato_inf_taxa_perfm text), entry and exit fees (extrato_existe* flags, _pr percent and _real reais), custody fee and class note are returned as filed; the row is the class for a CVM 175 fund (no subclass column, a subclass fee is not assumed). lamina_pr_pl_despesa is the declared total expense ratio from the lâmina (with its period and lamina_as_of), whatever the fee source, never added to the administration fee. ESTIMATE (adm_fee_flow, perf_fee_flow and the pct_annual_est columns): from the balancete accruals (cvm_fi_balancete_resumo): the fee accounts accumulate from each fund’s fiscal-year start and are filed negative, so the month’s accrual is previous minus current accumulated value (served positive = cost; a negative performance accrual is a reversed provision), annualised x 12 / NAV x 100, NAV = groups 6 + 7 + 8 of the month. In the fiscal-year reset month the accumulated fee falls: fiscal_reset_suspect is TRUE and the estimate is NULL, unless cad_fi DT_INI_EXERC puts the fiscal-year start in that month, in which case the month’s accumulated value alone is the accrual. estimate_label says on every row that the estimate is an estimate and why one is missing; it is never presented as the disclosed fee. ETFs (v56): CVM’s Extrato, lâmina and cad_fi carry no fee for an ETF, so for a CNPJ in SILO’s curated ETF registry etf_ticker names the ticker and etf_site_taxa_adm, etf_site_as_of and etf_site_source give the ‘Taxa de administração total’ etfsbrasil.com.br prints (etf_market_snapshot, the newest snapshot with a fee, joined by ticker): a third-party site, not a CVM filing, never in disclosed*, returned as published; etf_site_note says so and why a value is NULL. Since v57 etf_site_nr_cotistas and etf_site_pl (R$) are the ‘Número de cotistas’ and ‘Patrimônio líquido’ the same site prints in the SAME snapshot (etf_site_as_of): third-party descriptive facts, never summed, never a fee base. Since v68 (#606 Q36) the filed benchmark, whatever the fee source and as filed, never inferred from a name or a class: benchmark_extrato is the Extrato’s PARAM_TAXA_PERFM (the performance fee’s index, the Extrato’s only benchmark column; dated extrato_as_of), benchmark_lamina the lâmina’s INDICE_REFER at lamina_as_of when every class filed the same one, benchmark_lamina_n the count of distinct values filed (0 none, above 1 the classes differ). p_month = the balancete month (NULL = each fund’s newest). One row per distinct CNPJ; more than 200 CNPJs RAISES 22023.
Row cap. A window producing more than 1000 rows raises SQLSTATE 22023 naming this function. Nothing is trimmed to fit — PostgREST would silently cut the response at 1000 and a cut-short series is indistinguishable from one that simply ends. This function does not page — narrow the window instead.
curl --request POST \
--url https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees \
--header 'Content-Type: application/json' \
--header 'apikey: <api-key>' \
--data '
{
"p_cnpjs": [
"<string>"
],
"p_month": null
}
'import requests
url = "https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees"
payload = {
"p_cnpjs": ["<string>"],
"p_month": None
}
headers = {
"apikey": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {apikey: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({p_cnpjs: ['<string>'], p_month: null})
};
fetch('https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'p_cnpjs' => [
'<string>'
],
'p_month' => null
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"apikey: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees"
payload := strings.NewReader("{\n \"p_cnpjs\": [\n \"<string>\"\n ],\n \"p_month\": null\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("apikey", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees")
.header("apikey", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"p_cnpjs\": [\n \"<string>\"\n ],\n \"p_month\": null\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://zcjbtpxuhdekpwcxmepn.supabase.co/rest/v1/rpc/portfolio_fees")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["apikey"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"p_cnpjs\": [\n \"<string>\"\n ],\n \"p_month\": null\n}"
response = http.request(request)
puts response.read_body[
{
"cnpj": "<string>",
"fund_name": "<string>",
"month": "2023-12-25",
"nav": 123,
"adm_fee_flow": 123,
"adm_fee_pct_annual_est": 123,
"perf_fee_flow": 123,
"perf_fee_pct_annual_est": 123,
"fiscal_reset_suspect": true,
"disclosed_taxa_adm": 123,
"disclosed_taxa_adm_min": 123,
"disclosed_taxa_adm_max": 123,
"disclosed_taxa_perfm": "<string>",
"disclosed_taxa_adm_info": "<string>",
"disclosed_taxa_perfm_info": "<string>",
"disclosed_source": "<string>",
"disclosed_as_of": "2023-12-25",
"disclosed_age_months": 123,
"disclosed_n_classes": 123,
"disclosed_note": "<string>",
"estimate_label": "<string>",
"disclosed_origin": "<string>",
"disclosed_age_days": 123,
"filed_zero": true,
"implausible_filed": true,
"taxa_adm_filed_raw": 123,
"extrato_tp_fundo_classe": "<string>",
"extrato_classe_anbima": "<string>",
"extrato_class_note": "<string>",
"extrato_existe_taxa_perfm": "<string>",
"extrato_taxa_perfm": 123,
"extrato_param_taxa_perfm": "<string>",
"extrato_calc_taxa_perfm": "<string>",
"extrato_inf_taxa_perfm": "<string>",
"extrato_existe_taxa_ingresso": "<string>",
"extrato_taxa_ingresso_pr": 123,
"extrato_taxa_ingresso_real": 123,
"extrato_existe_taxa_saida": "<string>",
"extrato_taxa_saida_pr": 123,
"extrato_taxa_saida_real": 123,
"extrato_taxa_custodia_max": 123,
"lamina_pr_pl_despesa": 123,
"lamina_dt_ini_despesa": "2023-12-25",
"lamina_dt_fim_despesa": "2023-12-25",
"lamina_as_of": "2023-12-25",
"lamina_expense_note": "<string>",
"fee_resolution": "<string>",
"lamina_taxa_adm": 123,
"lamina_taxa_adm_min": 123,
"lamina_taxa_adm_max": 123,
"lamina_n_classes": 123,
"lamina_age_months": 123,
"extrato_taxa_adm_filed": 123,
"extrato_as_of": "2023-12-25",
"extrato_lamina_ratio": 123,
"extrato_scale_factor": 123,
"etf_ticker": "<string>",
"etf_site_taxa_adm": 123,
"etf_site_as_of": "2023-12-25",
"etf_site_source": "<string>",
"etf_site_note": "<string>",
"etf_site_nr_cotistas": 123,
"etf_site_pl": 123,
"benchmark_extrato": "<string>",
"benchmark_lamina": "<string>",
"benchmark_lamina_n": 123
}
]{
"code": "22023",
"message": "<string>",
"details": "<string>",
"hint": "<string>"
}{
"code": "22023",
"message": "<string>",
"details": "<string>",
"hint": "<string>"
}{
"code": "22023",
"message": "<string>",
"details": "<string>",
"hint": "<string>"
}Authorizations
The publishable key (sb_publishable_…), on every request. It is NOT a JWT — sending it as Authorization: Bearer is rejected as an invalid JWT. It identifies the project, not you, and maps to the Postgres anon role.
Body
Response
The result set, oldest first. An unknown id is an empty array, not a 404 and never a guessed value.
Was this page helpful?