ERF PENSION app icon

Dallas ERF · single-plan member view

Member data the ERF Pension app surfaces, and reading it on a member's behalf

The Dallas Employees' Retirement Fund runs one defined benefit plan with two membership tiers, and the ERF Pension app is the single member-facing view in front of it. The app, per its Play Store listing, is published through Bravo Studio — a Figma-to-app pipeline — which means the client is generated and the substance lives in the dallaserf.org backend the client calls. An integration here is not a generic banking pull; it is a single-plan, single-tenant read against a named municipal pension's member self-service backend, scoped to one member at a time and authorized by that member.

Data the app holds, surface by surface

The member screens are narrow but specific. Each row below names a surface the integration reaches behind the same member session that the app itself uses.

DomainWhere it shows in the appGranularityWhat an integrator does with it
Member profileAccount / identity panelMember ID, hire date, tier (A or B), employee groupIdentity binding, tier-aware routing for all downstream logic
Service creditService historyPer-period accrual; cumulative years and monthsVesting checks (5-year line, per ERF), eligibility windows
ContributionsContributions ledgerPer-pay-period employee contribution amountsReconciliation with payroll, projection inputs
Final average payPay history / estimate3-year window (Tier A) or 5-year window (Tier B)Benefit calc, what-if modeling at different retire dates
Benefit estimateEstimate / projection screenMonthly pension at chosen retirement datePlanning tools, side-by-side scenarios
Beneficiary designationBeneficiary screenNamed designees, allocationDisposition modeling, survivor scenarios
Disability / survivor statusBenefit type indicatorEligibility flagsBranching for non-service-retirement cases
Retire Now documentsAdjacent web portalForms, notarized submissions, statusWorkflow integration for retirement initiation

This is not a brokerage app or a checking account. There is no order book, no payment rail. What the integration moves is benefit data and the consent to read it.

How we reach those surfaces

Three routes are real here. They are not equivalent and we do not pretend they are.

Member-consented self-data retrieval

The member authorizes the integration to act on their behalf against the dallaserf backend. This is the route that scales for an end-product where each user sees only their own statements. Consent is recorded with scope and expiry; tokens live behind our infrastructure, not the client.

Protocol analysis of the app's traffic

Run under the same member's authorization, the analysis captures the auth handshake (login, token issuance, refresh) and the JSON envelopes the Bravo Studio shell consumes. The artifact is a documented endpoint catalog and an OAuth/cookie flow report. Without this the consented retrieval has nowhere to send its requests.

Retire Now portal automation

Where the use case touches retirement initiation rather than just reading statements, the integration is wired through the Retire Now portal session — the same place the member submits forms and notarized documents, per ERF's active-employees page. This route is heavier and only worth opening if forms are in scope.

For a member-facing product the first route carries most of the actual work, and the protocol analysis is what makes it implementable end to end. If the use case is purely retirement-application flow, weight shifts to the third.

A read against the member backend

The snippet below is illustrative, with field names and paths to be confirmed during the build. The branching on tier is real and is exactly the kind of thing a generic pension SDK gets wrong on a single-plan deployment.

# Illustrative — endpoint names and JSON keys confirmed during protocol analysis.
# Member-authorized session against the dallaserf backend the ERF Pension app calls.

session.post(
    "https://api.dallaserf.example/v1/auth/login",
    json={"member_id": MEMBER_ID, "credential": MEMBER_SECRET},
    headers={"X-Client": "erf-pension-integration/1.0"},
)
# token returned; rotated per the observed refresh window

profile = session.get(f"/v1/members/{MEMBER_ID}/profile").json()
tier    = profile["tier"]                   # "A" or "B" per ERF
hire    = profile["hire_date"]

# Tier-routed benefit logic — per ERF's tier explainer:
# Tier A: 2.75% multiplier, 36-month final-pay average
# Tier B: 2.50% multiplier, 60-month final-pay average
multiplier      = 0.0275 if tier == "A" else 0.0250
averaging_mos   = 36     if tier == "A" else 60

contribs = session.get(
    f"/v1/members/{MEMBER_ID}/contributions",
    params={"from": "2020-01", "to": "2026-05"},
).json()

estimate = session.post(
    f"/v1/members/{MEMBER_ID}/estimate",
    json={"retire_at": "2030-06-01"},
).json()
# estimate["monthly_pension"] capped at 100% of average monthly salary per ERF

Shape we normalize the response into

The wire format the app receives is convenient for the client but not for downstream tools. The integration emits a stable shape so a finance system, a retirement planner, or a CSV export all consume the same object.

{
  "member": { "id": "…", "tier": "B", "vesting_status": "vested" },
  "service_credit": { "total_months": 184, "as_of": "2026-05-30" },
  "final_average_pay": { "window_months": 60, "amount_usd": 6420.50 },
  "benefit_estimate": {
      "retire_at": "2030-06-01",
      "monthly_pension_usd": 4810.00,
      "formula": { "multiplier": 0.0250, "service_years": 19.5 }
  },
  "beneficiaries": [ … ],
  "consent": { "scope": ["profile","contribs","estimate"], "expires": "…" }
}

What lands in the repo

Source delivery is what the studio actually hands over. For ERF Pension that is:

  • An OpenAPI 3 spec for the consented endpoints the integration calls (auth, profile, service credit, contributions, estimate, beneficiaries), with the tier-routing semantics annotated rather than buried in client code.
  • A protocol & auth-flow report — the login, token issuance, refresh cadence, error envelopes — written from observed traffic under member authorization.
  • Runnable source in Python and Node.js for each endpoint, plus a normalized-shape adapter so callers do not bind to the wire format.
  • An automated test pack: a contract test against recorded responses, plus a schema-drift watcher so a quiet backend change does not silently break a statement.
  • Operating guidance: how to record consent, how to revoke, how long to retain, what to log, and what minimization to apply before anything leaves the integration.

Authorization, and the Texas oversight piece

A municipal pension fund in Texas is not under federal open-banking machinery — pensions are not Reg E accounts, and the Personal Financial Data Rights conversation in Washington does not govern reads against ERF. The dependable basis for this integration is the member's own authorization to retrieve their own data, recorded with scope and a revocation path.

For plan-level reporting, Dallas ERF is one of the funded defined benefit plans registered with the Texas Pension Review Board under Chapter 802 of the Texas Government Code; the PRB data center publishes the aggregate actuarial and funding data for the plan (see data.prb.texas.gov/plans/98.html). That oversight is about the plan; it is not the consent layer for an individual member's retrieval. We keep those two separate, both in the documentation and in how the integration logs what it touched.

The compliance posture on the studio side: authorized access only, recorded consent per member, data minimization on the way out, NDA with the client where one is required, and an audit log that survives independently of the member's session.

Things we plan for during the build

Three notes carry most of the weight on this one.

Tier A versus Tier B routing. We map the formula divergence — multiplier, averaging window, vesting age — to the tier field on the profile, not to a hard-coded default. A client deploying this with members on both tiers, which any City of Dallas department will have, gets correct accrual logic for each. Getting this wrong is silent: the statement still renders, the number is just off.

Bravo Studio re-publish risk. The app is a generated Figma front end. A re-publish can rearrange the UI without moving the backend; less often, it can move bindings without notice. We pin the integration to the backend endpoints and the auth flow, and the schema-drift test reruns on a schedule so a quiet change is caught before it shows up as a wrong figure.

Retire Now scope decision. The portal is a different surface from the app, with its own session and its own form set. We pick that up only when the use case actually needs retirement initiation, and we say so explicitly in the scope document rather than rolling it in by default and inflating the build.

Pricing and how the engagement runs

Source-code delivery starts at $300 and is paid only after the build is in your hands and you have signed off on it; the alternative is a pay-per-call hosted API where you call our endpoints and pay only for what you use, with no upfront fee. Cycle is one to two weeks for an integration of this scope. You give us the app name and what you want from the data; access arrangements, member authorization handling, and the compliance paperwork are run with you during onboarding rather than presented as homework. Start a conversation if either model fits.

What was checked, and by whom

The page was put together from the ERF tier explainer (Tier A and B formulas, vesting), the Texas Pension Review Board's plan data sheet for Dallas ERF, the ERF active-employees page describing the Retire Now portal, and the Play Store listing confirming the Bravo Studio build. Specifically: dallaserf.org/tiers-explained, data.prb.texas.gov/plans/98.html, dallaserf.org/active-employees, and the Play Store listing at play.google.com.

OpenBanking Studio · integration desk, 2026-05-30.

Other public pension apps and portals in the same shape

An integrator working on ERF Pension is almost always going to compare it with these — different plans, similar surfaces. Listed neutrally for context, not ranked.

  • MyNYCERS — the New York City Employees' Retirement System self-service app, with contribution balances and pension payment history for retirees.
  • myCalPERS Pay Warrant — California Public Employees' Retirement System app for viewing retirement checks; the broader myCalPERS portal carries the member statement.
  • CalSTRS member portal — California State Teachers' Retirement System; member-facing service credit and benefit projections.
  • SDCERS Member Portal — San Diego City Employees' Retirement System; beneficiary updates and estimate tools.
  • MEABF member services — Municipal Employees' Annuity and Benefit Fund of Chicago; a comparable single-municipality DB plan surface.
  • Seattle SCERS — Seattle City Employees' Retirement System; defined benefit plus optional deferred-comp data.
  • INPRS My Account — Indiana Public Retirement System member self-service.
  • Fort Worth Employees Retirement Fund — a Texas peer to Dallas ERF, similar oversight envelope.
  • ERFC member portal — Educational Employees' Supplementary Retirement System of Fairfax; a supplemental DB plan with its own member surface.

A serious unified-integration client is usually building against three or four of these at once. The shape rhymes; the field names do not.

Questions integrators have asked about this one

Does reading Dallas ERF data require coordinating with the City of Dallas HR system, or only with ERF itself?

Personal benefit, service-credit and contribution records sit with ERF. Payroll inputs upstream of those numbers sit with the City. A member-side integration only has to touch the ERF surfaces; a finance or HR reconciliation has to touch both, and we scope which one you actually need before we start cutting code.

The app is published through Bravo Studio from a Figma design. Will the integration break the next time the front end is re-published?

A Bravo Studio re-publish rearranges the client; the backend the client calls usually does not move. We pin the integration to the backend endpoints and the auth flow, not to the UI bindings, and the test pack runs a schema check against the recorded responses on a cadence so a quiet drift is caught before it shows up as a bad statement.

Can one integration cover both Tier A and Tier B members?

Yes — the member profile call carries the tier, and the integration branches the benefit formula on that: 2.75% multiplier with a 36-month final-pay average for Tier A, 2.5% with a 60-month average for Tier B, per ERF's tier explainer. Vesting age also differs between the tiers, so any retirement-eligibility logic reads from the same profile field rather than a hard-coded default.

How is the member's authorization recorded and revoked for a consented pull like this?

A signed authorization is stored against the member identifier, with the scope (which data domains, for how long), the timestamp, and the tokens issued. Revocation tears down the tokens and stops the next scheduled pull; the audit log keeps the prior consent so a future dispute about what was read and when has a paper trail.

App profile (collapsed)

ERF PENSION is the native member application of the Employees' Retirement Fund of the City of Dallas, a defined benefit plan for the City's non-uniformed permanent employees. The fund describes itself as providing retirement, disability and survivor benefits to members and their beneficiaries. The app gives members a mobile view of their pension fund information; the related Retire Now web portal handles retirement forms and notarized document submission. The mobile build is generated through Bravo Studio (Figma-to-app), per its Play Store package app.bravostudio.A01HG6H805NX7QM7G8H30D07H8S.

Mapping reviewed 2026-05-30.