tellatribe

Enter the access code to read the project documents.

tellatribe Docs Status: All modules built and live · Oct 19: Creator Campaigns Part B shipped (briefs, applications, deals, verification → bounties, brand balance + Stripe funding, disputes, reports) on top of the tax-identity gate and annual statements · awaiting owner inputs: tellatribe Stripe account (payments + Connect + funding webhook), HealthyApp webhook secret, Ayrshare key

tellatribe

A single affiliate platform that sits beside the products rather than inside any one of them. Products call it; it never calls them. It tracks clicks and conversions from affiliate links, calculates commissions across two tiers on an auditable ledger, pays affiliates on a schedule, and equips them with links and promotional collateral already personalised with their own link. HealthyApp is the first tenant, GetBooked and WhoHire follow, and a product added later should require a day of integration work, not a rebuild. The build is internal first and commercial-shaped: one merchant in v1, with the schema, auth boundary, and tokens laid out so selling the platform later is a feature project rather than a rewrite.

What an affiliate does

The whole job fits on a phone, in the gaps between other work.

  1. See what they earned. The portal opens on standing as a sentence: the amount that is theirs and the date it pays, with the pending amount and its hold date beneath. Every figure carries its state — pending, approved, paid, held, reversed — because each one maps to money someone is owed.
  2. Get a link. Each product the affiliate may promote has its own tracked link on that product's domain, plus deep links, campaign labels, and QR codes. One recruiting link brings in a second-tier affiliate.
  3. Take a piece of collateral. The wall shows every product as a row and every asset as a tile that says what it pays and how long it takes. Three delivery modes, in rising order of ease: download and post yourself, connect an account and the platform posts for you, or open a script on the phone and record against a teleprompter.
  4. Answer an open call. Above the brand rows, briefs the creator qualifies for appear as tiles that say what they pay and what they ask; one sheet to apply, then Studio → Deals carries the accepted work from draft to verified post to the payout.

Two tiers, permanently

An affiliate earns a direct (L1) commission on sales they refer and an override (L2) on sales made by the affiliates they recruited. There is no third level, no rank advancement, no volume qualification, and no breakaway.

Two tiers is an ordinary two-tier affiliate program, the structure PartnerStack, FirstPromoter, and Tapfiliate all ship as a normal feature. A third level is what turns a compensation plan into multi-level marketing in the FTC's eyes, and brings the full compliance posture with it: counsel review of the plan, income-claim exposure, state-level registration questions, and a permanent "is this a pyramid?" conversation with every prospective affiliate. The limit is enforced structurally: MAX_DEPTH = 2 in the engine with the legal reason beside it, and CHECK (level IN (1,2)) on the plan-levels table.

Depth is not the only line. Nothing in the system charges an affiliate to join or to recruit, and a commission row cannot exist without a positive conversion, so there is no code path that mints money from the act of recruiting.

Architecture at a glance

products ──► API ──► ledger ──► payouts
 (SDK)      (Vercel)  (Postgres)  (Stripe Connect)
  • Products install @affiliate-coach/sdk: a redirect route on their own domain that records the click server-side and sets first-party cookies, and a helper that carries the click id into Stripe Checkout metadata. No pixel, no client script.
  • API (apps/api, Next.js on Vercel) receives clicks and conversions, authenticates product keys, and mounts the platform Stripe webhook. Conversions are derived from invoice.paid and reversed from refunds and disputes; manual conversions exist for products not on the Stripe path.
  • Ledger (packages/core engine, packages/ledger service, packages/db migrations) is append-only on Supabase Postgres with row-level security. Money columns are frozen by trigger; state advances along defined edges only; every transition is logged. A 30-day hold sits between earning and payability. Money is bigint cents, rates are basis points, and arithmetic floors rather than rounds.
  • Payouts run monthly through Stripe Connect Express from a dedicated tellatribe Stripe account (PayPal Payouts is a later second rail; CSV is the manual fallback). Below-minimum and negative balances carry forward. No verified tax identity (W-9 / W-8 through Stripe), no payout: tellatribe is payer of record and files 1099-NEC, and every affiliate downloads an annual statement whatever the threshold.
  • Campaigns (packages/campaigns) sit on the same ledger: a brand publishes a brief, creators apply from the Wall, an accepted application becomes a deal with a frozen SOW, deliverables move draft → posted → verified, and verification writes a bounty row the payout run pays. Brands prefund a balance through Stripe Checkout; escrow is reserved at acceptance and the 10 % fee comes off at release.

Tests run on PGlite, so the whole chain from migration to ledger service is proven without a database container; the same migrations are applied to the live Supabase project with supabase db push.

The API is live at https://api.tellatribe.com.

Integration in three calls

A product joins in under a working day. The SDK has zero runtime dependencies and never breaks a paying customer's path.

1. The redirect route, on the product's own domain so the cookie is first-party:

// app/go/[code]/route.ts
export { GET } from '@affiliate-coach/sdk/next'

2. At checkout, carry the click into Stripe so month two and beyond stay attributable:

import { getClickId, stripeCheckoutFields } from '@affiliate-coach/sdk/next'

const attribution = await getClickId()
const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  ...stripeCheckoutFields({ ...attribution, product: 'healthyapp' }),
})

3. Manual conversion, only for products not on the Stripe webhook path. convert() never throws:

import { AffiliateCoach } from '@affiliate-coach/sdk'

const ac = new AffiliateCoach({ apiKey: process.env.AFFILIATE_COACH_API_KEY!, product: 'healthyapp' })
const result = await ac.convert({
  clickId, customerRef: 'cus_…', event: 'subscription_created',
  amountCents: 9900, idempotencyKey: 'evt_…',
})

The full contract, including cookie flags, the open-redirect guard, and why the SDK never sets client_reference_id, is in the SDK reference.

Where things stand

All modules built and live · Oct 19: Creator Campaigns Part B shipped (briefs, applications, deals, verification → bounties, brand balance + Stripe funding, disputes, reports) on top of the tax-identity gate and annual statements · awaiting owner inputs: tellatribe Stripe account (payments + Connect + funding webhook), HealthyApp webhook secret, Ayrshare key.

  • Phase 1, the ledger, is complete. 299 tests: 78 on the pure engine with 100% branch coverage and a golden replay, 125 schema tests across migrations 0001–0008, and 96 on the ledger service. Gates 1a, 1b, and 1c are green. The migrations are applied to the live Supabase project, so the chain holds on real Postgres as well as PGlite.
  • Phase 2, tracking, is complete. Gate 2 is green: an SDK redirect becomes a click, first-party cookies carry it into Stripe Checkout metadata, a signed invoice.paid through the mounted webhook produces L1 and L2 ledger rows, and a partial refund produces proportional reversals, all on one tree. 519 tests across six packages. 0009_collateral and the token resolver shipped alongside as the first slice of the collateral vault.
  • The API is deployed to production at https://api.tellatribe.com, prebuilt from the workspace root, with the cron routes registered and smoke-tested.
  • Phase 3 is in progress. Four streams run in parallel on phase-3: the portal shell (apps/portal), the admin app (apps/admin), payouts (packages/payouts), and publishing (0010_publishing with the Ayrshare adapter).

The dated log, the decisions that surfaced during integration, and the fifteen settled decisions are on the Build status page.

The documents

Requirements

  • Product

    Who the affiliate is, the phone as the real product, the two-tier rule, brand commitments, and the portal priorities.

  • PRD v0.2

    The requirements: tracking, the ledger, payouts, the portal, admin, compliance, and the build sequence.

  • Creator Campaigns — strategy & PRD

    Brand briefs, creator applications, deliverables, verification and campaign payments on top of the affiliate platform — with the competitive landscape (impact.com, enterprise SaaS, native marketplaces, networks) and the 20 things a credible campaign platform needs.

  • Creator Campaigns — build contract

    The engine API, admin, portal and API responsibilities the four Campaigns streams were built against, with the engine's §1.7 notes.

  • Activation Platform PRD (frozen v2 vision)

    The commercial platform this build is shaped to become. Kept frozen; not a requirements document for the current build.

Plan

  • Build plan

    Which document governs, the decisions already made, phases and gates, the status log, and the fifteen decisions.

Design

  • Design system

    The Title-Card Wall: colors, type, layout, elevation, shapes, and components, written from the built portal.

  • Portal direction contract

    The chosen visual direction for the affiliate portal, as contracted before the prototype was built.

  • Finish review

    The prototype's finish review: fidelity against the contract, material fixes, and the verdict.

Build tracks

Reference

  • Working in this repo

    Authority, shape, test harness, SQL house style, money rules, secrets, and the deploy recipe.

  • SDK

    What a product installs to join: the redirect route, the checkout fields, and the manual conversion call.

  • Campaigns engine

    What the Creator Campaigns engine does between a brief and the bounty the payout run pays: modules, balance semantics, errors, usage.

  • Prototype image provenance

    Where each image in the prototype came from.

  • Decisions for review

    Calls made without the owner while building to completion — each one reversible; change any and it propagates.

  • Paid social set

    The Facebook/Instagram ad set and the 14 UGC videos: copy, specs, scripts, compliance rules, how to regenerate.

  • Stripe setup guide

    For the Stripe administrator: the new tellatribe payout account (Connect Express, restricted key, Connect webhook, funding) and the read-only revenue webhook on each product's account; what to hand over and how.

Also here

  • Build status

    The dated log and the settled decisions, read from the build plan.

  • Screenshots

    Every captured surface, grouped and captioned, with its provenance.