BIO.RE
Creator

Get Public Bio Page (Fan-side)

SSR-friendly public bio page render by username. CDN + in-memory cache, status filter (suspended/banned/deactivated → 404), only published creators with active scheduled links.

GET /api/v1/bio/:username — 🌐 Public · Rate limit: 120 req / minute

The canonical fan-side bio page render — by username, no auth. Returns the visible payload only: profile basics, the published BioPage with scheduling-filtered active links, the active client theme preset, public DM packages, verified social accounts, and (when enabled) the "Powered by BIO.RE" referral badge. Cached in-memory and at the CDN edge (s-maxage=60, stale-while-revalidate=300).

Status filter — these all return 404, not 403:

  • User not ACTIVE (SUSPENDED / BANNED / DELETED / DEACTIVATED)
  • Creator not ACTIVE (creator-side SUSPENDED / BANNED / DEACTIVATED)
  • BioPage.published === false

The 404 is intentional — refusing to confirm an account exists when it shouldn't be visible. Don't try to disambiguate "doesn't exist" vs "hidden" client-side.

Link filter is server-side: only active = true links with scheduledStart <= now <= scheduledEnd (or null bounds) are returned. The creator-side editor (GET /creators/:creatorId/bio) returns ALL links so the editor can show inactive / future ones.

Request

Path parameters

ParamTypeNotes
usernamestringLowercased server-side; case-insensitive lookup

No body, no headers required.

Response headers

HeaderValue
Cache-Controlpublic, s-maxage=60, stale-while-revalidate=300

Response

200 OKApiResponseOf<PublicBioPageResponseDto>

{
  "success": true,
  "data": {
    "userId": "u1a2b3c4-d5e6-7890-abcd-ef1234567890",
    "username": "johndoe",
    "displayName": "John Doe",
    "bio": "Designer & creator",
    "avatarUrl": "https://cdn.bio.re/avatars/abc.webp",
    "level": "BRONZE",
    "dmType": "SINGLE_PAY",
    "dmPrice": "5.00",
    "dmActive": true,
    "vacationMode": false,
    "avgRating": "4.5",
    "ratingCount": 42,
    "userStatus": "ACTIVE",
    "bioPage": {
      "id": "b1a2b3c4-d5e6-7890-abcd-ef1234567890",
      "bio": "Designer & creator",
      "templateId": "t1a2b3c4-d5e6-7890-abcd-ef1234567890",
      "themeOverride": null,
      "customCss": null,
      "embedEnabled": false,
      "published": true,
      "emailCollectionEnabled": true,
      "links": [
        { "id": "l1...", "title": "My Site", "url": "https://example.com", "icon": "globe", "isSocial": false, "platform": null, "embedType": null, "embedMeta": null }
      ],
      "template": { "name": "Minimal Dark", "tokens": { /* design tokens */ } }
    },
    "socialAccounts": [
      { "platform": "INSTAGRAM", "platformUsername": "johndoe" }
    ],
    "dmPackages": [
      { "id": "d1...", "dmType": "SINGLE_PAY", "price": "5.00" }
    ],
    "themePreset": {
      "slug": "midnight",
      "name": "Midnight",
      "lightTokens": {},
      "darkTokens": {},
      "typography": {},
      "layout": {}
    },
    "referralBadge": {
      "enabled": true,
      "referralCode": "ABC123",
      "url": "https://bio.re/r/ABC123"
    }
  }
}

Top-level fields

FieldTypeNotes
userIdstring (UUID)The creator's user id
usernamestringLowercased echo of the path param
displayName / bio / avatarUrlstring | nullProfile basics from User
levelenumBRONZE / SILVER / GOLD / PLATINUM
dmType / dmPriceenum | null / string | nullDM pricing snapshot
dmActivebooleanComputedcreatorProfile.dmActive && !vacationMode (vacation forces DMs off in the public view even if creator left them on)
vacationModebooleanCreatorProfile.vacationMode
avgRating / ratingCountstring | null / numberAggregate rating
userStatusenumAlways ACTIVE here — non-active users 404
bioPageobject | nullThe published page (links scheduling-filtered server-side)
socialAccountsarrayVerified social accounts (verified = true), max 50, sorted by oldest connection
dmPackagesarrayActive DMPackage rows for this creator (max 10)
themePresetobject | nullCurrently-active CLIENT theme preset (status PUBLISHED, isActive: true) — admin-managed
referralBadgeobject | undefinedPresent only when the referral service successfully resolved a link — failures fall back to undefined (the badge is hidden gracefully)

Errors

HTTPcode / i18nKeyReason
404creator.bio.not_foundUser unknown / not ACTIVE / creator status blocked / BioPage.published === false
429(throttle)Rate limit exceeded (120 req/min)

Side effects

  1. In-memory cache hit path — if the bio page for this username is in the in-memory cache and not expired, return the cached payload directly (LRU touch on access). TTL = analytics.bio_cache_ttl_minutes (admin-managed, default 5).
  2. Cache missprisma.user.findUnique({ where: { username: lowercased } }) selecting (id, displayName, bio, avatarUrl, status). If missing OR status !== ACTIVE → return null → 404.
  3. Read CreatorProfile joined with BioPage (with scheduling-filtered links + template).
  4. Status filter — if creator.creatorStatus IN (SUSPENDED, BANNED, DEACTIVATED) → 404.
  5. Published filter — if bioPage.published !== true → 404.
  6. In parallel: read verified SocialAccount rows, the active CLIENT ThemePreset, active DMPackage rows, and the referral link (failure-safe — bad referral lookups don't break the page).
  7. Compute dmActive = creator.dmActive && !vacationMode.
  8. Cache the assembled payload (LRU eviction at 10,000 entries) and return it.

Code samples

curl https://api.bio.re/api/v1/bio/johndoe
async function getPublicBioPage(username: string): Promise<unknown> {
  const res = await fetch(`https://api.bio.re/api/v1/bio/${encodeURIComponent(username)}`);
  if (res.status === 404) return null; // Treat hidden / unknown identically per security note
  const json = await res.json();
  if (!res.ok || !json.success) {
    throw Object.assign(new Error(json?.error?.message ?? 'Bio page fetch failed'), {
      code: json?.error?.code,
    });
  }
  return json.data; // PublicBioPageResponseDto
}
import { useQuery } from '@tanstack/react-query';

export const bioKeys = {
  public: (username: string) => ['bio', 'public', username.toLowerCase()] as const,
};

export function usePublicBioPage(username: string) {
  return useQuery({
    queryKey: bioKeys.public(username),
    queryFn: async () => {
      const res = await fetch(`/api/v1/bio/${encodeURIComponent(username)}`);
      if (res.status === 404) return null;
      const json = await res.json();
      if (!res.ok || !json.success) {
        throw Object.assign(new Error(json?.error?.message ?? 'Bio page fetch failed'), {
          code: json?.error?.code,
          i18nKey: json?.error?.i18nKey,
        });
      }
      return json.data;
    },
    enabled: Boolean(username),
    // Match the CDN cache window
    staleTime: 60_000,
  });
}

Try it

GET
/api/v1/bio/{username}

Path Parameters

username*string

Response Body

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/bio/string"
{
  "success": true,
  "data": {
    "userId": "2c4a230c-5085-4924-a3e1-25fb4fc5965b",
    "username": "johndoe",
    "displayName": "John Doe",
    "bio": "string",
    "avatarUrl": "https://cdn.bio.re/avatars/abc.jpg",
    "level": "BRONZE",
    "dmType": "FREE",
    "dmPrice": "5.00",
    "dmActive": true,
    "vacationMode": false,
    "avgRating": "4.5",
    "ratingCount": 42,
    "userStatus": "ACTIVE",
    "bioPage": {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "bio": "string",
      "templateId": "196100ac-4eec-4fb6-a7f7-86c8b584771d",
      "themeOverride": {},
      "customCss": "string",
      "embedEnabled": false,
      "published": true,
      "emailCollectionEnabled": false,
      "links": [
        {
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "title": "My Website",
          "url": "https://example.com",
          "icon": "string",
          "isSocial": false,
          "platform": "YOUTUBE",
          "embedType": "VIDEO",
          "embedMeta": {}
        }
      ],
      "template": {
        "name": "Minimal Dark",
        "tokens": {}
      }
    },
    "socialAccounts": [
      {
        "platform": "INSTAGRAM",
        "platformUsername": "johndoe"
      }
    ],
    "dmPackages": [
      {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "dmType": "FREE",
        "price": "5.00"
      }
    ],
    "themePreset": {
      "slug": "midnight",
      "name": "Midnight",
      "lightTokens": {},
      "darkTokens": {},
      "typography": {},
      "layout": {}
    },
    "referralBadge": {
      "enabled": true,
      "referralCode": "ABC123",
      "url": "https://bio.re/r/ABC123"
    }
  }
}
{
  "success": false,
  "error": {
    "code": "AUTH_UNAUTHORIZED",
    "message": "Invalid credentials",
    "i18nKey": "auth.login.invalid_credentials",
    "i18nVars": {
      "field": "email"
    },
    "details": [
      {
        "message": "email must be an email"
      }
    ],
    "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}
{
  "success": false,
  "error": {
    "code": "AUTH_UNAUTHORIZED",
    "message": "Invalid credentials",
    "i18nKey": "auth.login.invalid_credentials",
    "i18nVars": {
      "field": "email"
    },
    "details": [
      {
        "message": "email must be an email"
      }
    ],
    "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Source

SourcePathLines
Controllerapps/api-core/src/modules/creator/bio-analytics.controller.ts57–70 (getPublicBioPage)
DTO (response)apps/api-core/src/modules/creator/dto/bio-analytics-response.dto.ts152–202 (PublicBioPageResponseDto), nested DTOs 30–144
Serviceapps/api-core/src/modules/creator/bio-analytics.service.ts52–158 (getCachedBioPage), 163–167 (invalidateCache)
Cache configapps/api-core/src/modules/config/config.service.tsanalytics.bio_cache_ttl_minutes (admin-managed)
Prisma modelspackages/prisma/prisma/schema.prismaUser, CreatorProfile, BioPage, BioLink (scheduling), BioTemplate, SocialAccount, DMPackage, ThemePreset (CLIENT, PUBLISHED, isActive)

On this page