Platform: VK API
Grounded in dev.vk.com/method/* and dev.vk.com/reference/objects/*.
Endpoint shape
https://api.vk.com/method/<methodName>?<params>&access_token=<token>&v=<version>
vis mandatory. This plugin pins5.199by default and exposesapiVersionin config.- Responses are
{ response: ... }or{ error: { error_code, error_msg, error_text, request_params, captcha_sid? } }. - POST with
application/x-www-form-urlencodedis required for anything with long text or attachments; GET breaks on URL length for wall posts with many attachments.
Token types — the single most important constraint
| Token | Can | Cannot |
|---|---|---|
| Community (group) token | wall post/edit/delete/pin, comments, photos/docs upload, board topics, market, messages, join requests handling, bans (with limits), Callback/LongPoll settings | groups.getMembers (full list), groups.getBanned (full), stats.get, groups.getRequests in some cases |
| User token (admin's own) | everything above plus members, banned, requests, stats | acts as the human — posts appear authored by them unless from_group: 1 |
| Service token | public methods only | anything administrative |
Consequences for this plugin:
Config.accessTokenis the community token — required.Config.userAccessTokenis optional but unlocksvk_members_list,vk_stats_get, and fullvk_ban_list.- Every tool that needs the user token checks for it and returns a typed
VK_SCOPE_MISSINGerror with the exact scope name — not a raw VK error 15.
Scopes
Community token: manage, wall, photos, docs, messages, market, stories, topics.
User token additionally: groups, stats, offline (for a non-expiring token).
Rate limits
| Token | Sustained | Burst behaviour |
|---|---|---|
| Community | ~3 req/s | error 6 — Too many requests per second |
| User | ~20 req/s | same |
This plugin implements a token bucket in vk/client.ts:
rateLimit.rps(default 3),rateLimit.burst(default 5),rateLimit.maxConcurrent(default 2).- On
error 6, the client waitsmax(1s, backoff)and retries up toretry.maxAttempts. executebatching: up to 25 VK method calls can be packed into oneexecuterequest. Used for batch member/ban operations to cut request count by ~20x.
Error codes that matter
| Code | Meaning | Handling in this plugin |
|---|---|---|
1 |
Unknown error | retry (transient) |
5 |
Auth failed — token invalid/expired | no retry, typed VK_AUTH_FAILED, surfaced to the user with the fix |
6 |
Too many requests per second | backoff + retry |
7 |
Permission denied | typed VK_PERMISSION_DENIED |
9 |
Flood control | backoff (longer), retry |
10 |
Internal server error | retry |
14 |
Captcha needed | typed VK_CAPTCHA_REQUIRED with captcha_sid; config captcha.policy decides fail or ask |
15 |
Access denied | typed VK_ACCESS_DENIED — usually a missing scope or wrong admin level |
17 |
Validation required | typed VK_VALIDATION_REQUIRED — user must confirm in VK UI |
18 |
User deleted/banned | typed, no retry |
100 |
Invalid parameter | typed VK_BAD_PARAM, includes the offending param name |
203 |
Access to group denied | typed VK_GROUP_ACCESS_DENIED |
260 |
Cannot remove the community's last admin | typed, surfaced verbatim |
retry.retryOn defaults to [1, 6, 9, 10]. Everything else fails fast — retrying a 5 or 15 wastes quota and hides the real problem.
Pagination
| Method family | Max count |
Notes |
|---|---|---|
groups.getMembers |
1000 | requires user token |
groups.getBanned |
200 | |
groups.getRequests |
200 | |
wall.get |
100 | |
wall.getComments |
100 | `sort: asc |
board.getComments |
100 | |
messages.getConversations |
200 | |
market.get |
200 |
Every list tool takes offset and count, clamps count to the method's maximum, and returns { items, total, offset, count, hasMore } so the model can page without guessing.
Media upload — always two steps
1. <type>.get<X>UploadServer → { upload_url }
2. POST multipart to upload_url → { server, photo, hash } (fields vary by type)
3. <type>.save<X> → { id, owner_id, ... }
4. build attachment string → "photo-123_456"
Upload URLs are single-use and expire. A retry must restart from step 1, not re-POST to the same URL. vk_media_upload handles this: on upload failure it re-requests the server up to retry.maxAttempts.
Attachment string formats:
| Type | Format |
|---|---|
| photo | photo{owner_id}_{id} |
| doc | doc{owner_id}_{id} |
| video | video{owner_id}_{id} |
| story | story{owner_id}_{id} |
| wall post | wall{owner_id}_{post_id} |
LongPoll
groups.getLongPollServer → { server, key, ts }
GET {server}?act=a_check&key={key}&ts={ts}&wait=25
→ { ts, updates: [...] }
→ { failed: 1 } // ts stale → re-read ts via groups.getLongPollServer, keep key
→ { failed: 2 } // key expired → full re-request of server+key+ts
→ { failed: 3 } // info lost → new session
Modes: 0 — receive all except typing/online; 1 — only messages; 2 — messages + typing (default here, filtered in events/mapping.ts).
Update codes used:
| Code | Event | Action |
|---|---|---|
| 4 | MESSAGE_NEW |
followup to agent |
| 6 | WALL_POST_NEW |
followup |
| 7 | WALL_REPLY_NEW |
followup |
| 20 | GROUP_JOIN |
followup if notifications.onJoin |
| 21 | GROUP_LEAVE |
followup if notifications.onLeave |
| 62 | MESSAGE_TYPING_STATE |
dropped |
| 63 | BOARD_REPLY_NEW |
followup |
| 74 | MARKET_COMMENT_NEW |
followup |
Callback API
Needs a public HTTPS endpoint, a confirmation string, and a secret. In a local DSH install there is no public endpoint, so Callback is opt-in and off by default. vk_callback_manage exists for deployments that do have a tunnel or a public host.
Community object — fields this plugin relies on
From dev.vk.com/reference/objects/group:
is_admin(0/1),admin_level(1 moderator, 2 editor, 3 admin) — requiresgroupsscope. This is the authority source for the safety guard.is_closed(0 open, 1 closed, 2 private).type(group/page/event).members_count,counters,wall,market,addresses,age_limits,main_section.ban_info(end_date,comment) — only for single-community requests.
What the API does not give you
- No endpoint to read another community's members or stats.
- No way to detect whether a token is a community or user token except by trying a scope-gated method.
- No idempotency keys except
guidonwall.post(which does provide safe retries for posting). - No batch moderation beyond
execute(25 calls).
References
dev.vk.com/method/groups— the group method family.dev.vk.com/method/wall,/board,/market,/messages,/photos,/docs,/stats,/utils,/execute.dev.vk.com/reference/objects/group— the community object.dev.vk.com/api/access-token/*— token types and scopes.dev.vk.com/api/community-long-poll— LongPoll protocol.