ZT zig-telegram v0.1.0 · Zig 0.17.0
SPECIFICATION LOCK: TELEGRAM BOT API 10.3 (2026-08-24) · MTPROTO 2.0 RFC · ZERO LIBC

Precision-Engineered Telegram Stack for Zig 0.17.

zig-telegram unifies three protocol planes in one zero-dependency Zig package: 100% deterministic codegen for Bot API 10.3 (all 185 methods & 400 types/unions), a pure-Zig MTProto 2.0 binary/cryptographic core (TL codec, AES-256-IGE, SHA-256 msg_key, Obfuscated2 framing), and an optional runtime-loaded TDLib tdjson bridge.

185 / 185
Bot API 10.3 Methods
400
Typed Structs & Unions
979 MiB/s
MTProto AES-256-IGE
0 C Deps
Pure std.http + std.crypto
echo_bot.zig — Zig 0.17.0
const std = @import("std");
const telegram = @import("telegram");

pub fn main(init: std.process.Init) !void {
    var http: telegram.transport.HttpTransport = .init(init.gpa, init.io);
    defer http.deinit();

    const token = try telegram.SecretToken.initValidated("123456:ABC-DEF");
    var client = telegram.bot.BotClient.init(
        init.gpa, init.io, token, http.transport(), .{},
    );

    var detail: ?telegram.ErrorDetail = null;
    defer if (detail) |*d| d.deinit(init.gpa);

    var msg = try client.sendMessage(.{
        .chat_id = .fromInt(42),
        .text = "Hello from zig-telegram (Bot API 10.3)!",
        .parse_mode = .MarkdownV2,
    }, &detail);
    defer msg.deinit();
}
01 // THREE-PLANE ARCHITECTURE

One Module. Three Protocol Planes. Zero Hidden State.

Every network call, allocator, and error diagnostic is explicit. Choose high-level Bot API 10.3 ergonomics, low-level MTProto 2.0 binary framing, or dynamic TDLib JSON bindings.

PLANE 1 · telegram.bot Bot API 10.3 Complete • 185 Methods + 400 Types (codegen) • Recursive attach:// Multipart Engine • Single-Pass Discriminated Unions • Poller (429 Retry-After) + Webhook • Comptime Command & Update Router → Persistent std.http.Client TLS 1.3 PLANE 2 · telegram.mtproto Pure-Zig MTProto 2.0 Core • TL Binary Reader / Writer (4B align) • AES-256-IGE + SHA-256 msg_key KDF • Brent-Pollard Rho pq Factorization • Abridged / Intermediate / Obfuscated2 • Monotonic 64-bit msg_id & seq_no → Zero OpenSSL / Zero C Dependencies PLANE 3 · telegram.tdlib Optional TDLib tdjson Bridge • Dynamic std.DynLib Loader • Zero Link-Time C/C++ Requirement • Mockable C ABI Vtable for Testing • create / send / receive / execute • Linux .so / macOS .dylib / Win .dll → Opt-In Only When Needed
PLANE 01 // BOT API 10.3

Recursive attach:// Multipart

Existing Zig libraries only inspect top-level method fields for InputFile, silently breaking sendMediaGroup, sendPaidMedia, and editMessageMedia.

  • Walks structs, optionals, slices, and unions
  • Emits "attach://part_<n>" in JSON automatically
  • Streams binary parts with CSPRNG 128-bit boundaries
  • RFC 7578 filename quote/CRLF escaping
PLANE 02 // SECURITY & RELIABILITY

SecretToken & Caller-Owned Errors

Bot tokens never leak in logs or stack traces, and concurrent threads never race on a shared mutable last_error struct field.

  • SecretToken.format prints bot<id>:[REDACTED]
  • Constant-time SHA-256 webhook header verification
  • Explicit err_out: ?*?ErrorDetail with retry_after
  • Automatic --local Bot API server path remapping
PLANE 03 // MTPROTO 2.0

Pure-Zig Cryptography & Framing

Full MTProto 2.0 binary packet codec built exclusively on Zig's standard library primitives.

  • AES-256-IGE mode on top of std.crypto.core.aes.Aes256
  • MTProto 2.0 SHA-256 msg_key & AES key/IV derivation
  • Abridged, Intermediate, Padded & Obfuscated2 framing
  • 64-bit time-synchronized monotonic msg_id generator
02 // ECOSYSTEM COMPARISON

Why zig-telegram Replaces First-Gen Zig Wrappers

Audited against zigtgshka, ziogram, and telebot.zig across specification coverage, multipart correctness, TLS connection reuse, and memory safety.

Capability zig-telegram (0.17.0) zigtgshka ziogram telebot.zig
Telegram Bot API Spec 10.3 (185 methods / 400 types) 9.2 (161 methods) 7.10 partial ~30 manual methods
Nested attach:// Multipart (sendMediaGroup) Recursive comptime + runtime Top-level fields only None libcurl C FFI
Discriminated Unions (23 unions + RichText) Single-pass zero-DOM scanner 2-pass DOM allocation Incomplete Manual structs
HTTP Transport & TLS 1.3 Keep-Alive Persistent pooled std.http.Client New client per request New client per request Requires C libcurl
Error Diagnostics (retry_after, migrate_to_chat_id) Caller-owned ?*?ErrorDetail Discarded on error Thread-unsafe struct field Status code only
Webhook Constant-Time Secret Verification SHA-256 + timing_safe.eql Not included Not included Not included
Pure-Zig MTProto 2.0 Core (TL + AES-256-IGE) Included (telegram.mtproto) No No No
03 // USAGE & CODE EXAMPLES

Copy-Ready Zig 0.17 Snippets

Add zig-telegram with zig fetch --save git+https://github.com/guanchzhou/zig-telegram and import @import("telegram").

examples/echo_bot.zigBotClient + Router + Poller
const std = @import("std");
const telegram = @import("telegram");

const AppCtx = struct {
    client: *telegram.bot.BotClient,
    pub fn onStart(self: *@This(), msg: telegram.bot.types.Message, args: []const u8) !void {
        _ = args;
        var r = try self.client.sendMessage(.{
            .chat_id = .fromInt(msg.chat.id),
            .text = "Welcome to zig-telegram!",
        }, null);
        r.deinit();
    }
};

const AppRouter = telegram.bot.Router(*AppCtx, .{
    .commands = &.{.{ .name = "start", .handler = AppCtx.onStart }},
});
examples/media_group.zigRecursive attach:// Multipart Streaming
const media_items = [_]telegram.bot.types.InputMedia{
    .{ .photo = .{
        .media = .fromBytes("diagram.png", png_bytes),
        .caption = "Uploaded via attach://part_0",
    } },
    .{ .document = .{
        .media = .fromPath("./spec/bot_api_10_3.json"),
        .thumbnail = .fromBytes("thumb.jpg", jpg_bytes),
    } },
};

var sent = try client.sendMediaGroup(.{
    .chat_id = .fromChannel("@zig_announcements"),
    .media = &media_items,
}, null);
defer sent.deinit();
examples/webhook_bot.zigConstant-Time X-Telegram-Bot-Api-Secret-Token Verification
var processor: telegram.bot.WebhookProcessor = .{
    .expected_secret_token = "whsec_super_secret_token_2026",
};

var update = try processor.verifyAndParseUpdate(
    allocator,
    headers,
    request_body,
);
defer update.deinit();
examples/mtproto_frame.zigPure-Zig MTProto 2.0 Session + Intermediate Framing
var session = telegram.mtproto.session.Session.init(
    auth_key,
    0x0102030405060708,
    0x1122334455667788,
);

const encrypted = try session.encryptPacket(
    allocator,
    tl_payload,
    unix_time_sec,
    true,
    .client_to_server,
    random_pad,
);
defer allocator.free(encrypted.packet);
zig-telegram CLIZero-Dependency Terminal Utility
$ zig build run -- spec
Telegram Bot API 10.3 (August 24, 2026) — 185 methods

$ zig build run -- mtproto
MTProto 2.0 Self-Test: OK (auth_key_id=0x..., msg_id=0x..., packet=64 bytes, factorizePq(0x17ED48941A08F981)=0x494C553B * 0x53911073)

$ TELEGRAM_BOT_TOKEN="123456:ABC-DEF" zig build run -- send --chat 42 --text "Deployed!"
04 // INTERACTIVE BOT API 10.3 CATALOG

Explore All 185 Generated BotClient Methods

Filter every method generated from spec/bot_api_10_3.json. Each method is available on telegram.bot.BotClient with strongly-typed parameters in telegram.bot.methods.

05 // RELEASEFAST TELEMETRY

Measured Performance on Apple Silicon (Zig 0.17.0 ReleaseFast)

Reproduce locally with zig build bench and enforce the regression gate in CI via zig build perf-check.

Discriminated Union JSON Decode (ChatMember)

Zero-allocation top-level tag scanner vs 2-pass std.json.Value DOM tree allocation.

zig-telegram Single-Pass Scanner740 ns/op (1.17x faster)
2-Pass std.json.Value DOM863 ns/op

Protocol & Cryptographic Throughput

Pure-Zig MTProto 2.0 AES-256-IGE packet encryption and constant-time SHA-256 webhook verification.

MTProto 2.0 AES-256-IGE (1 KiB packet)979.2 MiB/s
Full Update JSON Envelope Parse1,696 ns/op
Webhook SHA-256 Constant-Time Verify34 ns/op