Welcome to Twibooru! Anonymous posting only; no content restrictions beyond pony-related and legal; comments are disabled by default (Settings -> Comments). Read me!

Revision history for API

UserDateBody
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There is currently only one specific library that has been written for the Twibooru API. You may be able to adapt some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/AppleDash/philomena4j">Philomena4J (COMING SOON) - By Floorb, supports Twibooru natively (Java).</a></li> </ul> <h2>Routes</h2> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/featured"><code>/api/v3/posts/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id/comments</code></td> <td></td> <td>Fetches a list of <em>comment responses</em> representing all comments on the post referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"comments":[<a href="#comment-response">comment-response</a>]}</code></td> <td><a href="/api/v3/posts/1/comments"><code>/api/v3/posts/1/comments</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>post responses</em>.</td> <td><code>{"posts":[<a href="#post-response">post-response</a>]}</code></td> <td><a href="/api/v3/search/posts?q=safe"><code>/api/v3/search/posts?q=safe</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/tags</code></td> <td><code>page, per_page, q</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>tag responses</em>, sorted by descending image count.</td> <td><code>{"tags":[<a href="#tag-response">tag-response</a>]}</code></td> <td><a href="/api/v3/search/tags?q=*wing*"><code>/api/v3/search/tags?q=*wing*</code></a></td> </tr> </tbody> </table> <h2 id="post-response">Post Responses</h2> <p>These fields are present on all posts (unless otherwise noted), whether they have been hidden or not.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the post.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the post, or <code>null</code> if none provided. This will only be present on posts which have been deleted for a rule violation.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target post this post has been merged into. This will only be present on posts which have been merged into another post.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the post is hidden. A post is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The post's ID.</td> </tr> <tr> <td><code>locations</code></td> <td>Array&lt;Object&gt;</td> <td>Array of <a href="#locations-object">location objects</a>, providing information about other websites this image may be found on.</td> </tr> <tr> <td><code>media_type</code></td> <td>String</td> <td>The type of media associated with this post. One of <code>"paste", "image"</code>.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the post as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the post has finished background processing.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this post after it has been processed.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the post contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the post contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was last updated.</td> </tr> </tbody> </table> <h3>Non-hidden Post Responses</h3> <p>For posts which are not hidden (ie: most posts), the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments the post has.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The post's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the post has.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of favourites the post has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The post's score - usually the number of upvotes minus the number of downvotes.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the post's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The post's number of upvotes.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the post, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For non-hidden posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="#intensities-object">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="tag-response">Tag Responses</h2> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>aliased_tag</code></td> <td>String</td> <td>The name of the tag this tag is aliased to, if any.</td> </tr> <tr> <td><code>aliases</code></td> <td>Array</td> <td>The names of the tags aliased to this tag.</td> </tr> <tr> <td><code>category</code></td> <td>String</td> <td>The category class of this tag. One of <code>"character", "content-fanmade", "content-official", "error", "oc", "origin", "rating", "species", "spoiler"</code>.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The long description for the tag.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The tag's ID.</td> </tr> <tr> <td><code>images</code></td> <td>Integer</td> <td>The post count of the tag.</td> </tr> <tr> <td><code>implied_by_tags</code></td> <td>Array</td> <td>The names of the tags this tag is implied by.</td> </tr> <tr> <td><code>implied_tags</code></td> <td>Array</td> <td>The names of the tags this tag implies.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The name of the tag.</td> </tr> <tr> <td><code>name_in_namespace</code></td> <td>String</td> <td>The name of the tag in its namespace.</td> </tr> <tr> <td><code>namespace</code></td> <td>String</td> <td>The namespace of the tag.</td> </tr> <tr> <td><code>short_description</code></td> <td>String</td> <td>The short description for the tag.</td> </tr> <tr> <td><code>slug</code></td> <td>String</td> <td>The slug for the tag.</td> </tr> </tbody> </table> <h2 id="intensities-object">Intensities Objects</h2> <p>Meaning can be given to these fields by understanting the <a href="https://github.com/Twibooru/image_intensities">source code</a>. Please note that these values are <strong>NOT</strong> compatible with the values generated by the newer <code>cli_intensities</code> tool, which is used by Philomena.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>nw</code></td> <td>Float</td> <td>The north-west intensity of the image.</td> </tr> <tr> <td><code>ne</code></td> <td>Float</td> <td>The north-east intensity of the image.</td> </tr> <tr> <td><code>sw</code></td> <td>Float</td> <td>The south-west intensity of the image.</td> </tr> <tr> <td><code>se</code></td> <td>Float</td> <td>The south-east intensity of the image.</td> </tr> </tbody> </table> <h2 id="locations-object">Location Objects</h2> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>id_at_location</code></td> <td>Integer</td> <td>The identifier, specific to the site named in <code>location</code>, associated with this post's equivalent on the other site.</td> </tr> <tr> <td><code>location</code></td> <td>String</td> <td>Name of site that this location describes. May be one of <code>derpibooru, ponybooru, rainbooru, ponerpics, foalcon, lyrabooru, manebooru</code>. Currently only <code>derpibooru</code> is returned.</td> </tr> <tr> <td><code>url_at_location</code></td> <td>String</td> <td>A URL to the human-readable page at which this post can be found at the described location.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/search/tags</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>Errors</h2> <p>The API may return various HTTP error codes, either due to server or client error. When an error code is returned, the server will respond with a JSON payload containing an <code>error</code> key with a string value, textually describing the error that occured.</p> <table class="table"> <thead> <tr> <th>Error Code</th> <th>Description</th> <th>Resolution</th> </tr> </thead> <tbody> <tr> <td>401 Unauthorized</td> <td>You attempted to retrieve a resource you are not authorized to retrieve.</td> <td>Ensure you have provided appropriate credentials.</td> </tr> <tr> <td>404 Not Found</td> <td>You attempted to retrieve a resource that does not exist.</td> <td>Only attempt to retrieve resources that exist.</td> </tr> <tr> <td>422 Unprocessable Entity</td> <td>A query was sent to the server in an invalid format (eg: imbalanced parentheses in search term.)</td> <td>Format the query correctly.</td> </tr> <tr> <td>429 Too Many Requests</td> <td>Too many queries were sent to the server in too short of a time.</td> <td>Wait some time and re-try the request. Utilize the <a href="#rate-limits">rate limit headers</a> to avoid encountering this error.</td> </tr> <tr> <td>500 Internal Server Error</td> <td>An unknown server-side error occured while processing your request.</td> <td>Contact a site administrator for help.</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There is currently only one specific library that has been written for the Twibooru API. You may be able to adapt some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/AppleDash/philomena4j">Philomena4J (COMING SOON) - By Floorb, supports Twibooru natively (Java).</a></li> </ul> <h2>Routes</h2> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/featured"><code>/api/v3/posts/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id/comments</code></td> <td></td> <td>Fetches a list of <em>comment responses</em> representing all comments on the post referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"comments":[<a href="#comment-response">comment-response</a>]}</code></td> <td><a href="/api/v3/posts/1/comments"><code>/api/v3/posts/1/comments</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>post responses</em>.</td> <td><code>{"posts":[<a href="#post-response">post-response</a>]}</code></td> <td><a href="/api/v3/search/posts?q=safe"><code>/api/v3/search/posts?q=safe</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/tags</code></td> <td><code>page, per_page, q</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>tag responses</em>, sorted by descending image count.</td> <td><code>{"tags":[<a href="#tag-response">tag-response</a>]}</code></td> <td><a href="/api/v3/search/tags?q=*wing*"><code>/api/v3/search/tags?q=*wing*</code></a></td> </tr> </tbody> </table> <h2 id="post-response">Post Responses</h2> <p>These fields are present on all posts (unless otherwise noted), whether they have been hidden or not.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the post.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the post, or <code>null</code> if none provided. This will only be present on posts which have been deleted for a rule violation.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target post this post has been merged into. This will only be present on posts which have been merged into another post.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the post is hidden. A post is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The post's ID.</td> </tr> <tr> <td><code>locations</code></td> <td>Array&lt;Object&gt;</td> <td>Array of <a href="#locations-object">location objects</a>, providing information about other websites this image may be found on.</td> </tr> <tr> <td><code>media_type</code></td> <td>String</td> <td>The type of media associated with this post. One of <code>"paste", "image"</code>.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the post as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the post has finished background processing.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this post after it has been processed.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the post contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the post contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was last updated.</td> </tr> </tbody> </table> <h3>Non-hidden Post Responses</h3> <p>For posts which are not hidden (ie: most posts), the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments the post has.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The post's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the post has.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of favourites the post has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The post's score - usually the number of upvotes minus the number of downvotes.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the post's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The post's number of upvotes.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the post, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For non-hidden posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="https://github.com/twibooru/image_intensities">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> <td>Optional object of <a href="#intensities-object">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="tag-response">Tag Responses</h2> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>aliased_tag</code></td> <td>String</td> <td>The name of the tag this tag is aliased to, if any.</td> </tr> <tr> <td><code>aliases</code></td> <td>Array</td> <td>The names of the tags aliased to this tag.</td> </tr> <tr> <td><code>category</code></td> <td>String</td> <td>The category class of this tag. One of <code>"character", "content-fanmade", "content-official", "error", "oc", "origin", "rating", "species", "spoiler"</code>.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The long description for the tag.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The tag's ID.</td> </tr> <tr> <td><code>images</code></td> <td>Integer</td> <td>The post count of the tag.</td> </tr> <tr> <td><code>implied_by_tags</code></td> <td>Array</td> <td>The names of the tags this tag is implied by.</td> </tr> <tr> <td><code>implied_tags</code></td> <td>Array</td> <td>The names of the tags this tag implies.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The name of the tag.</td> </tr> <tr> <td><code>name_in_namespace</code></td> <td>String</td> <td>The name of the tag in its namespace.</td> </tr> <tr> <td><code>namespace</code></td> <td>String</td> <td>The namespace of the tag.</td> </tr> <tr> <td><code>short_description</code></td> <td>String</td> <td>The short description for the tag.</td> </tr> <tr> <td><code>slug</code></td> <td>String</td> <td>The slug for the tag.</td> </tr> </tbody> </table> <h2 id="intensities-object">Intensities Objects</h2> <p>Meaning can be given to these fields by understanting the <a href="https://github.com/Twibooru/image_intensities">source code</a>. Please note that these values are <strong>NOT</strong> compatible with the values generated by the newer <code>cli_intensities</code> tool, which is used by Philomena.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>nw</code></td> <td>Float</td> <td>The north-west intensity of the image.</td> </tr> <tr> <td><code>ne</code></td> <td>Float</td> <td>The north-east intensity of the image.</td> </tr> <tr> <td><code>sw</code></td> <td>Float</td> <td>The south-west intensity of the image.</td> </tr> <tr> <td><code>se</code></td> <td>Float</td> <td>The south-east intensity of the image.</td> </tr> </tbody> </table> <h2 id="locations-object">Location Objects</h2> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>id_at_location</code></td> <td>Integer</td> <td>The identifier, specific to the site named in <code>location</code>, associated with this post's equivalent on the other site.</td> </tr> <tr> <td><code>location</code></td> <td>String</td> <td>Name of site that this location describes. May be one of <code>derpibooru, ponybooru, rainbooru, ponerpics, foalcon, lyrabooru, manebooru</code>. Currently only <code>derpibooru</code> is returned.</td> </tr> <tr> <td><code>url_at_location</code></td> <td>String</td> <td>A URL to the human-readable page at which this post can be found at the described location.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/search/tags</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>Errors</h2> <p>The API may return various HTTP error codes, either due to server or client error. When an error code is returned, the server will respond with a JSON payload containing an <code>error</code> key with a string value, textually describing the error that occured.</p> <table class="table"> <thead> <tr> <th>Error Code</th> <th>Description</th> <th>Resolution</th> </tr> </thead> <tbody> <tr> <td>401 Unauthorized</td> <td>You attempted to retrieve a resource you are not authorized to retrieve.</td> <td>Ensure you have provided appropriate credentials.</td> </tr> <tr> <td>404 Not Found</td> <td>You attempted to retrieve a resource that does not exist.</td> <td>Only attempt to retrieve resources that exist.</td> </tr> <tr> <td>422 Unprocessable Entity</td> <td>A query was sent to the server in an invalid format (eg: imbalanced parentheses in search term.)</td> <td>Format the query correctly.</td> </tr> <tr> <td>429 Too Many Requests</td> <td>Too many queries were sent to the server in too short of a time.</td> <td>Wait some time and re-try the request. Utilize the <a href="#rate-limits">rate limit headers</a> to avoid encountering this error.</td> </tr> <tr> <td>500 Internal Server Error</td> <td>An unknown server-side error occured while processing your request.</td> <td>Contact a site administrator for help.</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There is currently only one specific library that has been written for the Twibooru API. You may be able to adapt some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/AppleDash/philomena4j">Philomena4J (COMING SOON) - By Floorb, supports Twibooru natively (Java).</a></li> </ul> <h2>Routes</h2> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/featured"><code>/api/v3/posts/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id/comments</code></td> <td></td> <td>Fetches a list of <em>comment responses</em> representing all comments on the post referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"comments":[<a href="#comment-response">comment-response</a>]}</code></td> <td><a href="/api/v3/posts/1/comments"><code>/api/v3/posts/1/comments</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>post responses</em>.</td> <td><code>{"posts":[<a href="#post-response">post-response</a>]}</code></td> <td><a href="/api/v3/search/posts?q=safe"><code>/api/v3/search/posts?q=safe</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/tags</code></td> <td><code>page, per_page, q</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>tag responses</em>, sorted by descending image count.</td> <td><code>{"tags":[<a href="#tag-response">tag-response</a>]}</code></td> <td><a href="/api/v3/search/tags?q=*wing*"><code>/api/v3/search/tags?q=*wing*</code></a></td> </tr> </tbody> </table> <h2 id="post-response">Post Responses</h2> <p>These fields are present on all posts (unless otherwise noted), whether they have been hidden or not.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the post.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the post, or <code>null</code> if none provided. This will only be present on posts which have been deleted for a rule violation.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target post this post has been merged into. This will only be present on posts which have been merged into another post.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the post is hidden. A post is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The post's ID.</td> </tr> <tr> <td><code>media_type</code></td> <td>String</td> <td>The type of media associated with this post. One of <code>"paste", "image"</code>.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the post as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the post has finished background processing.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this post after it has been processed.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the post contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the post contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was last updated.</td> </tr> </tbody> </table> <h3>Non-hidden Post Responses</h3> <p>For posts which are not hidden (ie: most posts), the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments the post has.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The post's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the post has.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of favourites the post has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The post's score - usually the number of upvotes minus the number of downvotes.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the post's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The post's number of upvotes.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the post, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For non-hidden posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="https://github.com/twibooru/image_intensities">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="tag-response">Tag Responses</h2> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>aliased_tag</code></td> <td>String</td> <td>The name of the tag this tag is aliased to, if any.</td> </tr> <tr> <td><code>aliases</code></td> <td>Array</td> <td>The names of the tags aliased to this tag.</td> </tr> <tr> <td><code>category</code></td> <td>String</td> <td>The category class of this tag. One of <code>"character", "content-fanmade", "content-official", "error", "oc", "origin", "rating", "species", "spoiler"</code>.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The long description for the tag.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The tag's ID.</td> </tr> <tr> <td><code>images</code></td> <td>Integer</td> <td>The post count of the tag.</td> </tr> <tr> <td><code>implied_by_tags</code></td> <td>Array</td> <td>The names of the tags this tag is implied by.</td> </tr> <tr> <td><code>implied_tags</code></td> <td>Array</td> <td>The names of the tags this tag implies.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The name of the tag.</td> </tr> <tr> <td><code>name_in_namespace</code></td> <td>String</td> <td>The name of the tag in its namespace.</td> </tr> <tr> <td><code>namespace</code></td> <td>String</td> <td>The namespace of the tag.</td> </tr> <tr> <td><code>short_description</code></td> <td>String</td> <td>The short description for the tag.</td> </tr> <tr> <td><code>slug</code></td> <td>String</td> <td>The slug for the tag.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/search/tags</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>Errors</h2> <p>The API may return various HTTP error codes, either due to server or client error. When an error code is returned, the server will respond with a JSON payload containing an <code>error</code> key with a string value, textually describing the error that occured.</p> <table class="table"> <thead> <tr> <th>Error Code</th> <th>Description</th> <th>Resolution</th> </tr> </thead> <tbody> <tr> <td>401 Unauthorized</td> <td>You attempted to retrieve a resource you are not authorized to retrieve.</td> <td>Ensure you have provided appropriate credentials.</td> </tr> <tr> <td>404 Not Found</td> <td>You attempted to retrieve a resource that does not exist.</td> <td>Only attempt to retrieve resources that exist.</td> </tr> <tr> <td>422 Unprocessable Entity</td> <td>A query was sent to the server in an invalid format (eg: imbalanced parentheses in search term.)</td> <td>Format the query correctly.</td> </tr> <tr> <td>429 Too Many Requests</td> <td>Too many queries were sent to the server in too short of a time.</td> <td>Wait some time and re-try the request. Utilize the <a href="#rate-limits">rate limit headers</a> to avoid encountering this error.</td> </tr> <tr> <td>500 Internal Server Error</td> <td>An unknown server-side error occured while processing your request.</td> <td>Contact a site administrator for help.</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There is currently only one specific library that has been written for the Twibooru API. You may be able to adapt some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/AppleDash/philomena4j">Philomena4J (COMING SOON) - By Floorb, supports Twibooru natively (Java).</a></li> </ul> <h2>Routes</h2> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> <td><a href="/api/v3/posts/featured"><code>/api/v3/posts/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id/comments</code></td> <td></td> <td>Fetches a list of <em>comment responses</em> representing all comments on the post referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"comments":[<a href="#comment-response">comment-response</a>]}</code></td> <td><a href="/api/v3/posts/1/comments"><code>/api/v3/posts/1/comments</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>post responses</em>.</td> <td><code>{"posts":[<a href="#post-response">post-response</a>]}</code></td> <td><a href="/api/v3/search/posts?q=safe"><code>/api/v3/search/posts?q=safe</code></a></td> </tr> </tbody> </table> <h2 id="post-response">Post Responses</h2> <p>These fields are present on all posts (unless otherwise noted), whether they have been hidden or not.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the post.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the post, or <code>null</code> if none provided. This will only be present on posts which have been deleted for a rule violation.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target post this post has been merged into. This will only be present on posts which have been merged into another post.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the post is hidden. A post is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The post's ID.</td> </tr> <tr> <td><code>media_type</code></td> <td>String</td> <td>The type of media associated with this post. One of <code>"paste", "image"</code>.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the post as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the post has finished background processing.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this post after it has been processed.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the post contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the post contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was last updated.</td> </tr> </tbody> </table> <h3>Non-hidden Post Responses</h3> <p>For posts which are not hidden (ie: most posts), the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments the post has.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The post's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the post has.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of favourites the post has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The post's score - usually the number of upvotes minus the number of downvotes.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the post's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The post's number of upvotes.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the post, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For non-hidden posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="https://github.com/twibooru/image_intensities">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There is currently only one specific library that has been written for the Twibooru API. You may be able to adapt some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/AppleDash/philomena4j">Philomena4J - By Floorb, supports Twibooru natively (Java).</a></li> <li><a href="https://github.com/AppleDash/philomena4j">Philomena4J (COMING SOON) - By Floorb, supports Twibooru natively (Java).</a></li> </ul> <h2>Routes</h2> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id/comments</code></td> <td></td> <td>Fetches a list of <em>comment responses</em> representing all comments on the post referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"comments":[<a href="#comment-response">comment-response</a>]}</code></td> <td><a href="/api/v3/posts/1/comments"><code>/api/v3/posts/1/comments</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>post responses</em>.</td> <td><code>{"posts":[<a href="#post-response">post-response</a>]}</code></td> <td><a href="/api/v3/search/posts?q=safe"><code>/api/v3/search/posts?q=safe</code></a></td> </tr> </tbody> </table> <h2 id="post-response">Post Responses</h2> <p>These fields are present on all posts (unless otherwise noted), whether they have been hidden or not.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the post.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the post, or <code>null</code> if none provided. This will only be present on posts which have been deleted for a rule violation.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target post this post has been merged into. This will only be present on posts which have been merged into another post.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the post is hidden. A post is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The post's ID.</td> </tr> <tr> <td><code>media_type</code></td> <td>String</td> <td>The type of media associated with this post. One of <code>"paste", "image"</code>.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the post as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the post has finished background processing.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this post after it has been processed.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the post contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the post contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was last updated.</td> </tr> </tbody> </table> <h3>Non-hidden Post Responses</h3> <p>For posts which are not hidden (ie: most posts), the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments the post has.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The post's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the post has.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of favourites the post has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The post's score - usually the number of upvotes minus the number of downvotes.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the post's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The post's number of upvotes.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the post, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For non-hidden posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="https://github.com/twibooru/image_intensities">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There are currently no libraries that have been written for the Twibooru API; however, you may be able to find old versions of some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. There is currently only one specific library that has been written for the Twibooru API. You may be able to adapt some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/joshua-stone/DerPyBooru">DerPyBooru (Python)</a></li> <li><a href="https://github.com/Xe/derpigo">derpigo (Go)</a></li> <li><a href="https://github.com/Ralvke/derpiboorust">derpiboorust (Rust)</a></li> <li><a href="https://github.com/octet-stream/dinky">dinky.js (JavaScript)</a></li> <li><a href="https://github.com/AppleDash/philomena4j">Philomena4J - By Floorb, supports Twibooru natively (Java).</a></li> </ul> <h2>Routes</h2> <p>Basic methods for fetching post lists and information are available. To access the JSON API for a given post, simply add <code>.json</code> to the end of the path. Here are a few examples.</p> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v1/json/comments/:comment_id</code></td> <td></td> <td>Fetches a <em>comment response</em> for the comment ID referenced by the <code>comment_id</code> URL parameter.</td> <td><code>{"comment":<a href="#comment-response">comment-response</a>}</code></td> <td><a href="/api/v1/json/comments/1000"><code>/api/v1/json/comments/1000</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#image-response">image-response</a>}</code></td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id/comments</code></td> <td></td> <td>Fetches a list of <em>comment responses</em> representing all comments on the post referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"comments":[<a href="#comment-response">comment-response</a>]}</code></td> <td><a href="/api/v3/posts/1/comments"><code>/api/v3/posts/1/comments</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns <em>post responses</em>.</td> <td><code>{"posts":[<a href="#image-response">image-response</a>]}</code></td> <td><a href="/api/v1/json/search/images?q=safe"><code>/api/v1/json/search/images?q=safe</code></a></td> <td>Executes the search given by the <code>q</code> query parameter, and returns a list of <em>post responses</em>.</td> <td><code>{"posts":[<a href="#post-response">post-response</a>]}</code></td> <td><a href="/api/v3/search/posts?q=safe"><code>/api/v3/search/posts?q=safe</code></a></td> </tr> </tbody> </table> <h2 id="post-response">Post Responses</h2> <p>These fields are present on all posts (unless otherwise noted), whether they have been hidden or not.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the post.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the post, or <code>null</code> if none provided. This will only be present on posts which have been deleted for a rule violation.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target post this post has been merged into. This will only be present on posts which have been merged into another post.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the post is hidden. A post is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The post's ID.</td> </tr> <tr> <td><code>media_type</code></td> <td>String</td> <td>The type of media associated with this post. One of <code>"paste", "image"</code>.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the post as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the post has finished background processing.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this post after it has been processed.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the post contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the post contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was last updated.</td> </tr> </tbody> </table> <h3>Non-hidden Post Responses</h3> <p>For posts which are not hidden (ie: most posts), the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments the post has.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The post's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the post has.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of favourites the post has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The post's score - usually the number of upvotes minus the number of downvotes.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the post's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The post's number of upvotes.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the post, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For non-hidden posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="https://github.com/twibooru/image_intensities">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There are currently no libraries that have been written for the Twibooru API; however, you may be able to find old versions of some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/joshua-stone/DerPyBooru">DerPyBooru (Python)</a></li> <li><a href="https://github.com/Xe/derpigo">derpigo (Go)</a></li> <li><a href="https://github.com/Ralvke/derpiboorust">derpiboorust (Rust)</a></li> <li><a href="https://github.com/octet-stream/dinky">dinky.js (JavaScript)</a></li> </ul> <h2>Routes</h2> <p>Basic methods for fetching post lists and information are available. To access the JSON API for a given post, simply add <code>.json</code> to the end of the path. Here are a few examples.</p> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v1/json/comments/:comment_id</code></td> <td></td> <td>Fetches a <em>comment response</em> for the comment ID referenced by the <code>comment_id</code> URL parameter.</td> <td><code>{"comment":<a href="#comment-response">comment-response</a>}</code></td> <td><a href="/api/v1/json/comments/1000"><code>/api/v1/json/comments/1000</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#image-response">image-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns <em>post responses</em>.</td> <td><code>{"posts":[<a href="#image-response">image-response</a>]}</code></td> <td><a href="/api/v1/json/search/images?q=safe"><code>/api/v1/json/search/images?q=safe</code></a></td> </tr> </tbody> </table> <h2 id="post-response">Post Responses</h2> <p>These fields are present on all posts (unless otherwise noted), whether they have been hidden or not.</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the post.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the post, or <code>null</code> if none provided. This will only be present on posts which have been deleted for a rule violation.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target post this post has been merged into. This will only be present on posts which have been merged into another post.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the post is hidden. A post is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The post's ID.</td> </tr> <tr> <td><code>media_type</code></td> <td>String</td> <td>The type of media associated with this post. One of <code>"paste", "image"</code>.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the post as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the post has finished background processing.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this post after it has been processed.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the post contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the post contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the post was last updated.</td> </tr> </tbody> </table> <h3>Non-hidden Post Responses</h3> <p>For posts which are not hidden (ie: most posts), the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments made on the image.</td> <td>The number of comments the post has.</td> </tr> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the image.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the image, or <code>null</code> if none provided. This will only have a value on images which are deleted for a rule violation.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The image's description.</td> <td>The post's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the image has.</td> <td>The number of downvotes the post has.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target image, or <code>null</code> if none provided. This will only have a value on images which are merged into another image.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of faves the image has.</td> <td>The number of favourites the post has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the image was first seen (before any duplicate merging).</td> <td>The time, in UTC, the post was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the image is hidden. An image is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The image's ID.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the image as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the image has finished optimization.</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The image's number of upvotes minus the image's number of downvotes.</td> <td>The post's score - usually the number of upvotes minus the number of downvotes.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this image after it has been processed.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the image's file contains.</td> <td>The number of bytes the post's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the image.</td> <td>The current source URL of the post.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the image contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the image contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the image was last updated.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The image's number of upvotes.</td> <td>The post's number of upvotes.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the image, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the post, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <p>For non-hidden posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="https://github.com/twibooru/image_intensities">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There are currently no libraries that have been written for the Twibooru API; however, you may be able to find old versions of some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/joshua-stone/DerPyBooru">DerPyBooru (Python)</a></li> <li><a href="https://github.com/Xe/derpigo">derpigo (Go)</a></li> <li><a href="https://github.com/Ralvke/derpiboorust">derpiboorust (Rust)</a></li> <li><a href="https://github.com/octet-stream/dinky">dinky.js (JavaScript)</a></li> </ul> <h2>Routes</h2> <p>Basic methods for fetching post lists and information are available. To access the JSON API for a given post, simply add <code>.json</code> to the end of the path. Here are a few examples.</p> <table class="table"> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There are currently no libraries that have been written for the Twibooru API; however, you may be able to find old versions of some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/joshua-stone/DerPyBooru">DerPyBooru (Python)</a></li> <li><a href="https://github.com/Xe/derpigo">derpigo (Go)</a></li> <li><a href="https://github.com/Ralvke/derpiboorust">derpiboorust (Rust)</a></li> <li><a href="https://github.com/octet-stream/dinky">dinky.js (JavaScript)</a></li> </ul> <h2>Routes</h2> <p>Basic methods for fetching post lists and information are available. To access the JSON API for a given post, simply add <code>.json</code> to the end of the path. Here are a few examples.</p> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v1/json/comments/:comment_id</code></td> <td></td> <td>Fetches a <em>comment response</em> for the comment ID referenced by the <code>comment_id</code> URL parameter.</td> <td><code>{"comment":<a href="#comment-response">comment-response</a>}</code></td> <td><a href="/api/v1/json/comments/1000"><code>/api/v1/json/comments/1000</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#image-response">image-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns <em>post responses</em>.</td> <td><code>{"posts":[<a href="#image-response">image-response</a>]}</code></td> <td><a href="/api/v1/json/search/images?q=safe"><code>/api/v1/json/search/images?q=safe</code></a></td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> <h2 id="post-response">Post Responses</h2> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>comment_count</code></td> <td>Integer</td> <td>The number of comments made on the image.</td> </tr> <tr> <td><code>created_at</code></td> <td>RFC3339 datetime</td> <td>The creation time, in UTC, of the image.</td> </tr> <tr> <td><code>deletion_reason</code></td> <td>String</td> <td>The hide reason for the image, or <code>null</code> if none provided. This will only have a value on images which are deleted for a rule violation.</td> </tr> <tr> <td><code>description</code></td> <td>String</td> <td>The image's description.</td> </tr> <tr> <td><code>downvotes</code></td> <td>Integer</td> <td>The number of downvotes the image has.</td> </tr> <tr> <td><code>duplicate_of</code></td> <td>Integer</td> <td>The ID of the target image, or <code>null</code> if none provided. This will only have a value on images which are merged into another image.</td> </tr> <tr> <td><code>faves</code></td> <td>Integer</td> <td>The number of faves the image has.</td> </tr> <tr> <td><code>first_seen_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the image was first seen (before any duplicate merging).</td> </tr> <tr> <td><code>hidden_from_users</code></td> <td>Boolean</td> <td>Whether the image is hidden. An image is hidden if it is merged or deleted for a rule violation.</td> </tr> <tr> <td><code>id</code></td> <td>Integer</td> <td>The image's ID.</td> </tr> <tr> <td><code>orig_sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of the image as it was originally uploaded.</td> </tr> <tr> <td><code>processed</code></td> <td>Boolean</td> <td>Whether the image has finished optimization.</td> </tr> <tr> <td><code>score</code></td> <td>Integer</td> <td>The image's number of upvotes minus the image's number of downvotes.</td> </tr> <tr> <td><code>sha512_hash</code></td> <td>String</td> <td>The SHA512 hash of this image after it has been processed.</td> </tr> <tr> <td><code>size</code></td> <td>Integer</td> <td>The number of bytes the image's file contains.</td> </tr> <tr> <td><code>source_url</code></td> <td>String</td> <td>The current source URL of the image.</td> </tr> <tr> <td><code>tag_ids</code></td> <td>Array</td> <td>A list of tag IDs the image contains.</td> </tr> <tr> <td><code>tags</code></td> <td>Array</td> <td>A list of tag names the image contains.</td> </tr> <tr> <td><code>updated_at</code></td> <td>RFC3339 datetime</td> <td>The time, in UTC, the image was last updated.</td> </tr> <tr> <td><code>upvotes</code></td> <td>Integer</td> <td>The image's number of upvotes.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>wilson_score</code></td> <td>Float</td> <td>The lower bound of the <a href="https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval">Wilson score interval</a> for the image, based on its upvotes and downvotes, given a z-score corresponding to a confidence of 99.5%.</td> </tr> </tbody> </table> <h3>Image Post Responses</h3> <p>For posts where <code>media_type</code> is equal to <code>"image"</code>, the following fields are also present in the response:</p> <table class="table"> <thead> <tr> <th>Field</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>animated</code></td> <td>Boolean</td> <td>Whether the image is animated.</td> </tr> <tr> <td><code>aspect_ratio</code></td> <td>Float</td> <td>The image's width divided by its height.</td> </tr> <tr> <td><code>duration</code></td> <td>Float</td> <td>The number of seconds the animation lasts, if animated, otherwise 0. (Currently unreliable.)</td> </tr> <tr> <td><code>format</code></td> <td>String</td> <td>The file extension of the image. One of <code>"gif", "jpg", "jpeg", "png", "svg", "webm", "mp4"</code>.</td> </tr> <tr> <td><code>height</code></td> <td>Integer</td> <td>The image's height, in pixels.</td> </tr> <tr> <td><code>intensities</code></td> <td>Object</td> <td>Optional object of <a href="https://github.com/twibooru/image_intensities">internal image intensity data</a> for deduplication purposes. May be <code>null</code> if intensities have not yet been generated.</td> </tr> <tr> <td><code>mime_type</code></td> <td>String</td> <td>The MIME type of this image. One of <code>"image/gif", "image/jpeg", "image/png", "image/svg+xml", "video/webm"</code>.</td> </tr> <tr> <td><code>name</code></td> <td>String</td> <td>The filename that the image was uploaded with.</td> </tr> <tr> <td><code>representations</code></td> <td>Object</td> <td>A mapping of representation names to their respective URLs. Contains the keys <code>"full", "large", "medium", "small", "tall", "thumb", "thumb_small", "thumb_tiny"</code>.</td> </tr> <tr> <td><code>thumbnails_generated</code></td> <td>Boolean</td> <td>Whether the image has finished thumbnail generation. Do not attempt to load images from <code>view_url</code> or <code>representations</code> if this is false.</td> </tr> <tr> <td><code>view_url</code></td> <td>String</td> <td>The image's view URL, including tags.</td> </tr> <tr> <td><code>width</code></td> <td>Integer</td> <td>The image's width, in pixels.</td> </tr> </tbody> </table> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests</li> <li>Do not make abusively high numbers of requests. Respect the <a href="#rate-limits">rate limits</a>.</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There are currently no libraries that have been written for the Twibooru API; however, you may be able to find old versions of some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/joshua-stone/DerPyBooru">DerPyBooru (Python)</a></li> <li><a href="https://github.com/Xe/derpigo">derpigo (Go)</a></li> <li><a href="https://github.com/Ralvke/derpiboorust">derpiboorust (Rust)</a></li> <li><a href="https://github.com/octet-stream/dinky">dinky.js (JavaScript)</a></li> </ul> <h2>Routes</h2> <p>Basic methods for fetching post lists and information are available. To access the JSON API for a given post, simply add <code>.json</code> to the end of the path. Here are a few examples.</p> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v1/json/comments/:comment_id</code></td> <td></td> <td>Fetches a <em>comment response</em> for the comment ID referenced by the <code>comment_id</code> URL parameter.</td> <td><code>{"comment":<a href="#comment-response">comment-response</a>}</code></td> <td><a href="/api/v1/json/comments/1000"><code>/api/v1/json/comments/1000</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#image-response">image-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns <em>post responses</em>.</td> <td><code>{"posts":[<a href="#image-response">image-response</a>]}</code></td> <td><a href="/api/v1/json/search/images?q=safe"><code>/api/v1/json/search/images?q=safe</code></a></td> </tr> </tbody> </table> <p>Note the list pages default to a 7 day sampling period; this can be altered with a URL parameter such as <code>6h</code>, <code>24h</code>, <code>7d,</code> or <code>4w</code>.</p> <p>Authenticated requests take a <var>key</var> argument. Fill this in with your personal API key from your Account page.</p> <h2 id="rate-limits">Rate Limits</h2> <p>There are hard rate limits enforced on every API endpoint. Exceeding these limits will result in your requests being throttled until the rate limit is complied with.</p> <p>You can determine the rate limit and your remaining balance, as well as the time at which the balance will reset, by examining the <code>X-RL</code>, <code>X-RL-Remaining</code>, and <code>X-RL-Reset</code> HTTP headers, respectively. For convenience, here is a list of rate limits:</p> <table class="table"> <thead> <tr> <th>Endpoint</th> <th>Maximum Requests</th> <th>Period</th> </tr> </thead> <tbody> <tr> <td>/api/v3/search/posts</td> <td>10</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id</td> <td>60</td> <td>1 minute</td> </tr> <tr> <td>/api/v3/posts/:id/comments</td> <td>60</td> <td>1 minute</td> </tr> </tbody> </table> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant with the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code></li> <li><code>/search.json?q=my:faves&amp;key=xxxxxxxxxxxxxxxxxxxx</code></li> <li><code>/search.json?q=my:upvotes&amp;key=xxxxxxxxxxxxxxxxxxxx</code></li> </ul> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant to the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is basically identical to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> prior to 2020. As such, any applications written for that API should be easily modifiable to be compatible with our API. The API is similar to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> and other <a href="https://github.com/philomena-dev/philomena" rel="external noopener" target="_blank">Philomena</a>-based boorus. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There are currently no libraries that have been written for the Twibooru API; however, you may be able to find old versions of some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/joshua-stone/DerPyBooru">DerPyBooru (Python)</a></li> <li><a href="https://github.com/Xe/derpigo">derpigo (Go)</a></li> <li><a href="https://github.com/Ralvke/derpiboorust">derpiboorust (Rust)</a></li> <li><a href="https://github.com/octet-stream/dinky">dinky.js (JavaScript)</a></li> </ul> <h2>Routes</h2> <p>Basic methods for fetching post lists and information are available. To access the JSON API for a given post, simply add <code>.json</code> to the end of the path. Here are a few examples.</p> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v1/json/comments/:comment_id</code></td> <td></td> <td>Fetches a <em>comment response</em> for the comment ID referenced by the <code>comment_id</code> URL parameter.</td> <td><code>{"comment":<a href="#comment-response">comment-response</a>}</code></td> <td><a href="/api/v1/json/comments/1000"><code>/api/v1/json/comments/1000</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#image-response">image-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns <em>post responses</em>.</td> <td><code>{"posts":[<a href="#image-response">image-response</a>]}</code></td> <td><a href="/api/v1/json/search/images?q=safe"><code>/api/v1/json/search/images?q=safe</code></a></td> </tr> </tbody> </table> <p>Note the list pages default to a 7 day sampling period; this can be altered with a URL parameter such as <code>6h</code>, <code>24h</code>, <code>7d,</code> or <code>4w</code>.</p> <p>Authenticated requests take a <var>key</var> argument. Fill this in with your personal API key from your Account page.</p> <ul> <li><code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code></li> <li><code>/search.json?q=my:faves&amp;key=xxxxxxxxxxxxxxxxxxxx</code></li> <li><code>/search.json?q=my:upvotes&amp;key=xxxxxxxxxxxxxxxxxxxx</code></li> </ul> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant to the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>
Floor Bored<div class="walloftext"> <p> We provide a <a href="https://www.json.org/" rel="external noopener" target="_blank"><abbr title="JavaScript Object Notation">JSON</abbr></a> <abbr title="Application Programming Interface">API</abbr> for major site functionality, which can be freely used by anyone wanting to produce tools for the site or other webapps that use the data provided within the site. </p> <p> The API is basically identical to that in use on <a href="https://derpibooru.org/" rel="external noopener" target="_blank">Derpibooru</a> prior to 2020. As such, any applications written for that API should be easily modifiable to be compatible with our API. </p> <h2>Licensing</h2> <p> Licensing of the API is simple &mdash; anyone can use it. However, there are some guidelines we ask that you follow: <ul class="rule"> <li>Do not make abusively high numbers of requests</li> <li>Your application <strong>MUST</strong> properly cache and respect server-side cache expiry times</li> <li>Your client <strong>MUST</strong> gracefully back off if requests fail (e.g., non-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="external noopener" target="_blank"><samp>200 OK</samp> HTTP status code</a>), preferably exponentially or fatally</li> <li>Credit <strong>SHOULD</strong> be given to Twibooru in the form of a link</li> <li>If media is displayed from Twibooru, the artist <strong>SHOULD</strong> be credited (if available) and you <strong>SHOULD</strong> display the original source <abbr title="Uniform Resource Locator">URL</abbr> with the media, either textually or as a link</li> <li>A link to the post here on Twibooru is optional but suggested</li> <li>We recommend using <code>twibooru.org</code> as the canonical domain</li> <li>The <code>https</code> protocol <strong>MUST</strong> be specified on all <abbr title="Uniform Resource Indicator">URI</abbr>s; we do not support plain text HTTP connections</li> </ul> </p> <h2>Parameters</h2> <p>This is a list of general parameters that are useful when working with the API. Not all parameters may be used in every request.</p> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>filter_id</code></td> <td>Assuming the user can access the filter ID given by the parameter, overrides the current filter for this request. This is primarily useful for unauthenticated API access.</td> </tr> <tr> <td><code>key</code></td> <td>An optional authentication token. If omitted, no user will be authenticated.<br><br>You can find your authentication token in your <a href="/registration/edit">account settings</a>.</td> </tr> <tr> <td><code>page</code></td> <td>Controls the current page of the response, if the response is paginated. Empty values default to the first page.</td> </tr> <tr> <td><code>per_page</code></td> <td>Controls the number of results per page, up to a limit of 50, if the response is paginated. The default is 25.</td> </tr> <tr> <td><code>q</code></td> <td>The current search query, if the request is a search request.</td> </tr> <tr> <td><code>sd</code></td> <td>The current sort direction, if the request is a search request.</td> </tr> <tr> <td><code>sf</code></td> <td>The current sort field, if the request is a search request.</td> </tr> </tbody> </table> <h2>Accessing the API</h2> <p> Most methods support API access by appending the <code>.json</code> extension to a URL. For requests that require authentication, the URL parameter <var>key</var> should be appended. This key provides limited access to a user's account and can be found by users on their account page. For instance, to access a user's watched feed, the request would be <code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code> </p> <p> Methods dealing with large feeds are paginated; the <var>page</var> parameter controls the page you're on. The number of posts per page can be set with the <var>perpage</var> parameter. The default is 15 unless you use your key and have changed the <q>Images per page</q> option on the settings page. </p> <p>Search endpoints are controlled by the current user's filter (or the default, if no key is supplied); if you wish to use a custom filter, you can use the <var>filter_id</var> parameter.</p> <h2>Libraries</h2> <p> There are currently no libraries that have been written for the Twibooru API; however, you may be able to find old versions of some of the Derpibooru API libraries listed below and make them work with Twibooru with minor modifications. We haven't tested any of them, so your results may vary. If you want to develop or port one of these to Twibooru, please do so and contact us if you'd like it included in this list. </p> <ul> <li><a href="https://github.com/joshua-stone/DerPyBooru">DerPyBooru (Python)</a></li> <li><a href="https://github.com/Xe/derpigo">derpigo (Go)</a></li> <li><a href="https://github.com/Ralvke/derpiboorust">derpiboorust (Rust)</a></li> <li><a href="https://github.com/octet-stream/dinky">dinky.js (JavaScript)</a></li> </ul> <h2>Routes</h2> <p>Basic methods for fetching post lists and information are available. To access the JSON API for a given post, simply add <code>.json</code> to the end of the path. Here are a few examples.</p> <table class="table"> <thead> <tr> <th>Method</th> <th>Path</th> <th>Allowed Query Parameters</th> <th>Description</th> <th>Response Format</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>GET</code></td> <td><code>/api/v1/json/comments/:comment_id</code></td> <td></td> <td>Fetches a <em>comment response</em> for the comment ID referenced by the <code>comment_id</code> URL parameter.</td> <td><code>{"comment":<a href="#comment-response">comment-response</a>}</code></td> <td><a href="/api/v1/json/comments/1000"><code>/api/v1/json/comments/1000</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/:post_id</code></td> <td><code>key, filter_id</code></td> <td>Fetches a <em>post response</em> for the post ID referenced by the <code>post_id</code> URL parameter.</td> <td><code>{"post":<a href="#post-response">post-response</a>}</code></td> <td><a href="/api/v3/posts/1"><code>/api/v3/posts/1</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/posts/featured</code></td> <td><code></code></td> <td>Fetches a <em>post response</em> for the for the current featured image.</td> <td><code>{"post":<a href="#image-response">image-response</a>}</code></td> <td><a href="/api/v3/images/featured"><code>/api/v3/images/featured</code></a></td> </tr> <tr> <td><code>GET</code></td> <td><code>/api/v3/search/posts</code></td> <td><code>key, filter_id, page, per_page, q, sd, sf</code></td> <td>Executes the search given by the <code>q</code> query parameter, and returns <em>post responses</em>.</td> <td><code>{"posts":[<a href="#image-response">image-response</a>]}</code></td> <td><a href="/api/v1/json/search/images?q=safe"><code>/api/v1/json/search/images?q=safe</code></a></td> </tr> </tbody> </table> <p>Note the list pages default to a 7 day sampling period; this can be altered with a URL parameter such as <code>6h</code>, <code>24h</code>, <code>7d,</code> or <code>4w</code>.</p> <p>Authenticated requests take a <var>key</var> argument. Fill this in with your personal API key from your Account page.</p> <ul> <li><code>/posts/watched.json?key=xxxxxxxxxxxxxxxxxxxx</code></li> <li><code>/search.json?q=my:faves&amp;key=xxxxxxxxxxxxxxxxxxxx</code></li> <li><code>/search.json?q=my:upvotes&amp;key=xxxxxxxxxxxxxxxxxxxx</code></li> </ul> <h2>oEmbed</h2> <p> For embedding content in other websites as well as for finding canonical post descriptors and IDs, we provide an <a href="https://oembed.com/" rel="external noopener" target="_blank">oEmbed</a> API. </p> <p>This API is compliant to the oEmbed specification and can be found at <a href="/oembed.json"><code>/oembed.json</code></a> or <a href="/oembed.xml"><code>/oembed.xml</code></a>.</p> <p> Format selection is done by URL; call <code>oembed.xml</code> for an <abbr title="eXtensible Markup Language">XML</abbr> response. This is the only API currently supporting XML and we strongly encourage the use of JSON wherever possible. </p> <p> <strong>You are strongly advised to cache response data on your own server upon embedding content via oEmbed, particularly if your website supports a large number of users.</strong> A <samp>cache_age</samp> parameter is provided, which your client <strong>SHOULD</strong> respect for oEmbed requests themselves. </p> <p> The <samp>author_url</samp> and <samp>author_name</samp> attributes will be set to the original author/source URL attributes wherever possible. The <samp>provider_url</samp> attribute will always direct you to the post's page on Twibooru. </p> <p>In addition to the standard oEmbed photo attributes, the following attributes are also provided: <samp>twibooru_id</samp>, <samp>twibooru_score</samp>, and <samp>twibooru_comments</samp></p> <p> The following domain spaces are supported (for <code>twibooru.org</code> and other domains, the format is the same). <code>/media/</code> and <code>/img/</code> URLs are only supported on <code>cdn.twibooru.org</code>. </p> <ul> <li><code>https://twibooru.org/*</code></li> <li><code>https://twibooru.org/posts/*</code></li> <li><code>https://cdn.twibooru.org/img/*</code></li> </ul> <p>For example:</p> <ul> <li><a href="/oembed.json?url=https://twibooru.org/470155"><code>/oembed.json?url=https://twibooru.org/470155</code></a></li> </ul> <p>This service supports <var>maxwidth</var> and <var>maxheight</var> parameters; these will return a fully formed thumbnail.</p> <p>For tools that support it, the Twibooru HTML header is embellished with appropriate oEmbed lookup link tags for automatic oEmbed discovery.</p> </div>