BIO.RE
Creator

Update Bank Details

Sparse update of bank fields (IBAN/SWIFT/holder/country/name) plus optional preferred-method choice. ANY bank field change resets the verified flag — admin must re-verify before BANK_TRANSFER becomes available again.

PATCH /api/v1/creators/bank-details — 🔑 Bearer · Rate limit: 10 req / hour

Sparse update of the creator's bank-transfer details. Validates IBAN format (^[A-Z]{2}[0-9]{2}[A-Z0-9]{4,30}$), SWIFT/BIC format (^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$), and ISO 3166-1 alpha-2 country code. Any change to a bank field (iban / bankName / accountHolderName / swiftCode / bankCountry) resets bankAccountVerified to false — the bank record must be re-verified by admin before BANK_TRANSFER becomes a usable payout method again.

Verification reset semantics. Submitting preferredPayoutMethod alone (no bank field changes) does not reset bankAccountVerified. Only changes to the five bank fields above flip verification off. Plan UX accordingly: a "switch preferred method" button is safe; a "edit bank details" button warns of pending re-verification.

The endpoint accepts updates even when verification is currently in flight or already passed. There is no idempotency / conflict gate — the rule is simply "any write resets verification". If you want to gate the UI on verification state, read it from GET /creators/payout-settings first.

Request

Body — UpdateBankDetailsDto

All fields optional. Send only what you want to change.

FieldTypeValidationNotes
ibanstringMaxLength(34), regex ^[A-Z]{2}[0-9]{2}[A-Z0-9]{4,30}$Bank account
bankNamestringMaxLength(100)Display name
accountHolderNamestringMaxLength(200)Legal account holder
swiftCodestringMaxLength(11), regex ^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$SWIFT/BIC
bankCountrystringMaxLength(2), regex ^[A-Z]{2}$ISO 3166-1 alpha-2
preferredPayoutMethodenum (PayoutMethod)IsEnum(PayoutMethod)One of: STRIPE_CONNECT / BANK_TRANSFER. Setting this does not reset verification.
HeaderRequiredNotes
Authorization: Bearer <accessToken>JWT from POST /auth/login

Response

200 OKSuccessOnlyResponseDto

{
  "success": true
}
FieldTypeNotes
successbooleanAlways true on 200. Re-fetch via GET /creators/payout-settings to read the post-write state (including the reset verified: false flag if applicable).

Errors

HTTPcode / i18nKeyReason
400(DTO validation)IBAN / SWIFT / country regex fail; field length over cap; invalid preferredPayoutMethod enum
401(guard)Missing / invalid bearer token
404creator.payout.not_foundNo CreatorProfile for this user
429(throttle)Rate limit exceeded (10 req/hour)

Side effects

  1. Lookup CreatorProfile.id by userId; throw not_found if missing.
  2. Build sparse data object from defined keys (the 5 bank fields + preferredPayoutMethod).
  3. Verification reset gate — compute bankFieldChanged = (iban|bankName|accountHolderName|swiftCode|bankCountry) supplied. If true:
    • data.bankAccountVerified = false.
    • data.bankVerifiedAt = null.
  4. prisma.creatorProfile.update({ where: { id }, data }).
  5. Audit log: [payout] Bank details updated for creator {id} (verified reset: <bool>).

Code samples

curl -X PATCH https://api.bio.re/api/v1/creators/bank-details \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "iban": "TR000000000000000000000000",
    "bankName": "Example Bank",
    "accountHolderName": "John Doe",
    "swiftCode": "EXAMPTRIS",
    "bankCountry": "TR"
  }'
type UpdateBankDetailsInput = {
  iban?: string;
  bankName?: string;
  accountHolderName?: string;
  swiftCode?: string;
  bankCountry?: string;
  preferredPayoutMethod?: 'STRIPE_CONNECT' | 'BANK_TRANSFER';
};

async function updateBankDetails(accessToken: string, input: UpdateBankDetailsInput): Promise<void> {
  const res = await fetch('https://api.bio.re/api/v1/creators/bank-details', {
    method: 'PATCH',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(input),
  });
  const json = await res.json();
  if (!res.ok || !json.success) {
    throw Object.assign(new Error(json?.error?.message ?? 'Update bank details failed'), {
      code: json?.error?.code,
    });
  }
}
import { useMutation, useQueryClient } from '@tanstack/react-query';

export function useUpdateBankDetails() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (input: UpdateBankDetailsInput) => {
      const res = await fetch('/api/v1/creators/bank-details', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(input),
      });
      const json = await res.json();
      if (!res.ok || !json.success) {
        throw Object.assign(new Error(json?.error?.message ?? 'Update bank details failed'), {
          code: json?.error?.code,
          i18nKey: json?.error?.i18nKey,
        });
      }
    },
    onSuccess: () => {
      // verified flag may have flipped to false — refresh the consolidated read
      qc.invalidateQueries({ queryKey: ['creators', 'payout-settings'] });
      qc.invalidateQueries({ queryKey: ['creators', 'profile'] });
    },
  });
}

Try it

PATCH
/api/v1/creators/bank-details
AuthorizationBearer <token>

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

curl -X PATCH "https://loading/api/v1/creators/bank-details" \  -H "Content-Type: application/json" \  -d '{}'
{
  "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"
  }
}
{
  "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.ts264–274 (updateBankDetails)
DTO (request)apps/api-core/src/modules/creator/dto/creator.dto.ts136–160 (UpdateBankDetailsDto)
DTO (response)apps/api-core/src/common/dto/common-response.dto.tsSuccessOnlyResponseDto
Serviceapps/api-core/src/modules/creator/creator.service.ts904–930 (updateBankDetails)
Prisma modelspackages/prisma/prisma/schema.prismaCreatorProfile bank fields, enum PayoutMethod

On this page