Users API
Common Information
Base URL
/api/v1/usersAuthentication Header
Authorization: Bearer <access_token>Response Envelope
All responses follow the standard format:
// Success response
interface SuccessResponse<T> {
success: true;
data: T;
meta?: {
pagination?: PaginationMeta;
[key: string]: unknown;
};
}
// Error response
interface ErrorResponse {
success: false;
error: {
code: string;
message: string;
details?: Record<string, string[]>;
};
}Pagination Format
interface PaginationMeta {
total: number;
page: number;
pageSize: number;
totalPages: number;
hasNext: boolean;
hasPrevious: boolean;
}Rate Limits
| Endpoint | Limit |
|---|---|
| All user endpoints | 100/min |
| Avatar upload | 10/hour |
| KYC submission | 5/day |
Endpoints
GET /api/v1/users/me
Get the current authenticated user's profile.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
None
Query Parameters
None
Response (200 OK)
interface UserProfileResponse {
id: string;
email: string;
phone: string | null;
status: 'PENDING_VERIFICATION' | 'ACTIVE' | 'SUSPENDED' | 'BANNED';
emailVerifiedAt: string | null;
phoneVerifiedAt: string | null;
lastLoginAt: string | null;
profile: {
firstName: string;
lastName: string;
middleName: string | null;
dateOfBirth: string | null; // YYYY-MM-DD
avatarUrl: string | null;
language: string;
timezone: string;
};
kyc: {
status: string;
level: string;
};
roles: string[];
twoFactorEnabled: boolean;
createdAt: string;
updatedAt: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Invalid or expired access token |
Example
Request:
curl -X GET https://api.iwm-platform.com/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"phone": "+79991234567",
"status": "ACTIVE",
"emailVerifiedAt": "2024-01-15T10:35:00Z",
"phoneVerifiedAt": null,
"lastLoginAt": "2024-01-15T14:00:00Z",
"profile": {
"firstName": "John",
"lastName": "Doe",
"middleName": null,
"dateOfBirth": "1990-05-15",
"avatarUrl": "https://cdn.iwm-platform.com/avatars/550e8400.jpg",
"language": "ru",
"timezone": "Europe/Moscow"
},
"kyc": {
"status": "APPROVED",
"level": "STANDARD"
},
"roles": ["USER"],
"twoFactorEnabled": true,
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T12:00:00Z"
}
}PATCH /api/v1/users/me
Update the current user's profile.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
interface UpdateProfileRequest {
firstName?: string; // 2-100 characters
lastName?: string; // 2-100 characters
middleName?: string | null; // 2-100 characters or null
dateOfBirth?: string; // YYYY-MM-DD format
phone?: string; // E.164 format
language?: string; // ISO 639-1 (e.g., 'ru', 'en')
timezone?: string; // IANA timezone (e.g., 'Europe/Moscow')
}Query Parameters
None
Response (200 OK)
interface UpdateProfileResponse {
id: string;
email: string;
phone: string | null;
profile: {
firstName: string;
lastName: string;
middleName: string | null;
dateOfBirth: string | null;
avatarUrl: string | null;
language: string;
timezone: string;
};
updatedAt: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid input data |
| 401 | UNAUTHORIZED | Invalid or expired access token |
| 409 | PHONE_ALREADY_EXISTS | Phone number is already in use |
Example
Request:
curl -X PATCH https://api.iwm-platform.com/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"firstName": "John",
"lastName": "Smith",
"language": "en",
"timezone": "Europe/London"
}'Response:
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"phone": "+79991234567",
"profile": {
"firstName": "John",
"lastName": "Smith",
"middleName": null,
"dateOfBirth": "1990-05-15",
"avatarUrl": "https://cdn.iwm-platform.com/avatars/550e8400.jpg",
"language": "en",
"timezone": "Europe/London"
},
"updatedAt": "2024-01-15T15:00:00Z"
}
}POST /api/v1/users/me/avatar
Upload a new avatar image.
Authentication: Required
Rate Limit: 10 requests per hour
Request Headers
Authorization: Bearer <access_token>
Content-Type: multipart/form-dataRequest Body
// multipart/form-data
interface AvatarUploadRequest {
avatar: File; // Image file (JPEG, PNG, WebP)
// Max size: 5MB
// Min dimensions: 100x100
// Max dimensions: 2000x2000
}Query Parameters
None
Response (200 OK)
interface AvatarUploadResponse {
avatarUrl: string;
thumbnailUrl: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | No file provided |
| 400 | INVALID_FILE_TYPE | File type not supported |
| 400 | FILE_TOO_LARGE | File exceeds 5MB limit |
| 400 | INVALID_DIMENSIONS | Image dimensions out of range |
| 401 | UNAUTHORIZED | Invalid or expired access token |
| 429 | RATE_LIMIT_EXCEEDED | Too many upload attempts |
Example
Request:
curl -X POST https://api.iwm-platform.com/api/v1/users/me/avatar \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-F "avatar=@/path/to/image.jpg"Response:
{
"success": true,
"data": {
"avatarUrl": "https://cdn.iwm-platform.com/avatars/550e8400-full.jpg",
"thumbnailUrl": "https://cdn.iwm-platform.com/avatars/550e8400-thumb.jpg"
}
}DELETE /api/v1/users/me/avatar
Remove the current avatar.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
None
Query Parameters
None
Response (200 OK)
interface RemoveAvatarResponse {
message: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Invalid or expired access token |
| 404 | NO_AVATAR | No avatar to remove |
Example
Request:
curl -X DELETE https://api.iwm-platform.com/api/v1/users/me/avatar \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"success": true,
"data": {
"message": "Avatar removed successfully"
}
}GET /api/v1/users/me/kyc
Get KYC verification status and details.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
None
Query Parameters
None
Response (200 OK)
interface KycStatusResponse {
status: 'NOT_STARTED' | 'DOCUMENTS_PENDING' | 'SUBMITTED' | 'UNDER_REVIEW' | 'APPROVED' | 'REJECTED' | 'NEEDS_INFO';
level: 'NONE' | 'BASIC' | 'STANDARD' | 'ENHANCED';
submittedAt: string | null;
reviewedAt: string | null;
expiresAt: string | null;
rejectionReason: string | null;
requiredDocuments: {
type: string;
status: 'REQUIRED' | 'PENDING' | 'VERIFIED' | 'REJECTED';
rejectionReason: string | null;
}[];
limits: {
dailyWithdrawal: number;
monthlyWithdrawal: number;
singleTransaction: number;
};
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Invalid or expired access token |
Example
Request:
curl -X GET https://api.iwm-platform.com/api/v1/users/me/kyc \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"success": true,
"data": {
"status": "APPROVED",
"level": "STANDARD",
"submittedAt": "2024-01-10T14:00:00Z",
"reviewedAt": "2024-01-12T09:30:00Z",
"expiresAt": "2025-01-12T09:30:00Z",
"rejectionReason": null,
"requiredDocuments": [
{
"type": "PASSPORT",
"status": "VERIFIED",
"rejectionReason": null
},
{
"type": "SELFIE",
"status": "VERIFIED",
"rejectionReason": null
},
{
"type": "UTILITY_BILL",
"status": "REQUIRED",
"rejectionReason": null
}
],
"limits": {
"dailyWithdrawal": 100000,
"monthlyWithdrawal": 1000000,
"singleTransaction": 500000
}
}
}POST /api/v1/users/me/kyc
Submit KYC documents for verification.
Authentication: Required
Rate Limit: 5 requests per day
Request Headers
Authorization: Bearer <access_token>
Content-Type: multipart/form-dataRequest Body
// multipart/form-data
interface KycSubmissionRequest {
personalInfo: {
firstName: string;
lastName: string;
middleName?: string;
dateOfBirth: string; // YYYY-MM-DD
nationality: string; // ISO 3166-1 alpha-2
documentNumber: string;
documentType: 'PASSPORT' | 'ID_CARD' | 'DRIVER_LICENSE';
documentIssueDate: string; // YYYY-MM-DD
documentExpiryDate: string; // YYYY-MM-DD
address: {
country: string; // ISO 3166-1 alpha-2
region: string;
city: string;
street: string;
building: string;
apartment?: string;
postalCode: string;
};
};
documents: {
type: 'PASSPORT' | 'ID_CARD' | 'DRIVER_LICENSE' | 'UTILITY_BILL' | 'BANK_STATEMENT' | 'SELFIE';
file: File; // Image file (JPEG, PNG, PDF for documents)
// Max size: 10MB per file
}[];
}Query Parameters
None
Response (201 Created)
interface KycSubmissionResponse {
verificationId: string;
status: 'SUBMITTED';
estimatedReviewTime: string; // e.g., "24-48 hours"
documentsSubmitted: {
type: string;
status: 'PENDING';
}[];
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid input data |
| 400 | MISSING_DOCUMENTS | Required documents not provided |
| 400 | INVALID_FILE_TYPE | File type not supported |
| 400 | FILE_TOO_LARGE | File exceeds 10MB limit |
| 401 | UNAUTHORIZED | Invalid or expired access token |
| 409 | KYC_PENDING | KYC verification already pending |
| 409 | KYC_APPROVED | KYC already approved at this level |
| 429 | RATE_LIMIT_EXCEEDED | Too many submission attempts |
Example
Request:
curl -X POST https://api.iwm-platform.com/api/v1/users/me/kyc \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-F 'personalInfo={"firstName":"John","lastName":"Doe",...}' \
-F "documents[0][type]=PASSPORT" \
-F "documents[0][file]=@/path/to/passport.jpg" \
-F "documents[1][type]=SELFIE" \
-F "documents[1][file]=@/path/to/selfie.jpg"Response:
{
"success": true,
"data": {
"verificationId": "770e8400-e29b-41d4-a716-446655440000",
"status": "SUBMITTED",
"estimatedReviewTime": "24-48 hours",
"documentsSubmitted": [
{
"type": "PASSPORT",
"status": "PENDING"
},
{
"type": "SELFIE",
"status": "PENDING"
}
]
}
}GET /api/v1/users/me/notifications
Get user notifications.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
None
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (optional) |
| pageSize | number | Items per page, max 50 (optional) |
| status | string | Filter by status: 'UNREAD', 'READ', 'ALL' (optional) |
| type | string | Filter by type (optional) |
Response (200 OK)
interface NotificationsResponse {
notifications: Notification[];
unreadCount: number;
}
interface Notification {
id: string;
type: 'SYSTEM' | 'ORDER' | 'COMMISSION' | 'PAYOUT' | 'KYC' | 'SECURITY' | 'PROMO';
title: string;
message: string;
data: Record<string, unknown> | null;
isRead: boolean;
readAt: string | null;
createdAt: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Invalid or expired access token |
Example
Request:
curl -X GET "https://api.iwm-platform.com/api/v1/users/me/notifications?status=UNREAD&page=1&pageSize=20" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"success": true,
"data": {
"notifications": [
{
"id": "880e8400-e29b-41d4-a716-446655440000",
"type": "COMMISSION",
"title": "New Commission Received",
"message": "You earned 500 RUB commission from a referral purchase",
"data": {
"commissionId": "990e8400-e29b-41d4-a716-446655440000",
"amount": 500
},
"isRead": false,
"readAt": null,
"createdAt": "2024-01-15T14:30:00Z"
}
],
"unreadCount": 5
},
"meta": {
"pagination": {
"total": 25,
"page": 1,
"pageSize": 20,
"totalPages": 2,
"hasNext": true,
"hasPrevious": false
}
}
}PATCH /api/v1/users/me/notifications/preferences
Update notification preferences.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
interface NotificationPreferencesRequest {
email: {
orders?: boolean;
commissions?: boolean;
payouts?: boolean;
security?: boolean;
marketing?: boolean;
newsletter?: boolean;
};
push: {
orders?: boolean;
commissions?: boolean;
payouts?: boolean;
security?: boolean;
marketing?: boolean;
};
sms: {
security?: boolean; // OTP, login alerts
payouts?: boolean; // Payout confirmations
};
}Query Parameters
None
Response (200 OK)
interface NotificationPreferencesResponse {
email: {
orders: boolean;
commissions: boolean;
payouts: boolean;
security: boolean;
marketing: boolean;
newsletter: boolean;
};
push: {
orders: boolean;
commissions: boolean;
payouts: boolean;
security: boolean;
marketing: boolean;
};
sms: {
security: boolean;
payouts: boolean;
};
updatedAt: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid preferences format |
| 401 | UNAUTHORIZED | Invalid or expired access token |
Example
Request:
curl -X PATCH https://api.iwm-platform.com/api/v1/users/me/notifications/preferences \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"email": {
"marketing": false,
"newsletter": false
},
"push": {
"marketing": false
}
}'Response:
{
"success": true,
"data": {
"email": {
"orders": true,
"commissions": true,
"payouts": true,
"security": true,
"marketing": false,
"newsletter": false
},
"push": {
"orders": true,
"commissions": true,
"payouts": true,
"security": true,
"marketing": false
},
"sms": {
"security": true,
"payouts": true
},
"updatedAt": "2024-01-15T15:30:00Z"
}
}GET /api/v1/users/me/addresses
List saved addresses.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
None
Query Parameters
None
Response (200 OK)
interface AddressesResponse {
addresses: Address[];
}
interface Address {
id: string;
label: string; // e.g., "Home", "Office"
isDefault: boolean;
country: string; // ISO 3166-1 alpha-2
region: string;
city: string;
street: string;
building: string;
apartment: string | null;
postalCode: string;
phone: string | null;
recipientName: string | null;
createdAt: string;
updatedAt: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Invalid or expired access token |
Example
Request:
curl -X GET https://api.iwm-platform.com/api/v1/users/me/addresses \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"success": true,
"data": {
"addresses": [
{
"id": "aa0e8400-e29b-41d4-a716-446655440000",
"label": "Home",
"isDefault": true,
"country": "RU",
"region": "Moscow Oblast",
"city": "Moscow",
"street": "Tverskaya",
"building": "15",
"apartment": "42",
"postalCode": "125009",
"phone": "+79991234567",
"recipientName": "John Doe",
"createdAt": "2024-01-10T10:00:00Z",
"updatedAt": "2024-01-10T10:00:00Z"
}
]
}
}POST /api/v1/users/me/addresses
Add a new address.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Request Body
interface CreateAddressRequest {
label: string; // e.g., "Home", "Office"
isDefault?: boolean; // If true, sets as default address
country: string; // ISO 3166-1 alpha-2
region: string;
city: string;
street: string;
building: string;
apartment?: string;
postalCode: string;
phone?: string;
recipientName?: string;
}Query Parameters
None
Response (201 Created)
interface CreateAddressResponse {
id: string;
label: string;
isDefault: boolean;
country: string;
region: string;
city: string;
street: string;
building: string;
apartment: string | null;
postalCode: string;
phone: string | null;
recipientName: string | null;
createdAt: string;
updatedAt: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid input data |
| 401 | UNAUTHORIZED | Invalid or expired access token |
| 400 | MAX_ADDRESSES_REACHED | Maximum 10 addresses allowed |
Example
Request:
curl -X POST https://api.iwm-platform.com/api/v1/users/me/addresses \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"label": "Office",
"isDefault": false,
"country": "RU",
"region": "Moscow Oblast",
"city": "Moscow",
"street": "Arbat",
"building": "25",
"apartment": "100",
"postalCode": "119002",
"phone": "+79999876543",
"recipientName": "John Doe"
}'Response:
{
"success": true,
"data": {
"id": "bb0e8400-e29b-41d4-a716-446655440000",
"label": "Office",
"isDefault": false,
"country": "RU",
"region": "Moscow Oblast",
"city": "Moscow",
"street": "Arbat",
"building": "25",
"apartment": "100",
"postalCode": "119002",
"phone": "+79999876543",
"recipientName": "John Doe",
"createdAt": "2024-01-15T16:00:00Z",
"updatedAt": "2024-01-15T16:00:00Z"
}
}PATCH /api/v1/users/me/addresses/:id
Update an existing address.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Path Parameters
| Parameter | Type | Description |
|---|---|---|
| id | string (UUID) | Address ID |
Request Body
interface UpdateAddressRequest {
label?: string;
isDefault?: boolean;
country?: string;
region?: string;
city?: string;
street?: string;
building?: string;
apartment?: string | null;
postalCode?: string;
phone?: string | null;
recipientName?: string | null;
}Query Parameters
None
Response (200 OK)
interface UpdateAddressResponse {
id: string;
label: string;
isDefault: boolean;
country: string;
region: string;
city: string;
street: string;
building: string;
apartment: string | null;
postalCode: string;
phone: string | null;
recipientName: string | null;
createdAt: string;
updatedAt: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid input data |
| 401 | UNAUTHORIZED | Invalid or expired access token |
| 404 | ADDRESS_NOT_FOUND | Address not found |
Example
Request:
curl -X PATCH https://api.iwm-platform.com/api/v1/users/me/addresses/bb0e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"isDefault": true,
"apartment": "101"
}'Response:
{
"success": true,
"data": {
"id": "bb0e8400-e29b-41d4-a716-446655440000",
"label": "Office",
"isDefault": true,
"country": "RU",
"region": "Moscow Oblast",
"city": "Moscow",
"street": "Arbat",
"building": "25",
"apartment": "101",
"postalCode": "119002",
"phone": "+79999876543",
"recipientName": "John Doe",
"createdAt": "2024-01-15T16:00:00Z",
"updatedAt": "2024-01-15T16:30:00Z"
}
}DELETE /api/v1/users/me/addresses/:id
Delete an address.
Authentication: Required
Rate Limit: 100 requests per minute
Request Headers
Authorization: Bearer <access_token>Path Parameters
| Parameter | Type | Description |
|---|---|---|
| id | string (UUID) | Address ID |
Request Body
None
Query Parameters
None
Response (200 OK)
interface DeleteAddressResponse {
message: string;
addressId: string;
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Invalid or expired access token |
| 404 | ADDRESS_NOT_FOUND | Address not found |
| 400 | CANNOT_DELETE_DEFAULT | Cannot delete default address when other addresses exist |
Example
Request:
curl -X DELETE https://api.iwm-platform.com/api/v1/users/me/addresses/bb0e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"success": true,
"data": {
"message": "Address deleted successfully",
"addressId": "bb0e8400-e29b-41d4-a716-446655440000"
}
}