# Resend Invite Codes — Design **Date**: 2026-02-12 ## Summary Add a "Resend" capability to both invite systems (platform invite codes and account invites). Resending revokes the old code and generates a fresh one, then emails it to the recipient. ## Backend ### Platform Invite Codes **New endpoint**: `POST /api/v1/invites/{code}/resend` (admin-only) 1. Look up existing invite by code 2. Reject if already used (409 Conflict) 3. Delete the old invite 4. Create a new invite with the same properties (email, plan, trial_days, note, expiration recalculated from now) 5. Send email via `EmailService.send_invite_email()` 6. Log audit event 7. Return the new invite ### Account Invites **New endpoint**: `POST /api/v1/accounts/me/invites/{invite_id}/resend` (owner-only) 1. Look up existing invite by ID 2. Reject if already used (409 Conflict) 3. Delete the old invite 4. Create a new invite with the same email, role, and fresh expiration 5. Send email via new `EmailService.send_account_invite_email()` 6. Log audit event 7. Return the new invite ### New Email Method: `send_account_invite_email()` Added to `EmailService` in `backend/app/core/email.py`. - **Parameters**: `to_email`, `code`, `account_name`, `role`, `signup_url` - **Subject**: "You've been invited to join [Account Name] on ResolutionFlow" - **Body**: Same dark monochrome HTML template as platform invites, with: - "You've been invited to join **[Account Name]** as an **Engineer/Viewer**" - Prominent invite code display (same style) - No plan/trial section - "Create Your Account" CTA button - **Returns** `bool` — best-effort, never raises ## Frontend ### Platform Invite Codes (`InviteCodesPage.tsx`) - Resend button in actions column (next to copy/delete) - Only visible for unused, non-expired codes with an email address - Calls `POST /api/v1/invites/{code}/resend` - Shows success toast with new code, refreshes list - Loading state on button during API call ### Account Invites (`AccountSettingsPage.tsx`) - Resend button next to each pending invite - Only visible for unused, non-expired invites - Calls `POST /api/v1/accounts/me/invites/{invite_id}/resend` - Shows success toast, refreshes list - Loading state on button during API call ## Files to Modify - `backend/app/core/email.py` — add `send_account_invite_email()` + HTML template - `backend/app/api/endpoints/invite.py` — add resend endpoint for platform codes - `backend/app/api/endpoints/accounts.py` — add resend endpoint for account invites - `frontend/src/pages/admin/InviteCodesPage.tsx` — add resend button - `frontend/src/pages/AccountSettingsPage.tsx` — add resend button - `frontend/src/api/admin.ts` — add resend API call - `frontend/src/api/accounts.ts` — add resend API call