Profiles and verification
Updated Oct 15, 2026 Open the tool
A Zoov.dev profile is the public page for an account plus a small set of server-managed flags: a verification status that can restrict paid tools, device limits that watch for account sharing, and an access tier that comes from Discord roles.
Public profile pages
Public profile pages live at /profile/<username>. /app/profile is your own account page (plan, credits, billing, linked Discord); signed out it sends you to sign in first. If your profile has no username it falls back to the homepage.
The page accepts a username or an account UUID. It shows a Discord member card (avatar, banner, nickname and server roles) when the account is a member of the Zoov.dev Discord server. If the Discord member data cannot be loaded it shows a plain card with the avatar and display name. Since 2026-10-13 a public profile card never shows the email to other people; the email appears only on your own profile, when you are signed in and looking at it. A username that does not exist shows "User not found" and "The profile you are looking for does not exist." The page has "Back to Home" and "Goto Editor" buttons and a "zoov.dev profile viewer" footer.
Profile data comes from /api/v1/discord/profile/<username>. That endpoint also accepts a 17 to 19 digit Discord id and will show a Discord-only card for someone who has never signed in. Results are cached in memory per server instance for up to ten minutes, so a fresh change can take that long to appear.
Only the owner viewing their own profile gets their email and credit balance in the response; other viewers get neither (the balance reads 0 and is not rendered).
The account in the workspace (2026-09-14)
Inside /app, Profile in the menu opens /app/profile: the avatar, the name, the Discord handle and id, the email, the day the account was made, the plan badge, then Plan, Credits, Storage and Team as four facts (Storage says the space used and, since 2026-10-02, both expiry clocks: "Uploads kept 7 days after last use · results 30 days · 0 of 3 pinned" on Free), and Plans, Billing and Sign out. It is the signed-in person's own account, not a public page. Nothing is edited there but one switch, Marketing emails, a row under the four facts since 2026-09-27: off means no campaign email reaches the account, on means it does, and it saves as it is moved (a toast "Marketing emails off" or "Marketing emails on"; "Could not save · try again" when the save failed, and the switch comes back). The name and avatar are Discord's and follow at the next sign-in. The public profile pages stay where they are. What the switch controls is in Email and notifications. Since 2026-10-06 the panel ends with a red Delete account area, the one way to delete an account; what it takes and what stays is in Accounts and sign-in, "Deleting your account".
What you can edit
Profile fields are not edited on Zoov.dev. Username, avatar and email are copied from Discord every time you sign in, so to change them: change them on Discord, sign out of Zoov.dev and sign in again. The username on the profile is your Discord display name at the time of sign-in (verify against your account if it looks stale).
Things you can change on the site: the Marketing emails switch on /app/profile (the old /email-preferences page redirects there since 2026-09-27), and team membership under /app/team. Verification fields cannot be changed by anyone but the server; a database trigger rejects client updates with "Profile verification fields are server-managed."
Verification status
Every profile has a verification_status. Default is verified, which means no restriction. The other three values restrict access to every paid or non-public tool permission (editor save, converter, optimizer, plugin, 3D generation and so on) until cleared. Public features and the verification page itself keep working.
| Status | Message shown | Set by |
|---|---|---|
verified |
none | default, or completing a verification challenge |
unverified |
"Your account is unverified. Please verify your account to use this feature." | opening a verification challenge that requires sign-in |
review_required |
"Your account requires admin review before you can use this feature. Contact admin@zoov.dev to appeal." | the device limit policy (see below) |
blocked |
"Your account is blocked from using this feature. Contact admin@zoov.dev to appeal." | staff (no code path sets it automatically) |
Where the restriction surfaces: tool APIs return the message with HTTP 403 (for example 3D model generation), permission checks such as tier.pro return false, and the plugin sends you to /plugin/no-access with reason account-review and the same message. review_required and blocked cannot be cleared by the user; they need staff. unverified is cleared by completing the challenge.
Blocklist (2026-10-05)
The verification states above hang off the profile row, so a blocked account can simply sign up again and get a fresh, verified profile. The blocklist closes that gap: account_blocklist keys a ban on the Discord id (and optionally the email), so it catches the same person on a new account.
It is checked at the OAuth callback, inside finalizeSignIn, before the Discord auto-join. A hit:
- force-sets the new profile to
verification_status = 'blocked', so every paid or non-public tool returns "Your account is blocked from using this feature. Contact admin@zoov.dev to appeal." — exactly like a staff block; - posts a #watchdog alert ("Blocklisted account signed in") with the reason, the note, the Discord id, the email and whether the account is brand new;
- skips the Discord server auto-join and the normal "just logged in" log line.
The person is left signed in but gated, not bounced to an error: nothing at sign-in reveals they were caught, and the signed-in session still records their device and network for the account-sharing monitor (which is what links sibling accounts). Blocking is never automatic from any signal — rows are added by staff, or seeded in the migration.
Siblings of a blocked account (2026-10-06). Every sign-in writes the browser's device hash and the address hash to referral_devices. A brand-new account whose first sign-in matches a blocked account on either raises a #watchdog alert, never a block: a device match is called strong (same browser), an address-only match weak (CGNAT and shared houses are common — about 4% of addresses in the table are shared by two or more accounts). The alert names the blocked accounts it matched and how. There is nothing to match until a blocked account has signed in at least once since 2026-10-01.
What every security alert carries. The Discord account's age from its snowflake id ("3 days old (made 2026-10-03) · under the 30-day gate"), the sign-in's city, region and country from Vercel's geo headers, and the address. These are enrichment, not triggers: 5.6% of signups have a Discord account under 30 days old (about eight a day), far too many to alert on by themselves.
Completing verification
Verification challenges are opened at /verify/<token>. Challenge links are issued outside the website, normally by the Discord bot when an account is flagged (verify in the bot repo). The page says "Verification Required" and "Complete the security check below to verify your account.", shows a Cloudflare Turnstile widget and a "Verify Identity" button.
Rules while verifying:
- If the challenge requires sign-in you are sent to
/loginfirst, then back. - The challenge must match your account. Otherwise: "This challenge belongs to another user." or "This verification belongs to another Discord account." Since 2026-10-13 the page takes your Discord id from the Discord account you signed in with, never from your profile, and the 30 day age check below uses that same account. If no Discord account is linked to your sign-in: "Please sign in with Discord before completing this verification."
- Your Discord account must be at least 30 days old. Younger accounts see "Verification Paused" with "Your Discord account must be at least 30 days old to verify. If this is a mistake or you need access, contact admin@zoov.dev to appeal."
- Expired links return "Challenge expired"; unknown tokens "Challenge not found"; a used link shows "Verification Complete" and "You have been verified and can close this window."
On success the page shows "Verified Successfully", the Unverified Discord role is removed and the profile goes back to verified. Failures show "CAPTCHA validation failed" or "Invalid, expired, or already completed token".
Device limits and account sharing
Device limits protect paid access from account sharing. Each browser or plugin install gets a device lease of 12 hours; up to 3 devices can hold an active lease at once. A fourth device replaces the oldest lease, so the previous device has to re-open the tool. When replacement is not possible the user sees "This account is active on too many devices. Try again in a moment or contact support." and the plugin shows /plugin/no-access?reason=device-limit.
The paid-access monitor that records these alerts skips requests from inside an editor panel: the legacy plugin routes (/plugin/...), the workspace panel routes (/app/plugin/...) and the plugin API (/api/v1/photoshop/...). A panel that reopens all day is one device, not a new one each time.
Review flag: a new device that brings the account to 8 or more distinct devices in 24 hours across 3 or more distinct networks sets the profile to review_required automatically. Staff receive a Discord "Account Access Alert" at a lower threshold (2 devices on 2 networks) with a 60 minute cooldown per reason. All limits can be changed by environment variables; the numbers here are the defaults.
Access tiers
Access tiers are labels for what an account can use: "Free", "Member", "Lite", "Standard", "Pro" and "Max". "Member" means a signed-in free account ("Open access" on the tools page). Paid tiers come from Discord roles on the Zoov.dev server, synced to your account at most every 15 minutes, or immediately when the bot reports a role change.
Tier order from lowest to highest: booster, lite, standard (a referrer role counts as standard), pro, max. Some gates in code:
tier.lite(Lite and above): the Photoshop and Photopea plugin, with its live 3D preview.tier.standard(Standard, referrer and above): saving and previewing designs, the editor, code tools, optimizer, converter, FiveM deploy.tier.pro(Pro and Max): 2048 vehicle UV export.- Since 2026-09-30 Lite and server boosters count as Free for every limit and price outside the plugin: only Standard and up are paid plans. Until then boosters also held the showcase and vehicle UV permissions (legacy flags nothing in
/appreads).
If a paid role looks missing, the user should confirm they are in the Discord server with the role, then wait up to 15 minutes or sign out and in.
Common questions
How do I change my username or avatar? Change it on Discord, then sign out and back in to Zoov.dev. The site copies it at sign-in.
Why does it say my account is unverified?
A verification challenge was opened for your account. Finish it at the /verify/<token> link you were given, from a Discord account at least 30 days old.
My account "requires admin review". What now? The device limit policy flagged it for possible sharing. Email admin@zoov.dev to appeal; staff clear it manually.
How many devices can I use? 3 at the same time. A new device bumps the oldest one, which then needs to re-open the tool.
I have the Pro role on Discord but the site says I am free. Roles sync every 15 minutes. Check you are still in the Zoov.dev server, wait, then sign out and in.
How do I turn marketing emails off?
On /app/profile, turn off the Marketing emails switch under the plan, credits, storage and team facts; it saves at once. The Unsubscribe link at the foot of any marketing email does the same without signing in.
Can other people see my email on my profile? No. Since 2026-10-13 a public profile card shows the email only to the account's owner, on their own profile. Other visitors never get it.
Languages
Since 2026-09-20 this part of the site is available in English, French, German, Spanish, Portuguese, Polish and Dutch. It follows the browser's language on a first visit, and the language menu (the icon beside the profile in /app, or in the top navigation on public pages) changes it. Nothing about how it works, what it costs or what a plan includes differs by language; only the words do. File names, format names (GLB, YDR, YTD), product and model names, code, and some error lines that come from the server stay in English. Details and known gaps: Languages and translation.