Wiki
猫Table of Contents
- tgapi Overview
- The important split first
- The normal layering
- When to use tgapi directly
- Typed methods first
- APIOpts
- API behavior and responsibilities
- Worker pool behavior
- Uploader behavior and responsibilities
- Choosing between API and Uploader
- File downloads
- Low-level request builders
- Low-level escape hatches
- Error model
- Testability
- tgapi vs high-level Laniakea
- Related pages
tgapi Overview
Russian version: tgapi-Overview-RU
tgapi is the low-level Telegram Bot API layer used under Laniakea’s higher-level bot runtime. Use it when you need direct access to Telegram methods, explicit parameter structs, upload control, or raw request building that sits below plugins and MessageContext helpers.
The important split first
There are two main clients:
tgapi.APIfor JSON requeststgapi.Uploaderfor multipart file uploads
That split is intentional:
- JSON-only calls such as
SendMessage,GetMe,GetUpdates, orEditMessageTextgo throughAPI; - binary uploads such as
SendPhoto,SendDocument,SendVideo, or webhook certificates go throughUploader.
If you stay on the typed method surface, you usually do not need to think about raw HTTP details at all.
The normal layering
In practice, Laniakea has three levels:
- high-level handler helpers on
MessageContext; - runtime structure on
Bot, plugins, and middleware; - low-level Telegram access in
tgapi.
tgapi is not a separate product inside the repository. It is the lower-level layer that the high-level bot runtime is already using under the hood.
When to use tgapi directly
Use tgapi directly when:
- a
MessageContexthelper does not expose the Telegram feature you need; - you need a Telegram method outside the high-level command/payload flow;
- you want explicit control over params, parse modes, message edits, or uploads;
- you are writing infrastructure code rather than command logic.
Stay on high-level Laniakea helpers when:
- you only need normal replies or callback answers;
- the work belongs inside command or payload handlers;
- keyboard, draft, localization, and context helpers already cover the use case.
Typical examples where tgapi is the better tool:
- setting bot metadata or command scopes directly;
- file downloads and streaming;
- multipart uploads;
- one-off Telegram methods that do not have a
MessageContextwrapper.
Typed methods first
The normal tgapi workflow is method-specific and typed.
Example:
api := tgapi.NewAPI(tgapi.NewAPIOpts(token))
defer api.Close()
msg, err := api.SendMessage(tgapi.SendMessage{
ChatID: chatID,
Text: "Hello",
})
This is preferred over building raw requests manually because:
- the method name is fixed correctly;
- the parameter type matches the Telegram method;
- the result type is explicit;
- per-chat rate limiting can be wired by the helper.
Most methods also have a context-aware variant:
msg, err := api.SendMessageWithContext(ctx, params)
Use the context-aware variants when cancellation, deadlines, or graceful shutdown behavior matters.
APIOpts
API is configured through NewAPIOpts(token).
Useful options include:
SetHTTPClient(...)UseTestServer(...)SetAPIURL(...)SetLimiter(...)SetLimiterDrop(...)
These options are also what Bot wires internally during construction, so understanding them helps even if you mostly use the high-level bot runtime.
API behavior and responsibilities
tgapi.API handles:
- JSON request encoding;
- HTTP execution;
- internal worker-pool scheduling;
- optional rate limiting;
- Telegram
429 retry_afterbackoff and retry; - response decoding into typed results.
A few practical points matter:
NewAPIOpts(token)is the normal constructor entry point.- if you do not provide an HTTP client,
APIcreates one with a 45-second timeout. SetLimiter(...)connects autils.RateLimiter.SetLimiterDrop(true)switches from waiting mode to immediateErrDropOverflowbehavior when the limiter is full.Close()must be called to stop the worker pool and close idle connections.
Worker pool behavior
tgapi.API executes requests through an internal worker pool.
That means:
- even typed API calls go through a managed execution layer;
Close()is important because it stops that pool cleanly;- context-aware variants are the right choice when cancellation should interrupt waiting work.
This is one reason Close() is not optional in long-lived code.
Uploader behavior and responsibilities
tgapi.Uploader is the multipart companion to API.
Use it when Telegram expects an uploaded file body rather than a file_id or URL. The uploader reuses the underlying API client, including its HTTP client and limiter behavior.
Example:
api := tgapi.NewAPI(tgapi.NewAPIOpts(token))
defer api.Close()
uploader := tgapi.NewUploader(api)
defer uploader.Close()
photo := tgapi.NewUploaderFile("cat.jpg", data)
msg, err := uploader.SendPhoto(tgapi.UploadPhoto{
ChatID: chatID,
Caption: "Cat",
}, photo)
NewUploaderFile(name, data) auto-detects a Telegram upload field from the file extension. If needed, override it with SetType(...).
Call Uploader.Close() when you own a standalone uploader instance. When you use the uploader created by laniakea.Bot, bot.Close() handles that lifecycle for you.
Choosing between API and Uploader
Use API when:
- Telegram accepts JSON-only parameters;
- you are sending
file_idor URL references instead of new binary content.
Use Uploader when:
- Telegram expects multipart file upload;
- you are sending new binary content from memory or disk;
- the method has an
Upload*parameter type.
File downloads
tgapi also covers downloads from Telegram’s file server.
The usual flow is:
- call
GetFile(...)to obtain file metadata andFilePath; - download via one of the file-link helpers.
Use:
GetFileByLink(...)when you want the full file in memory as[]byte;OpenFileByLink(...)when you want a streamingio.ReadCloser.
Prefer the streaming helpers for large files so you do not buffer everything into memory at once.
Low-level request builders
The raw request builders exist as escape hatches, not as the recommended day-to-day API.
Available helpers:
NewRequest(...)NewRequestWithChatID(...)NewUploaderRequest(...)NewUploaderRequestWithChatID(...)
The WithChatID variants matter because chat ID is used for per-chat rate limiting.
Low-level escape hatches
For advanced cases, tgapi keeps raw request builders public:
tgapi.NewRequest(...)tgapi.NewRequestWithChatID(...)tgapi.NewUploaderRequest(...)tgapi.NewUploaderRequestWithChatID(...)
These are intentionally lower-level than the typed helpers.
Use them only when:
- the project has not added a typed wrapper for a Telegram method yet;
- you need a one-off method quickly and are comfortable supplying the exact method name;
- you can guarantee that the request and response types actually match Telegram’s schema.
Example:
req := tgapi.NewRequest[bool]("deleteWebhook", tgapi.DeleteWebhook{
DropPendingUpdates: true,
})
ok, err := req.Do(api)
The WithChatID variants matter when the request should participate in per-chat rate limiting.
Error model
At the tgapi layer, most failures come back as ordinary Go errors.
Examples:
- HTTP transport failures;
- JSON parsing failures;
- Telegram API errors formatted as
"[code] description"; - limiter-related failures such as drop-overflow mode;
- context cancellation and deadline errors from
WithContextvariants.
Telegram 429 retry_after is handled specially:
- the limiter lock is updated;
- the client waits;
- the request is retried automatically unless the context is canceled.
Related page:
Testability
tgapi is easy to test with a fake http.Client transport.
This is a strong pattern for:
- asserting JSON request bodies;
- simulating Telegram API responses;
- testing method wrappers without real network calls.
The repository already uses that style for both API and uploader-related tests.
Related page:
tgapi vs high-level Laniakea
As a rule of thumb:
- use
MessageContextwhen responding to the current update; - use
Botand plugins when structuring runtime behavior; - use
tgapiwhen you need direct Telegram method control; - use raw
NewRequestorNewUploaderRequestonly as the final fallback.
That boundary keeps normal bot code ergonomic without hiding Telegram-specific capabilities from advanced users.
Related pages
- Getting-Started for the normal high-level bot setup path.
- MessageContext for handler-time reply helpers.
- Inline-Keyboards-and-Payloads for callback button construction.
- Bot-Lifecycle for runtime startup and shutdown responsibilities around
Bot,API, andUploader. - Rate-Limiting for limiter and
retry_afterbehavior.
Navigation
Start here
Runtime and Architecture
- Bot-Lifecycle
- Webhook-Runtime
- Middleware
- Runners
- Error-Handling
- Logging
- Update-Routing-Model
- Policies
- Scenes
Interaction and Telegram API
- Inline-Keyboards-and-Payloads
- Auto-Generated-Commands
- Drafts
- Rich-Messages
- Localization
- Rate-Limiting
- tgapi-Overview