BIO.RE
User

Check Username Availability

Real-time availability probe for the registration / settings form. Public — no auth required. Returns false on bad format too, so the UI can stop after one round-trip.

GET /api/v1/users/check-username — 🌐 Public · Rate limit: 30 req / minute

Real-time check used by the registration / settings form before submit. Returns { available: true } only when the value normalizes within the configured length bounds, matches the format regex, and is not currently held by an active user or the reserved-name list.

This is the only public endpoint in the user module — needed because the registration form runs before login. The 30/min throttle is per-IP. Pair it with client-side debouncing (~300ms) to keep within budget.

A length / format failure also returns { available: false } — there is no separate "invalid format" code path. If you need to distinguish "taken" from "malformed", validate format client-side before calling. The cooldown rule applies only to PATCH /users/username, not here.

Request

Query parameters

ParamTypeRequiredNotes
usernamestringThe candidate username — server normalizes via .toLowerCase().trim() before evaluation

No body, no headers required.

Response

200 OKApiResponseOf<UsernameAvailabilityDto>

{
  "success": true,
  "data": {
    "available": true
  }
}
FieldTypeNotes
availablebooleantrue only when length + format + uniqueness + not-reserved all pass

Errors

HTTPcode / i18nKeyReason
429(throttle)Rate limit exceeded (30 req/min)

The endpoint never throws on invalid input — available: false is the universal "not usable" signal.

Side effects

  1. Normalize input (.toLowerCase().trim()).
  2. Length check against site.username_min_length / site.username_max_length (admin-managed) → if outside bounds, return { available: false }.
  3. Format check against ^[a-z0-9._-]+$ → if failing, return { available: false }.
  4. prisma.user.findUnique({ where: { username } }) → if hit, return { available: false }.
  5. prisma.reservedUsername.findUnique({ where: { username } }) → if hit, return { available: false }.
  6. Otherwise: return { available: true }. No mutations.

Code samples

curl 'https://api.bio.re/api/v1/users/check-username?username=johndoe'
async function checkUsername(username: string): Promise<boolean> {
  const url = new URL('https://api.bio.re/api/v1/users/check-username');
  url.searchParams.set('username', username);
  const res = await fetch(url);
  const json = await res.json();
  if (!res.ok || !json.success) {
    throw Object.assign(new Error(json?.error?.message ?? 'Check failed'), {
      code: json?.error?.code,
    });
  }
  return json.data.available;
}
import { useQuery } from '@tanstack/react-query';

export const usernameKeys = {
  availability: (username: string) => ['users', 'check-username', username] as const,
};

export function useUsernameAvailability(username: string) {
  // Caller is responsible for debouncing the input upstream.
  return useQuery({
    queryKey: usernameKeys.availability(username),
    queryFn: async () => {
      const url = new URL('/api/v1/users/check-username', window.location.origin);
      url.searchParams.set('username', username);
      const res = await fetch(url);
      const json = await res.json();
      if (!res.ok || !json.success) {
        throw Object.assign(new Error(json?.error?.message ?? 'Check failed'), {
          code: json?.error?.code,
          i18nKey: json?.error?.i18nKey,
        });
      }
      return json.data.available as boolean;
    },
    enabled: username.length >= 3,
    staleTime: 10_000, // 10s — registration form lifetime is short
  });
}

Try it

GET
/api/v1/users/check-username
AuthorizationBearer <token>

In: header

Query Parameters

username*string

Response Body

application/json

curl -X GET "https://loading/api/v1/users/check-username?username=string"
{
  "success": true,
  "data": {
    "available": true
  }
}

Source

SourcePathLines
Controllerapps/api-core/src/modules/user/user.controller.ts114–121 (checkUsername, @Public())
DTO (response)apps/api-core/src/modules/user/dto/user-client-response.dto.ts120–123 (UsernameAvailabilityDto)
Serviceapps/api-core/src/modules/user/user.service.ts246–259 (checkUsernameAvailability)
Prisma modelspackages/prisma/prisma/schema.prismaUser.username, ReservedUsername

On this page