QivunaDevelopers

Errors

Every refusal has a real HTTP status, a stable string code, and a request id you can quote to support.

Shape#

HTTP/1.1 403 Forbidden
X-Request-Id: 01JB2H9M4T7Q2V8X5C1N6R3K0W

{"ok": false,
 "error": {"code": "forbidden_right", "message": "The bot lacks the right to do this here",
           "retry_after": null, "parameter": "can_send"},
 "request_id": "01JB2H9M4T7Q2V8X5C1N6R3K0W"}

Answers from the edge in front of the API keep the same ok/error shape but have no request_id: a 429 from the edge limits, and {"ok":false,"error":{"code":"not_found"}} for any path outside /v1/. Always use https://: the API is not served over plain HTTP, and a request sent over plain HTTP has already exposed its token — revoke it.

Codes#

HTTPcodeMeaningWhat to do
400bad_requestA parameter is missing or invalid. parameter names it (also method when a POST-only method was called with GET, and Idempotency-Key for a malformed key).Fix the request. Do not retry unchanged.
400token_in_urlThe token appeared in the URL path or query string. That token has been revoked and the owner was told by QivBot.Reveal a new token in the app and send it only in the Authorization header.
400bad_keysetMyEncryptionKey: a key, the proof of possession or its time t is not valid, the proof was already used, or the X25519 key belongs to another bot. parameter is x25519, ed25519, pop or t.Generate a fresh key pair and sign pop with the current time.
400webhooks_disabledsetWebhook: webhooks are not offered on this platform yet. Nothing was checked or saved. Not temporary: retrying gives the same answer.Receive updates with getUpdates (long polling). The changelog will say when webhooks open.
401unauthorizedNo Authorization: Bot <token> header, a malformed one, or an unknown token.Check the header. Repeated failures from one address are rate limited before the token is even checked.
401token_revokedThe token is known but revoked or past its 10-minute overlap window (a newer token was revealed, the tokens were revoked, the bot changed owners).Use the current token. Never retry with the old one.
403bot_suspendedThe bot is suspended, banned or deleted.Stop calling. The owner was told why in QivBot; appeals go to support.
403bot_restrictedThe bot is restricted by the Qivuna team: read methods work, writes are refused.Keep reading; writes resume when the restriction is lifted.
403forbidden_rightThe bot's grant in this room lacks a right. parameter names it (can_send, can_post, can_send_media, can_delete_messages, …). Also returned when a group allows only admins to send.Ask a room admin to grant the right. Do not retry.
403user_not_startedA 1:1 send to a person who never pressed Start.Wait for the person to start the bot (a start link helps).
403user_blocked_botThe person stopped or blocked the bot.Stop sending to this person until they start the bot again.
403unsolicited_limitThe person has not written to the bot or pressed its button in 24 h and the bot used today's unsolicited messages for them (3 / 10 / 50 by tier).Send only when asked, or wait for the next UTC day.
403e2ee_requiredPlaintext into an end-to-end encrypted context: an encrypted bot's private chat, an encrypted group the bot is attached to, or a plaintext answer to an encrypted button press.Send an envelope instead (the SDKs do this).
403e2ee_unsupportedNot possible where the room is end-to-end encrypted: moderation, media and member lists in an encrypted group, and every call through a grant that was suspended when the group became encrypted (except getChat and leaveChat).Nothing to retry. An admin can re-add the bot in encrypted (addressed) mode.
403reply_window_closedreply_token missing, expired (1 h), used up (5 sends) or voided (key change, detach, the person left the group).Answer the next request instead; a reply needs a fresh token.
403target_protectedModeration against the group's creator, an owner or admin, or another bot (for deletes: a bot's message).Not allowed for bots. Do not retry.
404not_foundUnknown method, a method that is not available yet (for example the encryption-key methods while encrypted bots are off), or the bot platform is switched off.Check the method name; check the changelog.
404chat_not_foundThe chat id is unknown, the bot is not in that room, cannot see it, the person is outside the rollout, or it never started the bot. One answer for all of these, on purpose.Do not retry the same id.
404message_not_foundUnknown message, a message of another chat, a deleted one, an end-to-end encrypted one, or an event line.Do not retry the same id.
404user_not_foundThe user_id does not decode for this bot, is a bot, or is not (or no longer) in the group.Do not retry the same id.
404callback_not_foundThe callback query is unknown, older than 15 minutes, already answered, or not this bot's.Answer presses promptly, once.
404file_not_foundgetFile or a download: an unknown file_id, one no longer visible to this bot, or an expired download link.Call getFile again while the file is still visible to the bot.
409conflictgetUpdates while a webhook is set, or while another getUpdates of this bot runs; or a second setWebhook while one is running. message says which.Run one poller per bot, or call deleteWebhook first.
409idempotency_mismatchThe Idempotency-Key was used in the last hour with a different request.Use a new key for a new request.
409idempotency_in_progressA request with the same Idempotency-Key is still running.Retry shortly with the same key.
409key_not_activeAn encrypted send, edit or answer (or setWebhook with encrypt_payload) while the bot has no active key.Propose a key and have the owner confirm it in the app.
410room_closedThe room was closed by moderation.Stop writing to it.
413payload_too_largeA JSON body over 1 MB, a file over 20 MB, form fields of an upload over 1 MB, or a file sent to a method other than the three send methods.Send less. Do not retry unchanged.
422message_too_oldEditing a message older than 48 h, or deleting someone else's message older than 48 h.Send a new message instead.
422invalid_markupThe inline keyboard breaks a limit or has an unknown field. parameter is reply_markup.Fix the keyboard (see Keyboards).
422invalid_entitiesEntities outside the text or overlapping, an unknown type, a non-https link, or HTML with an unsupported tag.Fix the formatting (see Text and formatting).
422content_blockedThe text, a button, a caption, a description or a moderation reason matched the platform's anti-phishing rules. The answer never says which rule. Each block adds a strike to the owner (at most one a day).Do not ask people for codes, passwords or recovery phrases, and do not link to look-alikes of Qivuna.
422content_not_allowedsetMyDescription or setMyShortDescription: the text has words that cannot be published (the platform's word filter for public texts). parameter names the field. No strike.Change the text.
422webhook_unverifiedThe ownership challenge failed. message says why without the response body: the status, “without the challenge”, or “could not be reached”.Answer the challenge (see Webhooks).
429rate_limitedA rate limit. retry_after (seconds) and a Retry-After header say when to try again.Wait retry_after seconds, then retry.
500internalAn unexpected error on our side. The request_id identifies it in our logs.Retry reads. Retry writes only with the same Idempotency-Key.
503platform_pausedThe bot platform is paused (the global kill switch). Every method answers this; nothing is queued while paused.Back off and retry later; updates created while paused are not kept.
503webhook_unavailablesetWebhook: webhooks are not available right now (no egress, or too many ownership challenges in flight; then retry_after is 5).Use getUpdates, or retry later.

Handling errors#