GIFs
A GIF is one animated media item held by the deployment’s active GIF provider. Fluxer stores none of them, so every route on this page reads the provider live and returns provider URLs beside signed Media Proxy URLs.
Every route requires a session credential. A bot token and an OAuth2 bearer credential are both refused with 403 ACCESS_DENIED. Save meme from URL saves a result into the account’s own collection.
Provider availability
Section titled “Provider availability”klipy is the only provider name a deployment binds. Get instance discovery publishes it as the GIF provider object. An instance that has bound no provider key refuses every route on this page with 403 FEATURE_TEMPORARILY_DISABLED. That same key drives gif_enabled in service availability, a flag an operator can also set by hand, so a client that reads gif_enabled as true can still receive the 403.
A provider outage, a request that outlives its deadline, and an unreadable provider payload all surface as 503 SERVICE_UNAVAILABLE. The deadline is 12 seconds everywhere except Register a GIF share, which uses 3 seconds. An operator can change both.
Locale and country
Section titled “Locale and country”Every route takes an optional locale drawn from the supported locale registry, in the query string on the four GET routes and in the body of Register a GIF share. It defaults to en-US. A tag outside the registry fails with 400 INVALID_FORM_BODY.
Fluxer also derives a two-letter country from the requesting address by geolocation, and uses US when geolocation resolves none. No route accepts the country as a parameter, so a client cannot override it. Get GIF search suggestions is the one route that ignores it.
Provider headers
Section titled “Provider headers”Every response under /gifs, /tenor, and /klipy has these three headers, including error responses and responses to a path no route claims. The three values repeat the GIF provider object, so a client follows a provider change without refetching /.well-known/fluxer.
| Field | Type | Description |
|---|---|---|
| X-Fluxer-GIF-Provider1 | string | The machine name of the active provider, which is klipy on every deployment today |
| X-Fluxer-GIF-Provider-Display-Name1 | string | The provider name a client displays |
| X-Fluxer-GIF-Provider-Attribution-Required1 | string | The literal true or false, stating whether a client shows the provider attribution mark |
1 All three are absent together while the instance has bound no provider key, which is the same condition that answers 403 FEATURE_TEMPORARILY_DISABLED
Result freshness
Section titled “Result freshness”Fluxer caches one answer for each combination of operation, locale, country, and query. Past the refresh bound a request still receives the stored answer, and past the discard bound it waits for a fresh answer.
| Answer | Refresh bound | Discard bound |
|---|---|---|
| Search results | 30 seconds | 5 minutes |
| Search suggestions | 1 minute | 10 minutes |
| Featured GIFs and trending GIFs | 5 minutes | 30 minutes |
| Featured categories | 24 hours | 48 hours |
A deployment can configure a further cache in front of those bounds. Neither cache is keyed by the caller, so two accounts sending the same query in the same country receive the same answer. No route on this page invalidates a cached answer.
GIF object
Section titled “GIF object”A GIF object is one media item the active provider owns. Every URL in it resolves to bytes the provider hosts.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id1 | string | The provider-stable identifier of the GIF |
| slug1 | string | The canonical slug used to share the GIF or resolve it again |
| provider | string | The name of the provider that produced the GIF (1-32 characters) |
| title | string | The title the provider gives the GIF |
| url | string | The provider page URL for the GIF |
| src2 | string | The direct media URL of the format the server chose |
| proxy_src2 | string | The Media Proxy URL of that same format |
| width2 | integer | The width of the chosen format in pixels |
| height2 | integer | The height of the chosen format in pixels |
| media3 | map[string, GIF media format object] | The formats keyed by GIF media format name |
| placeholder?4 | ?string | The compact thumbhash placeholder rendered while the GIF loads |
1 The active provider writes the same slug into both, so id is the value Register a GIF share takes
2 Copied from the webm entry of media when the provider returned one, and from the first entry it returned otherwise
3 Empty when no format the provider returned could be proxied. No key is guaranteed, so a client walks a priority list
4 The active provider emits none, so the field is absent from every GIF these routes return. Resolve GIF URLs is the operation that produces one
A GIF has no snowflake and no creation timestamp. id is the provider’s own identifier, so it does not sort by time, and no other Fluxer route resolves it.
Example
Section titled “Example”{ "id": "goat-plays-banjo-4", "slug": "goat-plays-banjo-4", "provider": "klipy", "title": "Goat Plays Banjo", "url": "https://klipy.com/gifs/goat-plays-banjo-4", "src": "https://static.example.com/goat-plays-banjo.webm", "proxy_src": "https://media.example.com/external/9f21c0/goat-plays-banjo.webm", "width": 220, "height": 229, "media": { "webm": { "src": "https://static.example.com/goat-plays-banjo.webm", "proxy_src": "https://media.example.com/external/9f21c0/goat-plays-banjo.webm", "width": 220, "height": 229 }, "tinygif": { "src": "https://static.example.com/goat-plays-banjo-tiny.gif", "proxy_src": "https://media.example.com/external/4ad117/goat-plays-banjo-tiny.gif", "width": 137, "height": 90 } }}GIF category object
Section titled “GIF category object”A GIF category object pairs a category search term with a preview GIF for that term.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| name | string | The search term the category stands for, translated for the requested locale |
| src1 | string | The direct media URL of the preview GIF |
| proxy_src1 | string | The Media Proxy URL of the preview GIF |
| gif | ?GIF object | The preview GIF, or null when the preview lookup returned nothing |
1 Copied from the same field of gif, and the empty string when gif is null
To open the category, a client sends name as the q of Search GIFs.
Deprecated vendor paths
Section titled “Deprecated vendor paths”Two vendor-named prefixes serve the same five handlers as /gifs. Each answers exactly as its successor does and has the same provider headers.
| Method | Deprecated path | Successor |
|---|---|---|
| GET | /v1/tenor/search | Search GIFs |
| GET | /v1/tenor/featured | Get featured GIFs |
| GET | /v1/tenor/trending-gifs | Get trending GIFs |
| GET | /v1/tenor/suggest | Get GIF search suggestions |
| POST | /v1/tenor/register-share | Register a GIF share |
| GET | /v1/klipy/search | Search GIFs |
| GET | /v1/klipy/featured | Get featured GIFs |
| GET | /v1/klipy/trending-gifs | Get trending GIFs |
| GET | /v1/klipy/suggest | Get GIF search suggestions |
| POST | /v1/klipy/register-share | Register a GIF share |
A response from one of the ten has three further headers.
| Field | Type | Description |
|---|---|---|
| Deprecation | string | The literal value true |
| Link | string | The literal value </gifs>; rel="successor-version" |
| Warning1 | string | A 299 warning naming the successor prefix |
1 The exact value is 299 - "Use /gifs/* instead - these vendor-specific paths are deprecated and will be removed."
The vendor name in the path selects nothing. A request to /v1/tenor/search reaches the same active provider as /v1/gifs/search, and the provider field of every GIF it returns names that provider.
Search GIFs
Section titled “Search GIFs”GET/v1/gifs/searchSearches the active provider for GIFs matching a query. Returns at most 50 GIF objects in the order the provider returned them.
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| q | string | The search term (1-256 characters) |
| locale? | string | A supported locale, default en-US |
Fluxer does not stem, expand, or spell-correct the term. A term that matches nothing returns 200 with an empty array.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | array[GIF object] | Results were returned, possibly as an empty array |
| 400 | error response | q is absent, empty, or longer than 256 characters, or locale is outside the registry, each returning INVALID_FORM_BODY |
| 403 | error response | Caller is a bot or presents a bearer credential and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The instance has bound no provider key and the request returns FEATURE_TEMPORARILY_DISABLED |
| 503 | error response | The provider failed, the request outlived its deadline, or the gifs service answered with a payload the API could not read, each returning SERVICE_UNAVAILABLE |
Rate limit
Section titled “Rate limit”40 requests per 10 seconds for each authenticated user, on the gif:search bucket.
Get featured GIFs
Section titled “Get featured GIFs”GET/v1/gifs/featuredReturns the provider’s featured GIFs and the category terms offered alongside them.
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| locale? | string | A supported locale, default en-US |
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| gifs1 | array[GIF object] | The featured GIFs for the resolved locale and country |
| categories2 | array[GIF category object] | The category terms offered for the resolved locale |
1 At most one entry. Get trending GIFs is the route that returns a full listing
2 At most 50 entries, deduplicated by search term and kept in the order the provider returned them
Fluxer resolves the category list against the country US for every request, whatever country geolocation produced, so two callers in different countries receive the same categories and different gifs. A category whose preview lookup returned nothing is still listed, with gif null and both URLs empty.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | Featured GIFs and categories were returned |
| 400 | error response | locale is outside the registry and the request returns INVALID_FORM_BODY |
| 403 | error response | Caller is a bot or presents a bearer credential and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The instance has bound no provider key and the request returns FEATURE_TEMPORARILY_DISABLED |
| 503 | error response | The provider failed, the request outlived its deadline, or the gifs service answered with a payload the API could not read, each returning SERVICE_UNAVAILABLE |
Fluxer fetches both halves in one operation. A failure on either one fails the whole request and returns no partial body.
Rate limit
Section titled “Rate limit”40 requests per 10 seconds for each authenticated user, on the gif:featured bucket.
Get trending GIFs
Section titled “Get trending GIFs”GET/v1/gifs/trendingReturns at most 50 trending GIF objects for the resolved locale and country.
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| locale? | string | A supported locale, default en-US |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | array[GIF object] | Trending GIFs were returned, possibly as an empty array |
| 400 | error response | locale is outside the registry and the request returns INVALID_FORM_BODY |
| 403 | error response | Caller is a bot or presents a bearer credential and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The instance has bound no provider key and the request returns FEATURE_TEMPORARILY_DISABLED |
| 503 | error response | The provider failed, the request outlived its deadline, or the gifs service answered with a payload the API could not read, each returning SERVICE_UNAVAILABLE |
Trending and featured read the same provider listing, trending for 50 results and featured for one. The two are cached separately, so the single GIF in a featured response can be older than the first entry here.
Rate limit
Section titled “Rate limit”40 requests per 10 seconds for each authenticated user, on the gif:trending bucket.
Get GIF search suggestions
Section titled “Get GIF search suggestions”GET/v1/gifs/suggestReturns search-term suggestions for a partial query, as an array of strings.
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| q | string | The partial search term (1-256 characters) |
| locale? | string | A supported locale, default en-US |
This route sends no country to the provider. Its answers are keyed by locale and query alone, and do not vary with the requesting address.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | array[string] | Suggestions were returned, possibly as an empty array |
| 400 | error response | q is absent, empty, or longer than 256 characters, or locale is outside the registry, each returning INVALID_FORM_BODY |
| 403 | error response | Caller is a bot or presents a bearer credential and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The instance has bound no provider key and the request returns FEATURE_TEMPORARILY_DISABLED |
| 503 | error response | The provider failed, the request outlived its deadline, or the gifs service answered with a payload the API could not read, each returning SERVICE_UNAVAILABLE |
Each suggestion is a term a client sends back as the q of Search GIFs.
Rate limit
Section titled “Rate limit”40 requests per 10 seconds for each authenticated user, on the gif:suggest bucket.
Register a GIF share
Section titled “Register a GIF share”POST/v1/gifs/register-shareTells the active provider that the caller is sharing one of its GIFs, and returns 204 with an empty body.
JSON body
Section titled “JSON body”| Field | Type | Description |
|---|---|---|
| id1 | string | The id of the shared GIF object (1-300 characters) |
| q?2 | ?string | The search term that produced the GIF (0-256 characters) |
| locale? | string | A supported locale, default en-US |
1 The provider reads it as a slug or a slug-id token. Fluxer does not check it against a GIF it has returned, so an identifier the provider does not recognise fails at the provider
2 An omitted or null value is sent to the provider as the empty string
The deadline on this route is 3 seconds.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 204 | empty | The provider accepted the registration |
| 400 | error response | id is absent, empty, or longer than 300 characters, q is longer than 256 characters, or locale is outside the registry, each returning INVALID_FORM_BODY |
| 403 | error response | Caller is a bot or presents a bearer credential and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The instance has bound no provider key and the request returns FEATURE_TEMPORARILY_DISABLED |
| 503 | error response | The provider rejected the registration, the gifs service did not answer within the deadline, or it answered with something other than an acknowledgement, each returning SERVICE_UNAVAILABLE |
Side effects
Section titled “Side effects”The registration reaches the provider and changes no Fluxer state, so it emits no Gateway Dispatch and does not add the GIF to the account’s memes.
Fluxer neither caches nor deduplicates the call, so registering the same id twice reaches the provider twice.
Rate limit
Section titled “Rate limit”60 requests per 10 seconds for each authenticated user, on the gif:register_share bucket.