BIO.RE
Creator

Get Bio Page (Editor)

Read the creator's own BioPage row plus its links (ordered) and template. Ownership-checked. Use this for the editor — public fan-side rendering uses GET /bio/:username instead.

GET /api/v1/creators/:creatorId/bio — 🔑 Bearer

Returns the creator-owned view of the BioPage for a creatorId, including all BioLink rows (ordered by sortOrder ASC) and the joined BioTemplate. Ownership is enforced — the bearer's user id must match CreatorProfile.userId; otherwise 403.

Editor path, not render path. This endpoint returns the raw editable record (including customCss, themeOverride, published flag) — render the public view via GET /bio/:username (cached, scope-filtered). Use this only inside the creator dashboard.

Request

Path parameters

ParamTypeValidationNotes
creatorIdstring (UUID)ParseUUIDPipeMust match the bearer's CreatorProfile.id (otherwise 403)
HeaderRequiredNotes
Authorization: Bearer <accessToken>JWT from POST /auth/login

Response

200 OKApiResponseOf<BioPageResponseDto>

{
  "success": true,
  "data": {
    "id": "b1a2b3c4-d5e6-7890-abcd-ef1234567890",
    "creatorId": "c1a2b3c4-d5e6-7890-abcd-ef1234567890",
    "templateId": "t1a2b3c4-d5e6-7890-abcd-ef1234567890",
    "bio": "Designer & creator",
    "themeOverride": null,
    "customCss": null,
    "embedEnabled": false,
    "published": true,
    "emailCollectionEnabled": false,
    "links": [
      {
        "id": "l1a2b3c4-d5e6-7890-abcd-ef1234567890",
        "title": "My Site",
        "url": "https://example.com",
        "icon": "globe",
        "sortOrder": 0,
        "active": true,
        "isSocial": false,
        "platform": null,
        "embedType": null,
        "embedMeta": null,
        "scheduledStart": null,
        "scheduledEnd": null
      }
    ],
    "template": { /* BioTemplate row when templateId is set */ }
  }
}

Top-level fields

FieldTypeNotes
idstring (UUID)BioPage.id
creatorIdstring (UUID)Owning CreatorProfile.id
templateIdstring (UUID) | nullSelected template (null when none)
biostring | nullBody — stored sanitized (HTML tags stripped at write time)
themeOverrideobject | nullFree-form JSON theme override
customCssstring | nullCustom CSS — stored sanitized (expression(...), javascript:, non-https url(...) stripped at write time)
embedEnabledbooleanWhen true, third-party sites may embed via iframe (also gates GET /bio/embed/:username)
publishedbooleanWhen false, public render endpoint returns 404
emailCollectionEnabledbooleanWhen true, POST /creators/:bioPageId/subscribe accepts emails
linksarrayAll BioLink rows (ordered by sortOrder ASC) — includes inactive / scheduled-future links (the public render filters them)
templateobject | nullJoined BioTemplate when templateId is set

Errors

HTTPcode / i18nKeyReason
400(validation)creatorId not a valid UUID
401(guard)Missing / invalid bearer token
403(verifyCreatorOwnership)creatorId does not belong to the bearer's user
404creator.bio.not_foundBioPage row missing for this creator

Side effects

  1. Ownership checkverifyCreatorOwnership(creatorId, userId) reads CreatorProfile.userId and throws 403 on mismatch.
  2. prisma.bioPage.findUnique({ where: { creatorId }, include: { links: { orderBy: { sortOrder: 'asc' } }, template: true } }).
  3. Throw not_found if missing.
  4. Return the row. No mutations.

Code samples

curl https://api.bio.re/api/v1/creators/c1a2b3c4-d5e6-7890-abcd-ef1234567890/bio \
  -H "Authorization: Bearer $ACCESS_TOKEN"
async function getBioPage(accessToken: string, creatorId: string): Promise<unknown> {
  const res = await fetch(`https://api.bio.re/api/v1/creators/${creatorId}/bio`, {
    headers: { Authorization: `Bearer ${accessToken}` },
  });
  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; // BioPageResponseDto with .links and .template
}
import { useQuery } from '@tanstack/react-query';

export const creatorKeys = {
  bioPage: (creatorId: string) => ['creators', creatorId, 'bio'] as const,
};

export function useBioPage(creatorId: string) {
  return useQuery({
    queryKey: creatorKeys.bioPage(creatorId),
    queryFn: async () => {
      const res = await fetch(`/api/v1/creators/${creatorId}/bio`);
      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(creatorId),
    staleTime: 30_000,
  });
}

Try it

GET
/api/v1/creators/{creatorId}/bio
AuthorizationBearer <token>

In: header

Path Parameters

creatorId*string

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/creators/string/bio"
{
  "success": true,
  "data": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "creatorId": "688ebf54-d343-4104-8711-82c2feac534a",
    "templateId": "196100ac-4eec-4fb6-a7f7-86c8b584771d",
    "bio": "string",
    "themeOverride": {},
    "customCss": "string",
    "embedEnabled": true,
    "published": true,
    "emailCollectionEnabled": true,
    "createdAt": "2019-08-24T14:15:22Z",
    "updatedAt": "2019-08-24T14:15:22Z",
    "links": [
      {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "bioPageId": "19ae7b68-8677-4862-a3d1-274c4a95a121",
        "title": "string",
        "url": "string",
        "icon": "string",
        "sortOrder": 0,
        "active": true,
        "isSocial": true,
        "platform": "string",
        "embedType": "string",
        "embedMeta": {},
        "scheduledStart": "2019-08-24T14:15:22Z",
        "scheduledEnd": "2019-08-24T14:15:22Z",
        "clickCount": 0,
        "createdAt": "2019-08-24T14:15:22Z",
        "updatedAt": "2019-08-24T14:15:22Z"
      }
    ],
    "template": {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "description": "string",
      "tokens": {},
      "thumbnail": "string",
      "active": true,
      "sortOrder": 0,
      "createdAt": "2019-08-24T14:15:22Z",
      "updatedAt": "2019-08-24T14:15:22Z"
    }
  }
}
{
  "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"
  }
}
{
  "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/creator.controller.ts125–134 (getBioPage)
DTO (response)apps/api-core/src/modules/creator/dto/creator-client-response.dto.ts105–180 (BioPageResponseDto)
Serviceapps/api-core/src/modules/creator/creator.service.ts297–304 (getBioPage), ownership helper verifyCreatorOwnership
Prisma modelspackages/prisma/prisma/schema.prismaBioPage, BioLink (relation links), BioTemplate (relation template), CreatorProfile.userId (ownership)

On this page