BIO.RE
Creator

Reorder Bio Links

Atomic reordering of bio page links. Submit the full ordered array; sortOrder is set to the array index. Server verifies every linkId belongs to the creator before writing.

POST /api/v1/creators/:creatorId/links/reorder — 🔑 Bearer · Rate limit: 30 req / hour

Atomic reorder. Submit the full ordered list of linkIds; the server sets sortOrder = index for each, all inside a single Prisma transaction. The server verifies every submitted id belongs to the creator's bio page before writing — partial / cross-creator id sets are rejected wholesale.

Submit the full list — not a delta. If you omit a link's id from the array, its sortOrder is not changed. There is no implicit "leave others alone" — your client must always send the complete current ordering as you'd like it persisted.

Cross-creator id rejection. The service runs findMany({ where: { bioPageId, id: { in: linkIds } } }) and compares lengths — any id that doesn't belong to this creator's bio page causes the whole call to fail with 400 not_owned. No partial writes leak.

Request

Path parameters

ParamTypeValidationNotes
creatorIdstring (UUID)ParseUUIDPipeMust match the bearer's CreatorProfile.id (otherwise 403)

Body — ReorderLinksDto

FieldTypeRequiredValidationNotes
linkIdsstring[]IsArray(), ArrayUnique()The full ordered set of link ids. Position in the array becomes sortOrder.
HeaderRequiredNotes
Authorization: Bearer <accessToken>JWT from POST /auth/login

Response

200 OKSuccessOnlyResponseDto

{
  "success": true
}
FieldTypeNotes
successbooleanAlways true on 200. Re-fetch via GET /creators/:creatorId/bio to read the post-write order.

Errors

HTTPcode / i18nKeyReason
400(DTO validation)linkIds not unique / not an array
400creator.links.not_ownedAt least one submitted linkId doesn't belong to this creator's bio page
401(guard)Missing / invalid bearer token
403(verifyCreatorOwnership)creatorId does not belong to the bearer's user
404creator.bio.not_foundBioPage row missing for this creator
429(throttle)Rate limit exceeded (30 req/hour)

Side effects

  1. Ownership checkverifyCreatorOwnership(creatorId, userId) → 403 on mismatch.
  2. Lookup BioPage by creatorId; throw not_found if missing.
  3. Cross-creator id verificationbioLink.findMany({ where: { bioPageId, id: { in: linkIds } } }) (max 100). If result.length !== linkIds.length → throw not_owned. No writes occur.
  4. Atomic write — build N bioLink.update({ where: { id }, data: { sortOrder: index } }) operations and run them inside a single prisma.$transaction(updates) so all positions land or none do.
  5. Cache invalidationinvalidateBioCache(creatorId).

Code samples

curl -X POST https://api.bio.re/api/v1/creators/c1a2b3c4-d5e6-7890-abcd-ef1234567890/links/reorder \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "linkIds": [
      "l3a2b3c4-d5e6-7890-abcd-ef1234567890",
      "l1a2b3c4-d5e6-7890-abcd-ef1234567890",
      "l2a2b3c4-d5e6-7890-abcd-ef1234567890"
    ]
  }'
async function reorderBioLinks(accessToken: string, creatorId: string, linkIds: string[]): Promise<void> {
  const res = await fetch(`https://api.bio.re/api/v1/creators/${creatorId}/links/reorder`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ linkIds }),
  });
  const json = await res.json();
  if (!res.ok || !json.success) {
    throw Object.assign(new Error(json?.error?.message ?? 'Reorder failed'), {
      code: json?.error?.code,
    });
  }
}
import { useMutation, useQueryClient } from '@tanstack/react-query';

export function useReorderBioLinks(creatorId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (linkIds: string[]) => {
      const res = await fetch(`/api/v1/creators/${creatorId}/links/reorder`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ linkIds }),
      });
      const json = await res.json();
      if (!res.ok || !json.success) {
        throw Object.assign(new Error(json?.error?.message ?? 'Reorder failed'), {
          code: json?.error?.code,
          i18nKey: json?.error?.i18nKey,
        });
      }
    },
    // Optimistic UI: locally re-sort, then call mutation; on error revert
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['creators', creatorId, 'bio'] });
    },
  });
}

Try it

POST
/api/v1/creators/{creatorId}/links/reorder
AuthorizationBearer <token>

In: header

Path Parameters

creatorId*string

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://loading/api/v1/creators/string/links/reorder" \  -H "Content-Type: application/json" \  -d '{    "linkIds": [      "link_1",      "link_2",      "link_3"    ]  }'
{
  "success": true
}
{
  "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"
  }
}
{
  "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

SourcePathLines
Controllerapps/api-core/src/modules/creator/creator.controller.ts189–200 (reorderLinks)
DTO (request)apps/api-core/src/modules/creator/dto/creator-social.dto.ts35–38 (ReorderLinksDto)
DTO (response)apps/api-core/src/common/dto/common-response.dto.tsSuccessOnlyResponseDto
Serviceapps/api-core/src/modules/creator/creator.service.ts464–483 (reorderLinks)
Prisma modelspackages/prisma/prisma/schema.prismaBioPage, BioLink.sortOrder

On this page