Get Creator Profile
Read the calling creator's full profile — level, KYC, DM pricing, vacation, earnings, Stripe Connect status, bank details, plus the joined BioPage (with links + template), categories, and active DM packages.
GET /api/v1/creators/profile — 🔑 Bearer
Returns the rich CreatorProfile row for the user resolved from the bearer token, joined with their BioPage (including ordered links and template), all CreatorCategory rows, and all active = true DmPackage rows. Heavy read — call once on dashboard load and cache.
This is the canonical creator dashboard payload. For a lighter read of a specific slice (e.g. just the bio page or just payout settings), see GET /creators/:creatorId/bio and GET /creators/payout-settings respectively.
Request
No body, no params.
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <accessToken> | ✓ | JWT from POST /auth/login |
Response
200 OK — ApiResponseOf<CreatorProfileResponseDto>
{
"success": true,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"userId": "f0e1d2c3-b4a5-6789-0123-456789abcdef",
"level": "BRONZE",
"kycStatus": "NOT_STARTED",
"kycProvider": null,
"kycProviderId": null,
"kycCompletedAt": null,
"dmType": "FREE",
"dmPrice": null,
"dmActive": true,
"creatorStatus": "ACTIVE",
"vacationMode": false,
"vacationStart": null,
"vacationEnd": null,
"totalEarnings": "0.00",
"totalMessages": 0,
"totalFollowers": 0,
"avgRating": null,
"ratingCount": 0,
"stripeAccountId": null,
"stripeAccountStatus": "NOT_STARTED",
"stripeChargesEnabled": false,
"stripePayoutsEnabled": false,
"iban": null,
"bankName": null,
"accountHolderName": null,
"swiftCode": null,
"bankCountry": null,
"bankAccountVerified": false,
"bankVerifiedAt": null,
"preferredPayoutMethod": null,
"autoPayoutEnabled": false,
"createdAt": "2026-04-29T20:00:00.000Z",
"updatedAt": "2026-04-29T20:00:00.000Z",
"deletedAt": null,
"bioPage": { /* BioPageResponseDto with .links and .template */ },
"categories": [],
"dmPackages": []
}
}Top-level fields
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | CreatorProfile.id |
userId | string (UUID) | Owning User.id |
level | enum | BRONZE / SILVER / GOLD / PLATINUM |
kycStatus | enum | NOT_STARTED / PENDING / APPROVED / REJECTED / EXPIRED |
kycProvider / kycProviderId / kycCompletedAt | string | null | KYC bookkeeping (vendor identity hidden — admin-managed via external.kyc.active_provider) |
dmType | enum | null | FREE / SINGLE_PAY / PER_MESSAGE |
dmPrice | string (decimal) | null | Decimal as string to preserve precision |
dmActive | boolean | True if creator currently accepts DMs |
creatorStatus | enum | ACTIVE / VACATION / SUSPENDED / BANNED / DEACTIVATED |
vacationMode / vacationStart / vacationEnd | boolean / string | null | Vacation block — see /creators/:creatorId/vacation |
totalEarnings | string (decimal) | Lifetime payouts (decimal as string) |
totalMessages / totalFollowers | number | Counters |
avgRating / ratingCount | string | null / number | Aggregate rating |
stripeAccountId / stripeAccountStatus / stripeChargesEnabled / stripePayoutsEnabled | string | null / enum / boolean / boolean | Stripe Connect snapshot (live status from Stripe API is on /creators/stripe-connect/status) |
iban / bankName / accountHolderName / swiftCode / bankCountry / bankAccountVerified / bankVerifiedAt / preferredPayoutMethod / autoPayoutEnabled | various | Bank transfer details — managed via PATCH /creators/bank-details |
createdAt / updatedAt / deletedAt | timestamp / timestamp / timestamp | null | Lifecycle timestamps |
Joined fields
| Field | Type | Notes |
|---|---|---|
bioPage | BioPageResponseDto | null | Includes links (ordered by sortOrder asc) and template. See Bio Page. |
categories | array | All CreatorCategory rows linked to this creator |
dmPackages | array | Only rows where active = true |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
401 | (guard) | Missing / invalid bearer token |
404 | creator.profile.not_found | No CreatorProfile for this user — call POST /creators/upgrade first |
Side effects
prisma.creatorProfile.findUnique({ where: { userId }, include: { bioPage: { include: { links: orderBy sortOrder asc, template } }, categories: true, dmPackages: where active=true } }).- Throw
not_foundif missing. - Return the row. No mutations.
Code samples
curl https://api.bio.re/api/v1/creators/profile \
-H "Authorization: Bearer $ACCESS_TOKEN"async function getCreatorProfile(accessToken: string): Promise<unknown> {
const res = await fetch('https://api.bio.re/api/v1/creators/profile', {
headers: { Authorization: `Bearer ${accessToken}` },
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Profile fetch failed'), {
code: json?.error?.code,
});
}
return json.data; // CreatorProfileResponseDto — see Response section above for shape
}import { useQuery } from '@tanstack/react-query';
export const creatorKeys = {
profile: () => ['creators', 'profile'] as const,
};
export function useCreatorProfile() {
return useQuery({
queryKey: creatorKeys.profile(),
queryFn: async () => {
const res = await fetch('/api/v1/creators/profile');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Profile fetch failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data;
},
staleTime: 60_000,
});
}Try it
Authorization
bearer In: header
Response Body
application/json
application/json
application/json
curl -X GET "https://loading/api/v1/creators/profile"{
"success": true,
"data": {
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"userId": "2c4a230c-5085-4924-a3e1-25fb4fc5965b",
"level": "BRONZE",
"kycStatus": "NOT_STARTED",
"kycProvider": "string",
"kycProviderId": "string",
"kycCompletedAt": "2019-08-24T14:15:22Z",
"dmType": "FREE",
"dmPrice": "5.00",
"dmActive": true,
"creatorStatus": "ACTIVE",
"vacationMode": true,
"vacationStart": "2019-08-24T14:15:22Z",
"vacationEnd": "2019-08-24T14:15:22Z",
"totalEarnings": "1250.00",
"totalMessages": 47,
"totalFollowers": 100,
"avgRating": "4.50",
"ratingCount": 0,
"stripeAccountId": "string",
"stripeAccountStatus": "NOT_STARTED",
"stripeChargesEnabled": true,
"stripePayoutsEnabled": true,
"iban": "string",
"bankName": "string",
"accountHolderName": "string",
"swiftCode": "string",
"bankCountry": "string",
"bankAccountVerified": true,
"bankVerifiedAt": "2019-08-24T14:15:22Z",
"preferredPayoutMethod": "STRIPE_CONNECT",
"autoPayoutEnabled": true,
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"deletedAt": "2019-08-24T14:15:22Z",
"bioPage": {
"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"
}
},
"categories": [
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "string"
}
],
"dmPackages": [
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"creatorId": "688ebf54-d343-4104-8711-82c2feac534a",
"dmType": "FREE",
"price": "5.00",
"active": true,
"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"
}
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/creator/creator.controller.ts | 52–59 (getProfile) |
| DTO (response) | apps/api-core/src/modules/creator/dto/creator-client-response.dto.ts | 183–297 (CreatorProfileResponseDto), 105–180 (BioPageResponseDto) |
| Service | apps/api-core/src/modules/creator/creator.service.ts | 185–196 (getProfile) |
| Prisma models | packages/prisma/prisma/schema.prisma | CreatorProfile, BioPage, BioLink, BioTemplate, CreatorCategory, DmPackage, enums CreatorLevel/KycStatus/DmType/CreatorStatus/StripeAccountStatus/PayoutMethod |
Upgrade to Creator
Convert an authenticated user into a creator. Atomic — creates CreatorProfile + BioPage + flips User.intent to CREATOR. Gated by an admin kill switch.
Connect Social Account
Verify a creator's ownership of a social account via OAuth callback. Stores the link plus access/refresh tokens for later platform calls. Recomputes totalFollowers.