---
title: "Upload or replace the current user avatar"
method: PUT
path: "/users/me/profile/avatar"
tags: ["user-profile"]
---

# Upload or replace the current user avatar

`PUT /users/me/profile/avatar`

Multipart form with a single field `avatar` (JPEG, PNG, WebP, or GIF, max 2 MB). The avatar is stored in S3 under `users/{userId}/` and uploading again replaces the stored file and updates the profile avatar key.

## Response `200`

User profile updated with new avatar key and read URL

- UserProfileResponseDto
  - `id` number, required — User profile ID
  - `name` string, required — Full name
  - `username` object, nullable, required — Username
  - `type` 1 | 2, required — Profile type
  - `companyName` object, nullable, required — Company name (business profiles)
  - `jobTitle` object, nullable, required — Job title
  - `birthday` object, nullable, required — Birthday
  - `phone` object, nullable, required — Phone number
  - `timezone` object, nullable, required — Timezone
  - `avatar` object, nullable, required — Avatar
  - `userId` number, required — User ID
  - `user` User, required
    - `id` number, required — User ID
    - `privyId` string, required — Privy user ID
    - `email` object, nullable, required — Email address
    - `status` 1 | 2 | 3, required — User status
    - `lastLoginCountry` object, nullable, required — Country of the last login with a known geo (ISO 3166-1 alpha-2)
    - `lastLoginCountryAt` object, nullable, required — When lastLoginCountry was last updated
    - `created_at` string, date-time, required — Creation timestamp
    - `updated_at` string, date-time, required — Last update timestamp
    - `userProfile` UserProfile, required
      - `id` number, required — User profile ID
      - `name` string, required — Full name
      - `username` object, nullable, required — Username
      - `type` 1 | 2, required — Profile type
      - `companyName` object, nullable, required — Company name (business profiles)
      - `jobTitle` object, nullable, required — Job title
      - `birthday` object, nullable, required — Birthday
      - `phone` object, nullable, required — Phone number
      - `timezone` object, nullable, required — Timezone
      - `avatar` object, nullable, required — Avatar
      - `userId` number, required — User ID
      - `user` User, required — recursive
      - `referralCode` ReferralCode, required
        - `id` number, required — Referral code ID
        - `wallet` string, required — Wallet address
        - `code` string, required — Referral code
        - `codeNormalized` string, required — Referral code normalized
        - `createdAt` string, date-time, required — Creation timestamp
      - `onboardingCompleted` boolean, required — Whether the onboarding is completed
      - `currency` object, nullable, required — Display currency, lower-case ISO 4217
      - `inputMode` object, nullable, required — Amount entry mode: fiat or token
      - `language` object, nullable, required — UI language, as a resolved translation-bundle key. NULL means never chosen (DRE-447).
      - `sessionTimeout` object, nullable, required — App-lock idle timeout in minutes; 0 disables it
      - `appLockEnabled` boolean, required — Whether the app lock (PIN) is set up
      - `created_at` string, date-time, required — Creation timestamp
      - `updated_at` string, date-time, required — Last update timestamp
  - `referralCode` ReferralCode, required
    - `id` number, required — Referral code ID
    - `wallet` string, required — Wallet address
    - `code` string, required — Referral code
    - `codeNormalized` string, required — Referral code normalized
    - `createdAt` string, date-time, required — Creation timestamp
  - `onboardingCompleted` boolean, required — Whether the onboarding is completed
  - `currency` object, nullable, required — Display currency, lower-case ISO 4217
  - `inputMode` object, nullable, required — Amount entry mode: fiat or token
  - `language` object, nullable, required — UI language, as a resolved translation-bundle key. NULL means never chosen (DRE-447).
  - `sessionTimeout` object, nullable, required — App-lock idle timeout in minutes; 0 disables it
  - `appLockEnabled` boolean, required — Whether the app lock (PIN) is set up
  - `created_at` string, date-time, required — Creation timestamp
  - `updated_at` string, date-time, required — Last update timestamp
  - `avatarUrl` object, nullable — Presigned read URL for the avatar
  - `betaApproved` boolean, required — Live beta access status for the authenticated wallet (admin or allowlisted).

## Other responses

- `400` — Invalid avatar file
- `401` — Unauthorized
- `403` — Region blocked (`code: REGION_BLOCKED`), beta access not enabled for this wallet (no code — check `status` on `GET /auth/session`), or a missing/invalid CSRF token on a cookie session (`code: CSRF_INVALID` — re-fetch it and retry once)
- `404` — User profile not found

---

[API](https://skmtc.dev/dre/apis/dre-api.md) · [All operations](https://skmtc.dev/dre/apis/dre-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/dre/dre-api/revisions/5d14beb9482b/schema)
