Dados B3 › Transparency
Transparency
Transparency — how you check the numbers yourself
Data version 2026-11-09-ancora-do-fre · page generated 2026-11-12 08:09 UTC. If these do not match /saude, you are reading a cached copy.
What is checked, before every publication — 1298 automated tests, collected live
41 are DATA invariants (does the number tie out?) and 131 are product tests — access gate, navigation, language, AI connector. Calling all 1298 'invariants' would be inflating it: the split is checkable in the list itself. Not a hand-picked highlight reel: every test below was found by introspecting the actual test files just now, the same way pytest --collect-only would. Grouped by what it protects against, not by which file it lives in.
Level 1 — Integrity: does the data tie out? (41)
PR05— The free-key button leads to a form, not to the payment provider. The free tier is a zero-value subscription, and the path to it used to be the same checkout as the paid plan — no card requested, but wearing the face of a payment form. The funnel measured the cost: 47 people opened it and 16 finished. Asking someone to cross a billing screen to collect something free is friction with nothing on the other side.PR06— The plans page states who the charge comes from. Forty-six checkouts were opened and none was paid, and at the last step the customer met a company name the site had never mentioned. The public name at the payment provider is now the product's, but the registered entity is still another one and it is the entity that appears on the invoice — so the page says so BEFORE, instead of leaving the discovery for the moment of the card.PR07— A malformed e-mail creates no customer, and neither does a crawler. Without the checkout in front, creating a key became an anonymous POST that creates a customer at the payment provider. The two remaining doors are e-mail validation and the crawler filter — the same one already blocking bots on the plans page, where 27 of 72 visits were automation.PR08— A created key records WHERE the person came from — the tag on the link we sent out and the optional 'how did you find us' answer — and none of it is stored with the e-mail. Without cookies, the entry visit and the key created later were rows with nothing linking them: the dashboard said 'N keys' and could not tell whether any came from the AI connector, from llms.txt or from an AI assistant. Tags come from a closed list; an invented tag is dropped, never stored as free text.PR09— The paid checkouts (card and Pix) ask Stripe for abandoned-cart recovery (a recovery link and the marketing-consent box on Stripe's own page); the free one does not. If Stripe rejects those parameters, the session is created again without them: checkout never fails because of the extra. On 16/10/2026, 48 of 55 paid checkouts opened in 30 days were abandoned.PR10— The welcome e-mail approved by the owner goes only to FREE-plan key holders (no Pro, not the owner, no repeated address), with replies going to the owner; the dry run only counts; a second run skips whoever already got it; a failed send is recorded as failed and retried next time; the route does not exist without the admin token.PR11— The site sends the reminder for a PAID checkout that expired only to people who ticked the consent box on Stripe's page, with the recovery link and replies going to the owner; a R$ 0 (free) checkout, one without e-mail or link, or from someone who completed another checkout in the window is skipped; nobody gets it twice; a Stripe failure never raises.PR12— The screener (stocks and REITs) offers a download of this list as a spreadsheet with the SAME filters; the spreadsheet is Pro only (free key 403, no key 401) and holds exactly the rows on screen, in the same order, with percentages in percent and the caveat in its own column; the key may come in the URL (the form sends it that way).PR13— The plans page (PT and EN) shows what Pro does for daily users: the screener list as a spreadsheet, the database as CSV, direct answers within 1 business day and the 7-day guarantee up front; and still says nothing was taken away from the free tier.PR14— Every campaign and reminder e-mail carries a one-click stop link (and Gmail's List-Unsubscribe): the link is signed (no one can unsubscribe someone else) and does not carry the address; opening it (GET) only asks, the POST records; whoever stopped gets neither the campaign nor the reminder; a stop sent by reply enters through the token-protected panel; if the list cannot be read, the campaign does not go out.PR15— An HTML page requested with utm_source/utm_medium/utm_campaign goes out with the same mark on its internal links (the a-href paths starting with a slash), so the next click (for example /assinar) arrives marked and the panel can count the journey from a campaign to the Pro page — no cookie, nobody identified; personal links, admin and the canonical tag are not marked; only the three utm fields, normalized.PR16— The key page tells the FIRST delivery (chave_entregue plus the plan, the conversion) from an existing subscriber reopening their own key (chave_reaberta plus the plan, not a conversion); the key is the same both times; without payment, nothing is delivered and the route answers 402.PR17— A request with a browser User-Agent but without Accept-Language, or claiming Chrome without sec-ch-ua, is a program, not a person: it is recorded as robo_disfarcado (bot) and stays out of the visitor count; real browsers stay human; Firefox does not need sec-ch-ua; no header is stored.PR18— The GET of the subscribe route shows a confirmation page and does not charge: no payment session at the provider and no funnel event. Robots dressed as browsers, in bursts of five hits in the same second, were opening fake checkouts through a GET that had side effects.PR19— The POST of the subscribe route creates the session, records the funnel event and answers with a 303 redirect to the payment page, never a 307 that would resend the POST.PR20— A declared crawler that POSTs to the subscribe route opens neither a session nor an event, for card and for Pix: the robot filter stays on the route that charges.PR21— Someone who gives up on the card form returns to the plans page, not to the home page, where there is no price and no Pix option.PR22— On the plans page Pix and card are buttons of the same weight (same class), side by side, with Pix first for the Portuguese-speaking public.PR23— On the free-key form, the e-mail of a Pro subscriber (or of someone who already has a free key) does NOT return the key in the HTML or the JSON: the page says that if the e-mail already has a key we are sending it there, and the key goes only to that same e-mail. A new e-mail still sees its new key on screen, with no e-mail sent, so the free funnel does not get worse.PR24— No enumeration: on the free-key form the answer for an existing key is identical for Pro and free (it does not reveal the plan); on the subscriber portal the answer is identical for a customer e-mail and an unknown one. Sending happens after the response, so the response time does not depend on whether the customer exists.PR25— The API key alone does not open the Stripe portal: the page asks for the e-mail; a key in the header or in the old form neither redirects nor creates a Stripe session, it only sends a link to the e-mail registered at Stripe.PR26— The portal link is single-use and expires in 30 minutes: opening it only shows a button (an e-mail scanner that pre-opens links does not burn it); the button opens the right customer portal once; a second use, an expired link or an invented one gets 410; the disk keeps only a hash, never the link or the e-mail.PR27— Fail closed: in production (RENDER=true) without the Stripe keys, the Pro dump, the key routes and the Pro check answer 503 instead of opening everything; only the sample stock stays open. Outside production, without Stripe, everything stays open as before (development).PR28— Without the webhook secret, the Stripe webhook answers 503 and neither reads nor processes the body (before, it was read as raw JSON); with the secret, a wrong signature is 400 and the right one is accepted.PR29— Key resends and portal links are capped at 3 per hour and 10 per day for the same e-mail, counted on disk; past the cap the page is the same and nothing is sent, and different e-mails do not share the cap.PR30— Asking for deletion answers the same (status and text) whether or not data is linked to the e-mail, sends the confirmation link only to that same e-mail and only if something exists to delete, deletes nothing at request time, refuses a malformed e-mail and ignores robots.PR31— The deletion link is single-use: opening it only shows a button (an e-mail scanner that pre-opens links deletes nothing), the POST deletes once, an invented or expired link or a portal link deletes nothing, and the deletion link does not open the Stripe portal.PR32— Once the link is confirmed, the Stripe customer record is emptied and deleted and the key leaves the cache; follow-ups, portfolio, bulletin, weekly-send history, trial request, waiting e-mails and the usage counts of the key disappear for that person only; campaigns swap the e-mail for its hash; receipts lose only the owner; the hash goes to the do-not-send list; the event keeps the hash, never the e-mail, and no disk file keeps the e-mail in readable bytes.PR33— Without an e-mail provider the request and confirmation routes answer 503 with the contact and write nothing (not even the pending-mail file, which would keep the address); in production without Stripe, the same.PR34— The daily snapshot file has no column about a person (e-mail, name, key, IP...) and the deletion leaves it byte for byte as it was.PR35— Repeated deletion requests respect the same cap as the portal: at most 3 e-mails per hour and 10 per day to the same address, and the page stays the same.PR36— The hourly resync skips a deleted Stripe customer who once paid by Pix: it does not try to write a key on it (which would break the whole resync) and does not give the access back.PR37— The owner's key lookup route /admin/chave/{prefix} does not exist without the admin header: 404 with no token, a wrong token, or the token in the query string, and 503 with the right token when Stripe is not configured. Nothing is asked of Stripe before the door.PR38— The lookup prefix must be 8 to 32 lowercase hexadecimal characters; anything shorter, longer, upper-case or with symbols is refused with 422, so nobody can list every customer with a one-character prefix.PR39— A matching prefix returns the key owner's e-mail, plan, whether the subscription is active, creation date and a usage summary (successful calls, active days, first and last day, most used endpoint families, 429 count), without caching and without writing anything.PR40— The API key itself, or any part of it, never appears in the lookup response, and the customer's e-mail never reaches the log, even when Stripe fails.PR41— A prefix matching more than 5 customers returns only the count and asks for a longer prefix, with no e-mail; an unknown prefix returns zero.PR42— The key-hash index lives in memory for a few minutes, so repeated lookups scan Stripe once, and the route never modifies, deletes or creates anything in Stripe.PR43— The owner can replace the key of a customer who asks for it: the old key stops working at once, the new one keeps the same plan and goes only to the e-mail on file, never to the response or the log.PR44— Replacing a key needs the owner token (404 without it); an invalid body gets 422; an e-mail with no key, or with two accounts holding keys, gets 409 and nothing changes.PR45— The thank-you e-mail approved by the owner on 2026-11-01 goes only to FREE keys used on 3 or more distinct days in the last 30; Pro, the owner, occasional keys and anyone already sent are left out; the dry run only counts; replies go to the owner; the route does not exist without the admin token.
Level 2 — Semantics: does the account mean what the calculation assumes? (0)
Level 3 — Economic: is the result possible in the real world? (0)
Other product tests (4)
Access gate, navigation and the MCP connector — they test whether the product works, not whether a number is right, so they don't fit the 3 levels above by design. Still counted, still listed:
PR01— This file's header may not lose the warning that passing the suite is not proof of truth.PR02— No indicator goes live without a methodology page.PR03— Someone who has not chosen a plan sees the plans, not a credit card form. The subscribe route was a redirect straight into a live Stripe checkout, and the plan parameter defaulted to the paid tier, so eighteen links across the site, including the nav button, threw readers from a content page into a charge they had not asked for. The funnel showed exactly what you would expect: forty-one paid checkouts opened and zero card attempts, not one declined. Nobody balked at the price; people landed on a form they never requested.PR04— The plans page shows the free tier before the price. This is not an aesthetic preference: the free door is the only one with measured conversion, nine out of thirty-one against zero out of forty-one, so a page leading with the price pushes everyone toward the door that does not convert. The check reads the body only, because the meta description names both prices and is not visual order — the test itself once failed for that reason, and the defect was in the test.
Reconstruct it yourself — net margin across 5 companies, 4 sectors
We don't ask you to trust the numbers. Here's the net margin of five companies in four different sectors, each rebuilt straight from its annual report (DFP) at the CVM — net income ÷ revenue, matching the published figure exactly. For ANY indicator, of any company, the whole chain down to the line in CVM's file is at /linhagem:
| Company · sector | Net income (CVM acct) | Revenue (CVM acct) | Margin =÷ |
|---|---|---|---|
| WEGE3 · industrial | R$ 6.78 bn DRE:3.11 | R$ 40.80 bn DRE:3.01 | 16.6% |
| VALE3 · mining | R$ 11.81 bn DRE:3.11 | R$ 213.59 bn DRE:3.01 | 5.5% |
| PETR4 · oil & gas | R$ 110.61 bn DRE:3.11 | R$ 497.55 bn DRE:3.01 | 22.2% |
| ITUB4 · bank | R$ 45.85 bn DRE:3.09 | R$ 387.12 bn DRE:3.01 | 11.8% |
| BBAS3 · bank | R$ 16.78 bn DRE:3.11 | R$ 319.46 bn DRE:3.01 | 5.3% |
Download any of these DFPs from the CVM, take the income and revenue accounts, divide — you get the same number. Banks use interest income as revenue (what makes sense for a bank), so the reconciliation is sector-aware; the others use sales revenue. Figures are the latest fiscal year.
Why we may differ from another site (and it's not an error)
A difference between two sites usually isn't one being wrong — it's a method choice. We disclose ours:
- Average vs ending capital: ROE and ROIC use average equity/capital (this year + last ÷ 2), not the ending balance — so they're not a naive single-year division.
- Controlling vs consolidated: we state which one each item uses.
- TTM vs annual: quarterly multiples use trailing-twelve-months earnings.
- IFRS 16, goodwill, cash, exceptional tax: each handled explicitly and flagged when it distorts.
Do the tests bite? Yes — real cases the suite has caught
A test that never fails could mean perfect data — or a weak test. These were born from real errors that slipped through, and now fail — only shown for tests that actually exist in the collected suite above:
- I-B16 · banks' P/E = 0: the CVM reports share count sometimes in units, sometimes in thousands (varying by company and year); market cap came out 1000× too small and P/E was zero. I-B16 (price × shares recomputed) caught it — we fixed 661 annual and 2,027 quarterly multiples.
- I-B24 · the vanishing profit: the profit/equity account varies by bank (Itaú 3.09, BB 3.11); if the label search fails, the number vanishes silently and ROE is born wrong. I-B24 makes that hole fail.
- H-B23 · the 800% dividend yield: old B3 dividends carry a price not adjusted for splits; without H-B23 the yield would look absurdly real. The flag keeps the record and warns.
- I-B20 · the missing COTAHIST 2023: on the first deploy one year of prices failed to download silently; the API shipped with ~50k fewer prices and the suite passed, because nothing checked coverage. We added I-B20 — a year without prices now fails the build loudly.
- I-B33 · Oil & Gas at −89.6% in one week: COTAHIST isn't split-adjusted; a 10:1 split read as a −90% weekly return and stayed in the cumulative return forever, with nothing failing (a blind amplitude filter didn't fix it either — it just flipped which direction was wrong). I-B33 (no sector week beyond ±35%, the ruler is the exchange itself) stops the build.
- I-B31 · 364 of 865 sector-index weeks frozen: extending the series back to 2010, a sector with no company carrying a market cap that week turned into a factor of 1.0 — a flat line that the cumulative return read as 'market stood still', and the 'since 2010' return came out fictional (+527%). I-B31 fails on any week repeated to the cent.
- I-E05 · EMBRAER's 2010 P/E priced with 2025 data: the point-in-time price lookup fell forward with no ceiling whenever the current ticker had no price at balance-sheet time (ticker change, share-class migration); the multiple came out priced 15 years into the future, in 22% of annual and quarterly rows, silently. The 45-day window (and I-E05) blocks it: no session inside the deadline, no multiple computed.
- I-E04 · AZUL at R$ 1.67 quadrillion market cap: the balance sheet carried 54.7 trillion shares from the judicial recovery issuance, but the price used was already on the post-reverse-split (1:150,000) basis — two ends measured on different bases, market cap wrong by orders of magnitude. I-E04 (market cap never above Brazil's GDP) fails the build on that absurdity.
How far back each block of data goes
No asterisks here: this is coverage year by year, counted right now. Indicators (ROE, ROIC, margins, growth) come from the filings alone and cover the whole series. Multiples (P/E, P/BV, EV/EBITDA) need a price and a share count — and the share count comes from CVM's reference form, which the further back you go the fewer companies filed in a usable format. The gap between the two columns is a source limit, not an ingestion hole. If you look for an old P/E and do not find it, it is because nobody has it — not because we hid it. The same numbers as JSON: /cobertura.
| Year | Companies with indicators | Companies with multiples |
|---|---|---|
| 2025 | 441 | 290 |
| 2024 | 443 | 296 |
| 2023 | 441 | 298 |
| 2022 | 428 | 295 |
| 2021 | 422 | 296 |
| 2020 | 410 | 274 |
| 2019 | 371 | 166 |
| 2018 | 326 | 167 |
| 2017 | 317 | 165 |
| 2016 | 311 | 154 |
| 2015 | 303 | 144 |
| 2014 | 301 | 140 |
| 2013 | 292 | 131 |
| 2012 | 291 | 112 |
| 2011 | 284 | 98 |
| 2010 | 277 | 34 |
Live coverage
457 companies · 884,647 price points · 8,650 recorded restatements · last refresh 2026-11-12 01:38:24. Full live counts at /saude.
Sources: CVM (open data, ODbL) and B3 (COTAHIST). Not affiliated with B3 or the CVM. Not investment advice.
Numbers on this page are live. Data version 2026-11-09-ancora-do-fre · page generated 2026-11-12 08:09 UTC. If this does not match /saude, you are reading a cached copy.