The short answer
- 1History is fetched relative to a reference message: offset_id, add_offset and limit.
- 2add_offset 0 for older, minus limit for newer, minus half for around.
- 3Send hash for frequent lists; unchanged lists return NotModified.
In this article
History is fetched around a reference message
Chat history (messages.getHistory and similar) is never fetched all at once; it comes in batches. Instead of page numbers, you give the ID of a reference message and how far from it to start. Results usually come newest first, with the highest IDs first.
| Field | Meaning |
|---|---|
offset_id | The reference message's ID |
add_offset | How many messages away from the reference to start; negative means towards newer messages |
limit | How many to fetch this time |
max_id / min_id | Exclude messages above / below this ID (the boundary ID itself is excluded too) |
Three shapes you will use most
| Goal | offset_id | add_offset | limit |
|---|---|---|---|
| 20 messages older than the reference | Reference ID | 0 | 20 |
| 20 messages newer than the reference | Reference ID | -20 | 20 |
| 20 messages around the reference | Reference ID | -10 | 20 |
The count of 20 is just an example. When the user scrolls up, use the message at the top of the screen as the reference and fetch older ones; scrolling down, use the bottom message and fetch newer ones. Jumping to a message from search results calls for the "around" shape.
hash: skip the download when nothing changed
Lists your app asks for again and again, such as the chat list, sticker sets and contacts, have a hash field. Send a value computed from the list you already have, and if nothing has changed, the server returns only a "not modified" answer (a response whose name ends in NotModified) instead of the contents. It is the same idea as an ETag on the web.
- The hash is computed from the IDs in the results you hold. The formula is defined in the official documentation; follow it exactly (string values go in as the first part of their MD5 converted to a 64-bit number).
- Send 0 the first time, or when you have nothing stored.
- On "not modified", keep using your stored list.
Not fetching everything every time also means you hit rate limits (FLOOD_WAIT) less often; see reading API errors.
What TDLib does for you
TDLib stores message history in a database on the device and does these calculations for you; your app only asks for "this many messages from here". See building TDLib. New incoming messages arrive as updates, not by fetching history again; see handling updates.
FAQ
How do I load older messages in the Telegram API?
Call messages.getHistory with offset_id set to the oldest message you have, add_offset 0 and a limit.
What does add_offset do?
It moves the starting point away from offset_id; negative values move towards newer messages.
What is the hash field for?
It lets the server answer NotModified when your stored list is still current, saving requests.
Sources
At a glance
- 1Offsets
offset_id is the anchor; add_offset moves the window.
- 2Shapes
0 older, -20 newer, -10 around for a limit of 20.
- 3hash
0 first time; NotModified means reuse what you have.
Updated