Resend Confirmation Email
Generate a fresh confirmation token and re-dispatch the email via the active email provider. Always returns the same safe message — no enumeration leak.
POST /api/v1/creators/subscribe/resend — 🌐 Public · Rate limit: 3 req / hour
If an unconfirmed subscription exists for the submitted email, generates a new confirmToken and re-sends the confirmation email through the active email provider (admin-managed via external.email.active_provider). Always returns the same safe message — successfully or not — so the endpoint can't be abused for email enumeration.
No enumeration possible. Whether the email is registered, confirmed, or unknown, the response is identical. Don't try to disambiguate states client-side.
Request
Body — ResendConfirmationDto
| Field | Type | Required | Validation | Notes |
|---|---|---|---|---|
email | string | ✓ | IsEmail() | The email to resend to. Server lowercases + trims. |
No headers required.
Response
200 OK — ApiResponseOf<MessageResponseDto>
{
"success": true,
"data": {
"message": "If an unconfirmed subscription exists, a confirmation email has been sent."
}
}| Field | Type | Notes |
|---|---|---|
message | string | Always the same safe phrase, regardless of whether anything was sent. |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
400 | (DTO validation) | Email format failure |
429 | (throttle) | Rate limit exceeded (3 req/hour) |
Side effects
- Normalize email:
.toLowerCase().trim(). - Lookup
BioEmailSubscriberwhereemail = normalizedEmail AND confirmed = false. - If absent — return the safe message. No mutations, no email sent.
- If found:
- Generate
newToken = randomUUID(). bioEmailSubscriber.update({ where: { id }, data: { confirmToken: newToken } }).- Build confirm URL with the new token (
<seo.canonical_base_url>/subscribe/confirm?token=<newToken>). - Fire-and-forget dispatch via
notificationService.send({ eventKey: 'email_subscription_confirm', userId: 'system', variables: { confirmUrl, email } }). Failure is logged. - Return the safe message.
- Generate
Code samples
curl -X POST https://api.bio.re/api/v1/creators/subscribe/resend \
-H 'Content-Type: application/json' \
-d '{"email": "[email protected]"}'async function resendSubscriptionConfirmation(email: string): Promise<string> {
const res = await fetch('https://api.bio.re/api/v1/creators/subscribe/resend', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Resend failed'), {
code: json?.error?.code,
});
}
return json.data.message as string;
}import { useMutation } from '@tanstack/react-query';
export function useResendSubscriptionConfirmation() {
return useMutation({
mutationFn: async (email: string) => {
const res = await fetch('/api/v1/creators/subscribe/resend', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Resend failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data.message as string;
},
});
}Try it
Authorization
bearer In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
curl -X POST "https://loading/api/v1/creators/subscribe/resend" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"success": true,
"data": {
"message": "Operation completed successfully"
}
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/creator/creator.controller.ts | 319–327 (resendSubscriptionConfirmation) |
| DTO (request) | apps/api-core/src/modules/creator/dto/resend-confirmation.dto.ts | 4–8 (ResendConfirmationDto) |
| DTO (response) | apps/api-core/src/common/dto/common-response.dto.ts | MessageResponseDto |
| Service | apps/api-core/src/modules/creator/creator.service.ts | 679–712 (resendSubscriptionConfirmation) |
| Email provider | (admin-managed) | external.email.active_provider |
| Config | apps/api-core/src/modules/config/config.service.ts | seo.canonical_base_url (admin-managed) |
| Prisma model | packages/prisma/prisma/schema.prisma | BioEmailSubscriber.confirmToken, BioEmailSubscriber.confirmed |
Confirm Subscription
Public token endpoint. The fan clicks the link in the confirmation email; this flips confirmed=true and clears the token. Single-use.
Unsubscribe
Public soft-delete endpoint. Sets unsubscribedAt = now() — the row stays for audit but is excluded from active subscriber lists and future newsletter dispatches.