Skip to content

Database Reference

Full schema reference for the Affiliate Platform PostgreSQL database (hosted on Neon). All tables are managed by Prisma ORM. The database has two environments: staging and production — each is a separate Neon project.


Auth Tables

These tables are managed by BetterAuth and handle identity, sessions, and email verification.

User

The central user record for every account on the platform — both creators and admins.

FieldColumnTypeNotes
ididString (UUID)Primary key
emailemailStringLogin email. Unique. Read-only after creation.
emailVerifiedemailVerifiedBooleanSet to true after first magic-link sign-in
namenameStringDisplay name shown across the platform
profilePhotoUrlimageString?URL to profile photo in Vercel Blob storage
roleroleString"user" (default) or "admin". Controls access to /admin.
tiertierInt1, 2, or 3. Controls slug customization. See Auth → Creator Tiers.
legalNamelegal_nameString?Full legal name for payout records
phonephoneString?Phone number
biobioString?Creator bio
statusstatusString"active", "inactive", or "pending"
internalNotesinternal_notesString?Admin-only notes, not visible to creators
internalPlatformsinternal_platformsTEXT[]Array of platform keys. Controls dashboard access and magic-link email content. Values: "Affiliate Platform", "Ps-Workflow".
airtableEmailairtable_emailString?Email used in the Airtable creator database for sync matching
createdAtcreatedAtDateTimeAccount creation timestamp
updatedAtupdatedAtDateTimeLast update timestamp
lastSignedInAtlast_signed_in_atDateTime?Most recent sign-in timestamp

→ See Auth, Admin Panel → Users, Creator Experience → Settings


Session

Active authenticated sessions. One row per active sign-in.

FieldTypeNotes
idStringPrimary key
userIdStringFK → User.id
tokenStringSession token stored in the browser cookie
expiresAtDateTimeWhen the session expires
ipAddressString?IP address at sign-in time
userAgentString?Browser/device user agent string
createdAtDateTime
updatedAtDateTime

→ Created on every sign-in (magic link or Google OAuth). Also created when an admin impersonates a creator. See Auth → Sessions.


Verification

Short-lived tokens used for magic-link emails. One row per pending verification.

FieldTypeNotes
idStringPrimary key
identifierStringThe email address being verified
valueStringThe one-time token embedded in the magic-link URL
expiresAtDateTimeToken expiry — short window (minutes)
createdAtDateTime?
updatedAtDateTime?

→ Created when a creator requests a magic link. Consumed (deleted) on first use. See Auth.


Creator Tables

Profile data, channels, and platform associations for creator accounts.

CreatorChannel

Social media channels a creator has registered for link generation.

FieldTypeNotes
idStringPrimary key
userIdStringFK → User.id
platformStringe.g. "youtube", "tiktok", "instagram_reels"
handleStringCreator's channel name / handle
channelIdString?Platform-specific channel ID
urlString?URL to the channel
isPrimaryBooleanWhether this is the default channel for link generation
followerCountInt?Follower/subscriber count (informational)
createdAtDateTime
updatedAtDateTime

→ Populated during onboarding and editable from Settings → Channels. See Creator Experience.


CreatorPlatform

Alternative creator channel table (legacy/parallel to CreatorChannel).

FieldColumnTypeNotes
ididStringPrimary key
userIduser_idStringFK → User.id
platformplatformEnumPlatform enum value
handlehandleStringCreator handle
urlurlString?Channel URL
isPrimaryis_primaryBooleanPrimary channel flag
createdAtcreated_atDateTime
updatedAtupdated_atDateTime

→ Referenced by OfferApproval.creatorPlatformIds when a creator requests offer access.


UserSecondaryEmail

Additional email addresses associated with a user account.

FieldTypeNotes
idStringPrimary key
userIdStringFK → User.id
emailStringSecondary email address
createdAtDateTime

Offer Tables

Financial product offers available on the platform, their providers, access controls, and approval tracking.

Offer

Each row represents one financial product offer (e.g. "SoFi Personal Loans", "QuickBooks").

FieldTypeNotes
idStringPrimary key
nameStringDisplay name of the offer
brandString?Brand/company name
descriptionString?Description shown to creators
categoryStringOne of: investing, credit_cards, banking, insurance, loans, business, general
featuredBooleanIf true, shown in the Featured Offers grid on creator dashboards
statusString"active" or "inactive"
visibilityString"public" (visible to all creators) or "private" (allowlist-only)
approvalTypeString"none" (auto-approve), "standard" (admin review), "approval_required" (review + admin-provided URL)
imageUrlString?Offer logo/image URL
slugString?URL-safe identifier used in routing
payoutString?Human-readable payout description (e.g. "Up to $150 per conversion")
conversionEventString?What counts as a conversion (e.g. "Approved application")
howToPromoteString?Admin notes on best promotion practices, shown to creators
createdAtDateTime
updatedAtDateTime

→ See Offers & Providers, Admin Panel → Offers.


OfferProvider

One row per affiliate network/partner configured for an offer. An offer can have multiple providers.

FieldTypeNotes
idStringPrimary key
offerIdStringFK → Offer.id
displayNameStringHuman-readable provider name
dataSourceStringHow links are generated. Values: custom, manual, redeventures, money_com, bankrate, quinnstreet, impact, partnerstack
defaultWeightIntPercentage of traffic this provider receives (0–100). All active providers for an offer must sum to 100.
activeBooleanInactive providers are excluded from weight validation and traffic routing
affiliateUrlTemplateString?For custom data source — URL with {slug} placeholder
baseUrlString?For RedVentures/Money.com/Bankrate/QuinnStreet — base URL to append creator slug to
loanPurposeString?For QuinnStreet/Bankrate — loan purpose parameter
configJsonJSON?For impact: { campaignId, adId }. For partnerstack: { partnershipKey, dest, destinationGateKey }
createdAtDateTime
updatedAtDateTime

→ See Offers & Providers → Data Sources, Admin Panel → Providers tab.


OfferAllowlist

Restricts offer visibility to specific creators. If any rows exist for an offer, only listed creators can see it.

FieldTypeNotes
idStringPrimary key
offerIdStringFK → Offer.id
userIdStringFK → User.id — the creator being granted access
createdAtDateTime

→ See Offers & Providers → Offer Allowlist, Admin Panel → Details tab.


OfferApproval

Tracks a creator's access request to an offer that requires approval.

FieldTypeNotes
idStringPrimary key
userIdStringFK → User.id
offerIdStringFK → Offer.id
offerNameStringSnapshot of offer name at request time
creatorPlatformIdsTEXT[]Array of CreatorPlatform IDs the creator selected when requesting
notesString?Creator-provided notes with the request
statusString"pending", "approved", "denied"
denialReasonString?Admin-provided reason when denied
requestedAtDateTimeWhen the creator submitted the request
reviewedAtDateTime?When an admin approved or denied it

→ See Offers & Providers → Approval Types, Admin Panel → Approvals, Creator Experience → Offers Page.


CreatorWeights

Per-creator traffic split overrides for an offer. When present, these override OfferProvider.defaultWeight for that specific creator.

FieldTypeNotes
idStringPrimary key
userIdStringFK → User.id
offerIdStringFK → Offer.id
weightsJsonJSONArray of { providerId: string, weight: number }. Weights must sum to 100.
createdAtDateTime

→ See Offers & Providers → Per-creator overrides, Admin Panel → Split tab.


Affiliate links created by (or for) creators, and the resolved destination URLs per provider.

One row per creator+offer+channel combination. The slug is what appears in secure.moneymatchup.com/{slug}.

FieldTypeNotes
idStringPrimary key
userIdStringFK → User.id
offerIdStringFK → Offer.id
slugStringThe URL slug (e.g. caleb-sofi-youtube). Used for routing and analytics matching.
slugStatusString"active", "pending", etc.
platformStringPlatform the link is for (e.g. "youtube", "tiktok")
channelIdString?FK → CreatorChannel.id
labelString?Optional display label
createdAtDateTime
updatedAtDateTime

→ See Creator Experience → Link Generation, Admin Panel → Links, Analytics.


The actual resolved affiliate URL for a specific link+provider combination. Created when a link is generated (for auto-generate providers) or when a manual offer is approved.

FieldTypeNotes
idStringPrimary key
affiliateLinkIdStringFK → AffiliateLink.id
providerIdStringFK → OfferProvider.id
dataSourceStringMirrors the provider's data source type
linkString?The actual destination URL. Null for dynamic providers (Impact, PartnerStack) that resolve at click time. For manual offers, this is the admin-pasted URL.
createdAtDateTime

→ Created at link generation time for most data sources. For manual offers, created when an admin approves the request. Deleting an OfferProvider cascades to delete its GeneratedLink rows.


Analytics

affiliate_analytics

One row per affiliate link + provider + date. Written by the daily analytics cron job.

FieldColumnTypeNotes
ididStringPrimary key
userIduserIdStringFK → User.id — denormalized for fast creator-scoped queries
affiliateLinkIdaffiliateLinkIdStringFK → AffiliateLink.id
providerIdproviderIdStringFK → OfferProvider.id
datedateDateThe calendar date this row covers
clicksclicksIntClick count for this link+provider+date
conversionsconversionsIntConversion count
earningsearningsDecimalGross commission amount. Creators see earnings × 0.8 (agency keeps 20%).
createdAtcreatedAtDateTime
updatedAtupdatedAtDateTime

→ See Analytics & Reporting, Admin Panel → Crons.


Support Tables

SupportTicket

Creator-submitted support requests.

FieldTypeNotes
idStringPrimary key
userIdStringFK → User.id
messageStringThe creator's support message
categoryString?Ticket category (e.g. "links", "payouts", "account")
statusString"open", "resolved", etc.
notesString?Internal admin notes
resolvedAtDateTime?When the ticket was marked resolved
createdAtDateTime
updatedAtDateTime

→ See Admin Panel → Support, Creator Experience → Support.


SupportReply

Admin replies to support tickets.

FieldTypeNotes
idStringPrimary key
ticketIdStringFK → SupportTicket.id
bodyStringThe reply text
createdAtDateTime

→ Created when an admin replies from the Admin → Support panel. Replies are shown to the creator in their Support page.


Misc Tables

SponsoredVideo

Videos submitted to the platform that contain sponsored content. Used by the VidIQ integration and the sponsored video tracking system.

FieldTypeNotes
idStringPrimary key
socialMediaIdString?Platform-native video ID
userIdStringFK → User.id
platformString"youtube", "youtube_shorts", "tiktok", etc. Auto-set to "youtube_shorts" if duration ≤ 60s
platformOptionString?Sub-type (e.g. long-form vs shorts)
videoIdString?YouTube video ID
linkString?URL to the video
titleString?Video title
descriptionString?Video description
thumbnailString?Thumbnail URL
viewsInt?View count
likesInt?Like count
sharesInt?Share count
commentsInt?Comment count
durationInt?Video duration in seconds. Fetched via VidIQ API.
sourceString?How this record was created
affiliateLinkIdsTEXT[]Array of AffiliateLink IDs featured in the video
offerIdsTEXT[]Array of Offer IDs featured in the video
channelIdsTEXT[]Array of channel IDs
storyLinksTEXT[]Story-related links
createdAtDateTime
updatedAtDateTime

→ See Integrations → VidIQ.


AppSession

Key-value store for long-lived application credentials and session tokens that need to persist across deploys and serverless cold starts.

FieldTypeNotes
keyStringPrimary key. Currently one active key: "partnerstack_cookie"
valueStringThe stored value (e.g. the _dwrf JWT from PartnerStack)
updatedAtDateTimeLast time this value was written

Active keys:

KeyValueRefreshed by
partnerstack_cookiePartnerStack _dwrf session JWTWeekly cron (every Monday 9am UTC)

→ See Integrations → PartnerStack, Admin Panel → PartnerStack Auth Cron.