Get Dashboard Login Link
One-shot login URL for the creator's Stripe Express dashboard. Requires the account to be ACTIVE. Use to deep-link into payouts, payment methods, and settings.
POST /api/v1/creators/stripe-connect/dashboard-link — 🔑 Bearer · Rate limit: 10 req / hour
Returns a single-use Stripe Express dashboard login URL for the creator. Use to deep-link from the platform UI into the creator's Stripe dashboard (where they manage payouts, view balances, update payment methods, etc.) without making them log in to Stripe directly.
Active-only. Dashboard links are gated on stripeAccountStatus === 'ACTIVE'. Pending / restricted / disabled accounts can't access the dashboard yet — show the user the onboarding flow instead. Surface "Finish setting up your account" UI when you see creator.stripe.not_active.
Single-use. Stripe login links work for one redirect — fetch a new one every time the user clicks "Manage payouts" rather than caching the URL. The URL becomes invalid after first use or after a short timeout.
Request
No body, no params. Identity comes from the bearer token.
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <accessToken> | ✓ | JWT from POST /auth/login |
Response
200 OK — ApiResponseOf<StripeConnectDashboardLinkResponseDto>
{
"success": true,
"data": {
"url": "https://connect.stripe.com/express/..."
}
}| Field | Type | Notes |
|---|---|---|
url | string | One-shot Stripe Express dashboard login URL. Render into a button click handler that immediately redirects — don't store. |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
400 | creator.stripe.account_not_found | No stripeAccountId on the creator |
400 | creator.stripe.not_active | stripeAccountStatus !== 'ACTIVE' — account hasn't finished onboarding yet |
400 | creator.stripe.service_unavailable | Stripe SDK is not configured |
401 | (guard) | Missing / invalid bearer token |
404 | creator.stripe.not_creator | No CreatorProfile for this user |
429 | (throttle) | Rate limit exceeded (10 req/hour) |
Side effects
- Lookup
CreatorProfile; thrownot_creatorif missing. - Assert
stripeAccountIdis non-null; otherwiseaccount_not_found. - Assert
stripeAccountStatus === ACTIVE; otherwisenot_active. - Call
stripe.accounts.createLoginLink(stripeAccountId). - Return
{ url: loginLink.url }. No DB writes.
Code samples
curl -X POST https://api.bio.re/api/v1/creators/stripe-connect/dashboard-link \
-H "Authorization: Bearer $ACCESS_TOKEN"async function getDashboardLink(accessToken: string): Promise<string> {
const res = await fetch('https://api.bio.re/api/v1/creators/stripe-connect/dashboard-link', {
method: 'POST',
headers: { Authorization: `Bearer ${accessToken}` },
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Dashboard link failed'), {
code: json?.error?.code,
});
}
return json.data.url as string;
}
// Usage: fetch on-demand, redirect immediately
async function openStripeDashboard(accessToken: string) {
const url = await getDashboardLink(accessToken);
window.location.assign(url);
}import { useMutation } from '@tanstack/react-query';
export function useGetDashboardLink() {
// Mutation, not query — single-use URL, never cache
return useMutation({
mutationFn: async () => {
const res = await fetch('/api/v1/creators/stripe-connect/dashboard-link', { method: 'POST' });
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Dashboard link failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data.url as string;
},
});
}Try it
Authorization
bearer In: header
Response Body
application/json
application/json
curl -X POST "https://loading/api/v1/creators/stripe-connect/dashboard-link"{
"success": true,
"data": {
"url": "string"
}
}{
"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/stripe-connect.controller.ts | 44–51 (dashboardLink) |
| DTO (response) | apps/api-core/src/modules/creator/dto/stripe-connect-response.dto.ts | 48–51 (StripeConnectDashboardLinkResponseDto) |
| Service | apps/api-core/src/modules/creator/stripe-connect.service.ts | 183–207 (getDashboardLink) |
| Stripe provider | apps/api-core/src/modules/payment/stripe.provider.ts | requireStripe() |
| Prisma model | packages/prisma/prisma/schema.prisma | CreatorProfile.stripeAccountId, CreatorProfile.stripeAccountStatus (enum StripeAccountStatus.ACTIVE) |
Refresh Onboarding Link
Get a fresh hosted onboarding link for an existing Stripe Connect account. Use when the previous link expired or the user closed the tab without finishing.
Subscribe to Bio Page
Public fan-side email signup for a creator's bio page mailing list. Double-opt-in — confirmation email is sent through the active email provider (admin-managed) with a token.