TEASEDocs
ProductsClubTroubleshooting

Naming collisions to not conflate

Same-sounding names, different things — a third-party "Chatter" API that isn't your team, two unrelated PPV pricers, and two smart-link systems with near-identical filenames.

chatterapi.py is a third-party platform, not your team model

This is the one most likely to mislead a developer reading the code cold

app/products/club/core/chatterapi.py is a Bearer-key REST client for an external Chatter Stats&Sales API — a third-party platform that tracks Telegram/Fanvue sales, unrelated to this product's own team/chatter model (app.core.operator, the Operator/OperatorShift/ Conversation tables covered in the inbox concepts page). The two share the word "chatter" because the third-party product happens to be named that — not because one is a client for the other.

If you're reading core/chatterapi.py, scripts/poll_tg_sales.py, or scripts/poll_chatter_fans.py and looking for where it plugs into the roster, leaderboard, or shifts — it doesn't. It's a separate Telegram sales feed with its own base URL and its own Bearer key (TG_CHATTER_API_BASE / TG_CHATTER_API_KEY, both env-only), pulling in money as already-net cents from a platform this codebase doesn't otherwise touch.

Two unrelated suggest_ppv_price functions

Both are real, both are live, and they take different arguments and answer slightly different questions:

core/pricing.py::suggest_ppv_pricecore/ppv/pricing.py::suggest_ppv_price
Inputslifetime_net_cents, this fan's own avg_ppv_centsspend_cents, resolved country
SignalSpend tier, nudged toward the fan's own PPV historySpend tier × country purchasing power (PPP)
Reached fromGET /chatters/fan-pricingGET /inbox/fan/{fan_id}/ppv-suggest
Used byOlder fan-context panelThe live PPV composer (ComposerPpvPanel) — the endpoint's own code comment calls the country-PPP signal "the moat"

Both functions clamp their result to OnlyFans' $3–200 bounds and both are advisory-only — neither ever auto-charges a fan. If a price looks off, check which endpoint (and which function) actually produced it before assuming either one is broken.

api/admin/smart_links.py (/api/admin/smart-links, hyphenated) is the read API for the pooled OfSmartLink registry plus CAPI pixel config. api/admin/smartlinks.py (/api/admin/smartlinks, no hyphen) is a completely different, creator-facing CRUD for Route Spine's trial/paid policy smartlinks (models.Smartlink), served publicly at /r/<slug>. The filenames differ by one underscore and the URLs by one hyphen — read the module docstring, not the filename at a glance, before assuming which one a given route belongs to.

What's next

On this page