Skip to content

Client API

kwork_api.client.KworkClient

KworkClient(
    token=None, cookies=None, timeout=30.0, base_url=None
)

Kwork.ru API client.

Usage

Login with credentials

client = await KworkClient.login("username", "password")

Or restore from token

client = KworkClient(token="your_web_auth_token")

Make requests

catalog = await client.catalog.get_list(page=1)

Initialize client.

Parameters:

Name Type Description Default
token Optional[str]

Web auth token (from getWebAuthToken)

None
cookies Optional[dict[str, str]]

Session cookies (optional, will be set from token)

None
timeout float

Request timeout in seconds

30.0
base_url Optional[str]

Custom base URL (for testing)

None
Source code in src/kwork_api/client.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def __init__(
    self,
    token: Optional[str] = None,
    cookies: Optional[dict[str, str]] = None,
    timeout: float = 30.0,
    base_url: Optional[str] = None,
):
    """
    Initialize client.

    Args:
        token: Web auth token (from getWebAuthToken)
        cookies: Session cookies (optional, will be set from token)
        timeout: Request timeout in seconds
        base_url: Custom base URL (for testing)
    """
    self.base_url = base_url or self.BASE_URL
    self.timeout = timeout
    self._token = token
    self._cookies = cookies or {}

    # Initialize HTTP client
    self._client: Optional[httpx.AsyncClient] = None

Attributes

catalog property

catalog

Catalog API.

notifications property

notifications

Notifications API.

other property

other

Other endpoints.

projects property

projects

Projects API.

reference property

reference

Reference data API.

user property

user

User API.

Classes

CatalogAPI

CatalogAPI(client)

Catalog/Kworks API endpoints.

Source code in src/kwork_api/client.py
266
267
def __init__(self, client: "KworkClient"):
    self.client = client
Functions
get_details async
get_details(kwork_id)

Get kwork details.

Parameters:

Name Type Description Default
kwork_id int

Kwork ID

required

Returns:

Type Description
KworkDetails

KworkDetails with full information

Source code in src/kwork_api/client.py
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
async def get_details(self, kwork_id: int) -> KworkDetails:
    """
    Get kwork details.

    Args:
        kwork_id: Kwork ID

    Returns:
        KworkDetails with full information
    """
    data = await self.client._request(
        "POST",
        "/getKworkDetails",
        json={"kwork_id": kwork_id},
    )
    return KworkDetails.model_validate(data)
get_details_extra async
get_details_extra(kwork_id)

Get additional kwork details.

Parameters:

Name Type Description Default
kwork_id int

Kwork ID

required

Returns:

Type Description
dict[str, Any]

Extra details dict

Source code in src/kwork_api/client.py
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
async def get_details_extra(self, kwork_id: int) -> dict[str, Any]:
    """
    Get additional kwork details.

    Args:
        kwork_id: Kwork ID

    Returns:
        Extra details dict
    """
    return await self.client._request(
        "POST",
        "/getKworkDetailsExtra",
        json={"kwork_id": kwork_id},
    )
get_list async
get_list(page=1, category_id=None, sort='recommend')

Get kworks catalog.

Parameters:

Name Type Description Default
page int

Page number

1
category_id Optional[int]

Category filter

None
sort str

Sort option (recommend, price_asc, price_desc, etc.)

'recommend'

Returns:

Type Description
CatalogResponse

CatalogResponse with kworks and pagination

Source code in src/kwork_api/client.py
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
async def get_list(
    self,
    page: int = 1,
    category_id: Optional[int] = None,
    sort: str = "recommend",
) -> CatalogResponse:
    """
    Get kworks catalog.

    Args:
        page: Page number
        category_id: Category filter
        sort: Sort option (recommend, price_asc, price_desc, etc.)

    Returns:
        CatalogResponse with kworks and pagination
    """
    data = await self.client._request(
        "POST",
        "/catalogMainv2",
        json={
            "page": page,
            "category_id": category_id,
            "sort": sort,
        },
    )
    return CatalogResponse.model_validate(data)

NotificationsAPI

NotificationsAPI(client)

Notifications and messages endpoints.

Source code in src/kwork_api/client.py
475
476
def __init__(self, client: "KworkClient"):
    self.client = client
Functions
fetch async
fetch()

Fetch new notifications.

Source code in src/kwork_api/client.py
483
484
485
486
async def fetch(self) -> NotificationsResponse:
    """Fetch new notifications."""
    data = await self.client._request("POST", "/notificationsFetch")
    return NotificationsResponse.model_validate(data)
get_blocked_dialogs async
get_blocked_dialogs()

Get blocked dialogs.

Source code in src/kwork_api/client.py
493
494
495
496
async def get_blocked_dialogs(self) -> list[Dialog]:
    """Get blocked dialogs."""
    data = await self.client._request("POST", "/blockedDialogList")
    return [Dialog.model_validate(d) for d in data.get("dialogs", [])]
get_dialogs async
get_dialogs()

Get dialogs list.

Source code in src/kwork_api/client.py
488
489
490
491
async def get_dialogs(self) -> list[Dialog]:
    """Get dialogs list."""
    data = await self.client._request("POST", "/dialogs")
    return [Dialog.model_validate(d) for d in data.get("dialogs", [])]
get_list async
get_list()

Get notifications list.

Source code in src/kwork_api/client.py
478
479
480
481
async def get_list(self) -> NotificationsResponse:
    """Get notifications list."""
    data = await self.client._request("POST", "/notifications")
    return NotificationsResponse.model_validate(data)

OtherAPI

OtherAPI(client)

Other API endpoints.

Source code in src/kwork_api/client.py
503
504
def __init__(self, client: "KworkClient"):
    self.client = client
Functions
get_actor async
get_actor()

Get actor info.

Source code in src/kwork_api/client.py
565
566
567
async def get_actor(self) -> dict[str, Any]:
    """Get actor info."""
    return await self.client._request("POST", "/actor")
get_channel async
get_channel()

Get channel info.

Source code in src/kwork_api/client.py
526
527
528
async def get_channel(self) -> dict[str, Any]:
    """Get channel info."""
    return await self.client._request("POST", "/getChannel")
get_exchange_info async
get_exchange_info()

Get exchange info.

Source code in src/kwork_api/client.py
522
523
524
async def get_exchange_info(self) -> dict[str, Any]:
    """Get exchange info."""
    return await self.client._request("POST", "/exchangeInfo")
get_favorite_categories async
get_favorite_categories()

Get favorite categories.

Source code in src/kwork_api/client.py
552
553
554
555
async def get_favorite_categories(self) -> list[int]:
    """Get favorite categories."""
    data = await self.client._request("POST", "/favoriteCategories")
    return data.get("categories", [])
get_in_app_notification async
get_in_app_notification()

Get in-app notification.

Source code in src/kwork_api/client.py
530
531
532
async def get_in_app_notification(self) -> dict[str, Any]:
    """Get in-app notification."""
    return await self.client._request("POST", "/getInAppNotification")
get_kworks_status async
get_kworks_status()

Get kworks status.

Source code in src/kwork_api/client.py
514
515
516
async def get_kworks_status(self) -> dict[str, Any]:
    """Get kworks status."""
    return await self.client._request("POST", "/kworksStatusList")
get_offers async
get_offers()

Get offers.

Source code in src/kwork_api/client.py
518
519
520
async def get_offers(self) -> dict[str, Any]:
    """Get offers."""
    return await self.client._request("POST", "/offers")
get_security_user_data async
get_security_user_data()

Get security user data.

Source code in src/kwork_api/client.py
534
535
536
async def get_security_user_data(self) -> dict[str, Any]:
    """Get security user data."""
    return await self.client._request("POST", "/getSecurityUserData")
get_viewed_kworks async
get_viewed_kworks()

Get viewed kworks.

Source code in src/kwork_api/client.py
547
548
549
550
async def get_viewed_kworks(self) -> list[Kwork]:
    """Get viewed kworks."""
    data = await self.client._request("POST", "/viewedCatalogKworks")
    return [Kwork.model_validate(k) for k in data.get("kworks", [])]
get_wants async
get_wants()

Get user wants.

Source code in src/kwork_api/client.py
506
507
508
async def get_wants(self) -> dict[str, Any]:
    """Get user wants."""
    return await self.client._request("POST", "/myWants")
get_wants_status async
get_wants_status()

Get wants status.

Source code in src/kwork_api/client.py
510
511
512
async def get_wants_status(self) -> dict[str, Any]:
    """Get wants status."""
    return await self.client._request("POST", "/wantsStatusList")
go_offline async
go_offline()

Set user status to offline.

Source code in src/kwork_api/client.py
561
562
563
async def go_offline(self) -> dict[str, Any]:
    """Set user status to offline."""
    return await self.client._request("POST", "/offline")
is_dialog_allow async
is_dialog_allow(user_id)

Check if dialog is allowed.

Source code in src/kwork_api/client.py
538
539
540
541
542
543
544
545
async def is_dialog_allow(self, user_id: int) -> bool:
    """Check if dialog is allowed."""
    data = await self.client._request(
        "POST",
        "/isDialogAllow",
        json={"user_id": user_id},
    )
    return data.get("allowed", False)
update_settings async
update_settings(settings)

Update user settings.

Source code in src/kwork_api/client.py
557
558
559
async def update_settings(self, settings: dict[str, Any]) -> dict[str, Any]:
    """Update user settings."""
    return await self.client._request("POST", "/updateSettings", json=settings)

ProjectsAPI

ProjectsAPI(client)

Projects (freelance orders) API endpoints.

Source code in src/kwork_api/client.py
335
336
def __init__(self, client: "KworkClient"):
    self.client = client
Functions
get_list async
get_list(page=1, category_id=None)

Get projects list.

Parameters:

Name Type Description Default
page int

Page number

1
category_id Optional[int]

Category filter

None

Returns:

Type Description
ProjectsResponse

ProjectsResponse with projects and pagination

Source code in src/kwork_api/client.py
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
async def get_list(
    self,
    page: int = 1,
    category_id: Optional[int] = None,
) -> ProjectsResponse:
    """
    Get projects list.

    Args:
        page: Page number
        category_id: Category filter

    Returns:
        ProjectsResponse with projects and pagination
    """
    data = await self.client._request(
        "POST",
        "/projects",
        json={
            "page": page,
            "category_id": category_id,
        },
    )
    return ProjectsResponse.model_validate(data)
get_payer_orders async
get_payer_orders()

Get orders where user is customer.

Returns:

Type Description
list[Project]

List of projects

Source code in src/kwork_api/client.py
363
364
365
366
367
368
369
370
371
async def get_payer_orders(self) -> list[Project]:
    """
    Get orders where user is customer.

    Returns:
        List of projects
    """
    data = await self.client._request("POST", "/payerOrders")
    return [Project.model_validate(p) for p in data.get("orders", [])]
get_worker_orders async
get_worker_orders()

Get orders where user is performer.

Returns:

Type Description
list[Project]

List of projects

Source code in src/kwork_api/client.py
373
374
375
376
377
378
379
380
381
async def get_worker_orders(self) -> list[Project]:
    """
    Get orders where user is performer.

    Returns:
        List of projects
    """
    data = await self.client._request("POST", "/workerOrders")
    return [Project.model_validate(p) for p in data.get("orders", [])]

ReferenceAPI

ReferenceAPI(client)

Reference data (cities, countries, etc.) endpoints.

Source code in src/kwork_api/client.py
437
438
def __init__(self, client: "KworkClient"):
    self.client = client
Functions
get_badges_info async
get_badges_info()

Get badges info.

Source code in src/kwork_api/client.py
465
466
467
468
async def get_badges_info(self) -> list[Badge]:
    """Get badges info."""
    data = await self.client._request("POST", "/getBadgesInfo")
    return [Badge.model_validate(b) for b in data.get("badges", [])]
get_cities async
get_cities()

Get all cities.

Source code in src/kwork_api/client.py
440
441
442
443
async def get_cities(self) -> list[City]:
    """Get all cities."""
    data = await self.client._request("POST", "/cities")
    return [City.model_validate(c) for c in data.get("cities", [])]
get_countries async
get_countries()

Get all countries.

Source code in src/kwork_api/client.py
445
446
447
448
async def get_countries(self) -> list[Country]:
    """Get all countries."""
    data = await self.client._request("POST", "/countries")
    return [Country.model_validate(c) for c in data.get("countries", [])]
get_features async
get_features()

Get available features.

Source code in src/kwork_api/client.py
455
456
457
458
async def get_features(self) -> list[Feature]:
    """Get available features."""
    data = await self.client._request("POST", "/getAvailableFeatures")
    return [Feature.model_validate(f) for f in data.get("features", [])]
get_public_features async
get_public_features()

Get public features.

Source code in src/kwork_api/client.py
460
461
462
463
async def get_public_features(self) -> list[Feature]:
    """Get public features."""
    data = await self.client._request("POST", "/getPublicFeatures")
    return [Feature.model_validate(f) for f in data.get("features", [])]
get_timezones async
get_timezones()

Get all timezones.

Source code in src/kwork_api/client.py
450
451
452
453
async def get_timezones(self) -> list[TimeZone]:
    """Get all timezones."""
    data = await self.client._request("POST", "/timezones")
    return [TimeZone.model_validate(t) for t in data.get("timezones", [])]

UserAPI

UserAPI(client)

User API endpoints.

Source code in src/kwork_api/client.py
388
389
def __init__(self, client: "KworkClient"):
    self.client = client
Functions
get_favorite_kworks async
get_favorite_kworks()

Get favorite kworks.

Returns:

Type Description
list[Kwork]

List of kworks

Source code in src/kwork_api/client.py
422
423
424
425
426
427
428
429
430
async def get_favorite_kworks(self) -> list[Kwork]:
    """
    Get favorite kworks.

    Returns:
        List of kworks
    """
    data = await self.client._request("POST", "/favoriteKworks")
    return [Kwork.model_validate(k) for k in data.get("kworks", [])]
get_info async
get_info()

Get current user info.

Returns:

Type Description
dict[str, Any]

User info dict

Source code in src/kwork_api/client.py
391
392
393
394
395
396
397
398
async def get_info(self) -> dict[str, Any]:
    """
    Get current user info.

    Returns:
        User info dict
    """
    return await self.client._request("POST", "/user")
get_reviews async
get_reviews(user_id=None, page=1)

Get user reviews.

Parameters:

Name Type Description Default
user_id Optional[int]

User ID (None for current user)

None
page int

Page number

1

Returns:

Type Description
ReviewsResponse

ReviewsResponse

Source code in src/kwork_api/client.py
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
async def get_reviews(
    self,
    user_id: Optional[int] = None,
    page: int = 1,
) -> ReviewsResponse:
    """
    Get user reviews.

    Args:
        user_id: User ID (None for current user)
        page: Page number

    Returns:
        ReviewsResponse
    """
    data = await self.client._request(
        "POST",
        "/userReviews",
        json={"user_id": user_id, "page": page},
    )
    return ReviewsResponse.model_validate(data)

Functions

close async

close()

Close HTTP client.

Source code in src/kwork_api/client.py
179
180
181
182
async def close(self) -> None:
    """Close HTTP client."""
    if self._client and not self._client.is_closed:
        await self._client.aclose()

login async classmethod

login(username, password, timeout=30.0)

Login with username and password.

Parameters:

Name Type Description Default
username str

Kwork username or email

required
password str

Kwork password

required
timeout float

Request timeout

30.0

Returns:

Type Description
KworkClient

Authenticated KworkClient instance

Raises:

Type Description
KworkAuthError

If login fails

Source code in src/kwork_api/client.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
@classmethod
async def login(
    cls,
    username: str,
    password: str,
    timeout: float = 30.0,
) -> "KworkClient":
    """
    Login with username and password.

    Args:
        username: Kwork username or email
        password: Kwork password
        timeout: Request timeout

    Returns:
        Authenticated KworkClient instance

    Raises:
        KworkAuthError: If login fails
    """
    client = cls(timeout=timeout)

    try:
        async with client._get_httpx_client() as http_client:
            # Step 1: Login to get session cookies
            login_data = {
                "login_or_email": username,
                "password": password,
            }

            response = await http_client.post(
                cls.LOGIN_URL,
                data=login_data,
                headers={"Referer": "https://kwork.ru/"},
            )

            if response.status_code != 200:
                raise KworkAuthError(f"Login failed: {response.status_code}")

            # Extract cookies
            cookies = dict(response.cookies)

            if "userId" not in cookies:
                raise KworkAuthError("Login failed: no userId in cookies")

            # Step 2: Get web auth token
            token_response = await http_client.post(
                cls.TOKEN_URL,
                json={},
            )

            if token_response.status_code != 200:
                raise KworkAuthError(f"Token request failed: {token_response.status_code}")

            token_data = token_response.json()
            web_token = token_data.get("web_auth_token")

            if not web_token:
                raise KworkAuthError("No web_auth_token in response")

            # Create new client with token
            return cls(token=web_token, cookies=cookies, timeout=timeout)

    except httpx.RequestError as e:
        raise KworkNetworkError(f"Login request failed: {e}")