telegram-crawler/data/web/blogfork.telegram.org/api/offsets.html
2024-09-23 18:02:35 +00:00

175 lines
10 KiB
HTML

<!DOCTYPE html>
<html class="">
<head>
<meta charset="utf-8">
<title>Pagination in the API</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta property="description" content="How to fetch results from large lists of objects.">
<meta property="og:title" content="Pagination in the API">
<meta property="og:image" content="4dd378cd0f58b0b820">
<meta property="og:description" content="How to fetch results from large lists of objects.">
<link rel="icon" type="image/svg+xml" href="/img/website_icon.svg?4">
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
<link rel="alternate icon" href="/img/favicon.ico" type="image/x-icon" />
<link href="/css/bootstrap.min.css?3" rel="stylesheet">
<link href="/css/telegram.css?241" rel="stylesheet" media="screen">
<style>
</style>
</head>
<body class="preload">
<div class="dev_page_wrap">
<div class="dev_page_head navbar navbar-static-top navbar-tg">
<div class="navbar-inner">
<div class="container clearfix">
<ul class="nav navbar-nav navbar-right hidden-xs"><li class="navbar-twitter"><a href="https://twitter.com/telegram" target="_blank" data-track="Follow/Twitter" onclick="trackDlClick(this, event)"><i class="icon icon-twitter"></i><span> Twitter</span></a></li></ul>
<ul class="nav navbar-nav">
<li><a href="//telegram.org/">Home</a></li>
<li class="hidden-xs"><a href="//telegram.org/faq">FAQ</a></li>
<li class="hidden-xs"><a href="//telegram.org/apps">Apps</a></li>
<li class="active"><a href="/api">API</a></li>
<li class=""><a href="/mtproto">Protocol</a></li>
<li class=""><a href="/schema">Schema</a></li>
</ul>
</div>
</div>
</div>
<div class="container clearfix">
<div class="dev_page">
<div id="dev_page_content_wrap" class=" ">
<div class="dev_page_bread_crumbs"><ul class="breadcrumb clearfix"><li><a href="/api" >API</a></li><i class="icon icon-breadcrumb-divider"></i><li><a href="/api/offsets" >Pagination in the API</a></li></ul></div>
<h1 id="dev_page_title">Pagination in the API</h1>
<div id="dev_page_content"><!-- scroll_nav -->
<p>Lots of Telegram API methods provide access to potentially large lists of objects, which requires pagination.</p>
<p>In order to fetch only relevant subset of results for each request there is a number of available input parameters. Here is a list in order how they are applied in API.</p>
<p>Typically, results are returned in reverse chronological order with descending object ID values.</p>
<h3><a class="anchor" href="#limit-parameter" id="limit-parameter" name="limit-parameter"><i class="anchor-icon"></i></a><code>limit</code> parameter</h3>
<p>A limit on the number of objects to be returned, typically between 1 and 100. When 0 is provided the limit will often default to an intermediate value like ~20.</p>
<h3><a class="anchor" href="#offset-based-pagination" id="offset-based-pagination" name="offset-based-pagination"><i class="anchor-icon"></i></a><code>offset</code>-based pagination</h3>
<p>For a few methods with mostly static data this parameter allows to skip <code>offset</code> elements from the beginning of list; negative values are allowed in some cases.</p>
<h3><a class="anchor" href="#offset-id-based-pagination" id="offset-id-based-pagination" name="offset-id-based-pagination"><i class="anchor-icon"></i></a><code>offset_id</code>-based pagination</h3>
<p>For most methods where results are real-time data (e.g. any chat history) <code>offset</code> value is not passed directly. Instead it is calculated from the passed <code>offset_id</code> and <code>add_offset</code> parameter values as <code>offsetFromID(offset_id) + add_offset</code>, where <code>offsetFromID(offset_id)</code> is a number of results from the beginning of list up to the result with ID <code>offset_id</code>, inclusive.</p>
<p>Sample use cases:</p>
<ul>
<li>
<p>Loading 20 messages, older than message with ID <code>MSGID</code>:</p>
<p>messages.getHistory({offset_id: MSGID, add_offset: 0, limit: 20})</p>
</li>
<li>
<p>Loading 20 messages, newer than message with ID <code>MSGID</code>:</p>
<p>messages.getHistory({offset_id: MSGID, add_offset: -20, limit: 20})</p>
</li>
<li>
<p>Loading 20 messages around message with ID <code>MSGID</code>:</p>
<p>messages.getHistory({offset_id: MSGID, add_offset: -10, limit: 20})</p>
</li>
</ul>
<h3><a class="anchor" href="#additional-filtering" id="additional-filtering" name="additional-filtering"><i class="anchor-icon"></i></a>Additional filtering</h3>
<p>There is a number of parameters, which are applied to the list after slicing with offset and limit, to reduce the result subset even more:</p>
<ul>
<li><strong>max_id</strong>: Can be used to only return results with ID strictly smaller than <code>max_id</code> (e.g. message ID)</li>
<li><strong>min_id</strong>: Can be used to only return results with ID strictly greater than <code>min_id</code>(e.g. message ID)</li>
<li><strong>max_date</strong>: Can be used to only return results that are older than <code>max_date</code>:</li>
<li><strong>min_date</strong>: Can be used to only return results with are newer than <code>min_date</code>:</li>
<li><strong>hash</strong>: See below.</li>
</ul>
<h3><a class="anchor" href="#hash-generation" id="hash-generation" name="hash-generation"><i class="anchor-icon"></i></a>Hash generation</h3>
<p>To further reduce the result subset, there is a mechanism to avoid fetching data if the resulting list hasn't changed from the one stored on client, similar to <a href="https://en.wikipedia.org/wiki/HTTP_ETag">ETag</a>.</p>
<p>When the client has cached results for API request, it can calculate the <code>hash</code> value for it by taking the result IDs (message IDs or other fields with name <code>id</code>, or some extra fields in some cases) and using them to compute a 64-bit hash with the following algorithm:</p>
<pre><code># Here, ^ indicates a bitwise XOR
hash = 0
for id in ids:
hash = hash ^ (hash &gt;&gt; 21)
hash = hash ^ (hash &lt;&lt; 35)
hash = hash ^ (hash &gt;&gt; 4)
hash = hash + id</code></pre>
<p>The <code>&gt;&gt;</code> operator is the unsigned right shift operator. </p>
<p>Note: in some cases, the <code>ids</code> array passed to the algorithm must contain strings (i.e. the shortcut name in business shortcuts, and so on...), in which case they must be transformed to longs by taking the first 8 bytes of the MD5 hash of the string (<strong>not</strong> in hex form) and treating it as a big-endian 64-bit long. </p>
<p>In some cases, if the result container already has a <code>hash</code> field, that can be used instead. </p>
<p>When the client passes a correct value, the API will return one of <code>*NotModified</code> constructors, e.g. <a href="/constructor/messages.messagesNotModified">messages.messagesNotModified</a> instead of the actual results.</p>
<h3><a class="anchor" href="#example-methods" id="example-methods" name="example-methods"><i class="anchor-icon"></i></a>Example methods</h3>
<ul>
<li><a href="/method/messages.getHistory">messages.getHistory</a> supports all result navigation parameters including message ID hashes and except filters</li>
<li><a href="/method/channels.getParticipants">channels.getParticipants</a> supports simple navigation using <strong>limit</strong> and <strong>offset</strong>, along with filtering and <code>hash</code> reducing using the user IDs of returned participants</li>
</ul></div>
</div>
</div>
</div>
<div class="footer_wrap">
<div class="footer_columns_wrap footer_desktop">
<div class="footer_column footer_column_telegram">
<h5>Telegram</h5>
<div class="footer_telegram_description"></div>
Telegram is a cloud-based mobile and desktop messaging app with a focus on security and speed.
</div>
<div class="footer_column">
<h5><a href="//telegram.org/faq">About</a></h5>
<ul>
<li><a href="//telegram.org/faq">FAQ</a></li>
<li><a href="//telegram.org/privacy">Privacy</a></li>
<li><a href="//telegram.org/press">Press</a></li>
</ul>
</div>
<div class="footer_column">
<h5><a href="//telegram.org/apps#mobile-apps">Mobile Apps</a></h5>
<ul>
<li><a href="//telegram.org/dl/ios">iPhone/iPad</a></li>
<li><a href="//telegram.org/android">Android</a></li>
<li><a href="//telegram.org/dl/web">Mobile Web</a></li>
</ul>
</div>
<div class="footer_column">
<h5><a href="//telegram.org/apps#desktop-apps">Desktop Apps</a></h5>
<ul>
<li><a href="//desktop.telegram.org/">PC/Mac/Linux</a></li>
<li><a href="//macos.telegram.org/">macOS</a></li>
<li><a href="//telegram.org/dl/web">Web-browser</a></li>
</ul>
</div>
<div class="footer_column footer_column_platform">
<h5><a href="/">Platform</a></h5>
<ul>
<li><a href="/api">API</a></li>
<li><a href="//translations.telegram.org/">Translations</a></li>
<li><a href="//instantview.telegram.org/">Instant View</a></li>
</ul>
</div>
</div>
<div class="footer_columns_wrap footer_mobile">
<div class="footer_column">
<h5><a href="//telegram.org/faq">About</a></h5>
</div>
<div class="footer_column">
<h5><a href="//telegram.org/blog">Blog</a></h5>
</div>
<div class="footer_column">
<h5><a href="//telegram.org/apps">Apps</a></h5>
</div>
<div class="footer_column">
<h5><a href="/">Platform</a></h5>
</div>
<div class="footer_column">
<h5><a href="//telegram.org/press">Press</a></h5>
</div>
</div>
</div>
</div>
<script src="/js/main.js?47"></script>
<script src="/js/jquery.min.js?1"></script>
<script src="/js/bootstrap.min.js?1"></script>
<script>window.initDevPageNav&&initDevPageNav();
backToTopInit("Go up");
removePreloadInit();
</script>
</body>
</html>