Guia de início rápido

Bem-vindo ao Tenor! O Tenor adota uma abordagem centrada em dados para fornecer pesquisas de GIFs relevantes em mais de 45 idiomas. Integre a pesquisa de GIFs do Tenor ao seu aplicativo em questão de minutos.

Logotipos para Facebook, Twitter, WhatsApp, Gboard e LinkedIn

Destaques da API

O Tenor's GIF Keyboard é o app de compartilhamento de GIFs para dispositivos móveis com mais downloads. Os desenvolvedores podem incorporar todos os recursos do Tenor nos próprios aplicativos com nossas APIs. Os destaques incluem:

Pesquise GIFs interessantes e interessantes na Internet.

Compatível com mais de 45 idiomas, conteúdo localizado e adequação de conteúdo regional.

Recursos avançados que ajudam os usuários a encontrar rapidamente o GIF que desejam.

Otimização que entrega GIFs que carregam e consomem menos largura de banda.

Configuração

Antes de começar, siga estas etapas:

  1. Inscreva-se ou faça login no Console do Google Cloud

  2. Gerar uma chave da API Tenor

Inscreva-se ou faça login no Console do Google Cloud e receba uma chave de API sem custo financeiro do Tenor para seu aplicativo em menos de 60 segundos. Veja suas métricas de API e solicite novas chaves por meio do Console do Google Cloud.

Atribuição, limitação de taxa e armazenamento em cache

É necessário atribuir corretamente todo o conteúdo recuperado do Tenor com uma das três opções de atribuição.

Consulte as políticas de limites de taxa e armazenamento em cache da API Tenor.

Etapa 1: implementar a pesquisa

O Tenor Search oferece GIFs relevantes e envolventes em mais de 45 idiomas. O Tenor recebe mais de 300 milhões de pesquisas por dia e melhora continuamente os resultados de GIF para cada consulta com base na pesquisa de usuário e no comportamento de compartilhamento.

Recomendamos que você carregue inicialmente um dos tamanhos otimizados menores para visualizações, como tinygif. Em seguida, é possível carregar e exibir a versão em tamanho original, como gif, quando o usuário compartilhar.

Esta documentação inclui exemplos de solicitações de pesquisa nas amostras de código. Essas amostras usam o endpoint de pesquisa e solicitam os oito GIFs mais classificados para o termo de pesquisa excited.

Curl

/* search for excited top 8 GIFs */
curl "https://tenor.googleapis.com/v2/search?q=excited&key=API_KEY&client_key=my_test_app&limit=8"

Python

# set the apikey and limit
apikey = "API_KEY"  # click to set to your apikey
lmt = 8
ckey = "my_test_app"  # set the client_key for the integration and use the same value for all API calls

# our test search
search_term = "excited"

# get the top 8 GIFs for the search term
r = requests.get(
    "https://tenor.googleapis.com/v2/search?q=%s&key=%s&client_key=%s&limit=%s" % (search_term, apikey, ckey,  lmt))

if r.status_code == 200:
    # load the GIFs using the urls for the smaller GIF sizes
    top_8gifs = json.loads(r.content)
    print(top_8gifs)
else:
    top_8gifs = None

Android/Java

import android.app.Application;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;

public class App extends Application {

    private static final String API_KEY = "API_KEY";
    private static final String CLIENT_KEY = "my_test_app"
    private static final String LogTag = "TenorTest";

    @Override
    public void onCreate() {
        super.onCreate();

        new Thread() {
            @Override
            public void run() {

                final String searchTerm = "excited";

                // make initial search request for the first 8 items
                JSONObject searchResult = getSearchResults(searchTerm, 8);

                // load the results for the user
                Log.v(LogTag, "Search Results: " + searchResult.toString());

            }
        }.start();
    }

    /**
     * Get Search Result GIFs
     */
    public static JSONObject getSearchResults(String searchTerm, int limit) {

        // make search request - using default locale of EN_US

        final String url = String.format("https://tenor.googleapis.com/v2/search?q=%1$s&key=%2$s&client_key=%3$s&limit=%4$s",
                searchTerm, API_KEY, CLIENT_KEY, limit);
        try {
            return get(url);
        } catch (IOException | JSONException ignored) {
        }
        return null;
    }

    /**
     * Construct and run a GET request
     */
    private static JSONObject get(String url) throws IOException, JSONException {
        HttpURLConnection connection = null;
        try {
            // Get request
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

            // Handle failure
            int statusCode = connection.getResponseCode();
            if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) {
                String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url);
                throw new ConnectException(error);
            }

            // Parse response
            return parser(connection);
        } catch (Exception ignored) {
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return new JSONObject("");
    }

    /**
     * Parse the response into JSONObject
     */
    private static JSONObject parser(HttpURLConnection connection) throws JSONException {
        char[] buffer = new char[1024 * 4];
        int n;
        InputStream stream = null;
        try {
            stream = new BufferedInputStream(connection.getInputStream());
            InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
            StringWriter writer = new StringWriter();
            while (-1 != (n = reader.read(buffer))) {
                writer.write(buffer, 0, n);
            }
            return new JSONObject(writer.toString());
        } catch (IOException ignored) {
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException ignored) {
                }
            }
        }
        return new JSONObject("");
    }
}

Swift 2.0+/iOS

let apikey = "API_KEY"
let clientkey = "my_test_app"

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    requestData()

    return true
  }

  /**
   Execute web request to retrieve the top GIFs returned(in batches of 8) for the given search term.
   */
  func requestData()
  {
    // the test search term
    let searchTerm = "excited"

    // Define the results upper limit
    let limit = 8

    // make initial search request for the first 8 items
    let searchRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/search?q=%@&key=%@&client_key=%@&limit=%d",
                                                             searchTerm,
                                                             apikey,
                                                             clientkey,
                                                             limit))!)

    makeWebRequest(urlRequest: searchRequest, callback: tenorSearchHandler)

    // Data will be loaded by each request's callback
  }

  /**
   Async URL requesting function.
   */
  func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ())
  {
    // Make the async request and pass the resulting JSON object to the callback
    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
      do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] {
          // Push the results to our callback
          callback(jsonResult)
        }
      } catch let error as NSError {
        print(error.localizedDescription)
      }
    }
    task.resume()
  }

  /**
   Web response handler for search requests.
   */
  func tenorSearchHandler(response: [String:AnyObject])
  {
    // Parse the JSON response
    let responseGifs = response["results"]!

    // Load the GIFs into your view
    print("Result GIFS: (responseGifs)")

  }

JavaScript

<!DOCTYPE html>
<html>
<script>

// url Async requesting function
function httpGetAsync(theUrl, callback)
{
    // create the request object
    var xmlHttp = new XMLHttpRequest();

    // set the state change callback to capture when the response comes in
    xmlHttp.onreadystatechange = function()
    {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
        {
            callback(xmlHttp.responseText);
        }
    }

    // open as a GET call, pass in the url and set async = True
    xmlHttp.open("GET", theUrl, true);

    // call send with no params as they were passed in on the url string
    xmlHttp.send(null);

    return;
}

// callback for the top 8 GIFs of search
function tenorCallback_search(responsetext)
{
    // Parse the JSON response
    var response_objects = JSON.parse(responsetext);

    top_10_gifs = response_objects["results"];

    // load the GIFs -- for our example we will load the first GIFs preview size (nanogif) and share size (gif)

    document.getElementById("preview_gif").src = top_10_gifs[0]["media_formats"]["nanogif"]["url"];

    document.getElementById("share_gif").src = top_10_gifs[0]["media_formats"]["gif"]["url"];

    return;

}


// function to call the trending and category endpoints
function grab_data()
{
    // set the apikey and limit
    var apikey = "API_KEY";
    var clientkey = "my_test_app";
    var lmt = 8;

    // test search term
    var search_term = "excited";

    // using default locale of en_US
    var search_url = "https://tenor.googleapis.com/v2/search?q=" + search_term + "&key=" +
            apikey +"&client_key=" + clientkey +  "&limit=" + lmt;

    httpGetAsync(search_url,tenorCallback_search);

    // data will be loaded by each call's callback
    return;
}


// SUPPORT FUNCTIONS ABOVE
// MAIN BELOW

// start the flow
grab_data();

</script>

<body>

<h2># 1 GIF loaded - preview image</h2>
<img id="preview_gif" src="" alt="" style="width:220px;height:164px;">

<h2># 1 GIF loaded - share image</h2>
<img id="share_gif" src="" alt="" style="width:498px;height:372px;">

</body>
</html>

Objective-C

NSString *apiKey = @"API_KEY";
NSString *clientKey = @"my_test_app";

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [self requestData];
  return YES;
}

/**
 Execute web request to retrieve the top GIFs returned(in batches of 8) for the given search term.
 */
-(void)requestData
{
  // Define the results upper limit
  int limit = 8;

  // the test search term
  NSString *searchQuery = @"excited";

  // Get the top 10 trending GIFs (updated through out the day) - using the default locale of en_US
  NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/search?key=%@&client_key=%@&q=%@&limit=%d", apiKey, clientKey, searchQuery, limit];
  NSURL *searchUrl = [NSURL URLWithString:UrlString];
  NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl];
  [self makeWebRequest:searchRequest withCallback:tenorSearchResultsHandler];

  // Data will be loaded by each request's callback
}

/**
 Async URL requesting function.
 */
-(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback
{
  // Make the async request and pass the resulting JSON object to the callback
  NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NStopGifsError *jsonError = nil;
    NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

    if(jsonError != nil) {
      NSLog(@"%@", jsonError.localizedDescription);
      return;
    }

    // Push the results to our callback
    callback(jsonResult);
  }];

  [task resume];
}

/**
 Web response handler for searches.
 */
void (^tenorSearchResultsHandler)(NSDictionary *) = ^void(NSDictionary *response)
{
  // Parse the JSON response
  NSDictionary *topGifs = response[@"results"];

  // Load the GIFs into your view
  NSLog(@"Search Results: %@", topGifs);
};

Compartilhar

Etapa 2: implementar eventos de compartilhamento

Quando um usuário selecionar um GIF para compartilhar, envie um evento de compartilhamento correspondente para o Tenor. Os eventos de compartilhamento ajudam a Tenor AI Search Engine a ajustar os resultados da pesquisa, o que ajuda os usuários a encontrar o GIF perfeito.

O exemplo a seguir usa o endpoint de registro de compartilhamento com o primeiro resultado GIF retornado para o termo de pesquisa excited:

Curl

/* register share */
curl "https://tenor.googleapis.com/v2/registershare?id=16989471141791455574&key=API_KEY&client_key=my_test_app&q=excited"

Python

# set the apikey
apikey = "API_KEY"   # click to set to your apikey
ckey = "my_test_app"  # set the client_key for the integration

# get the GIF's id and search used
shard_gifs_id = top_8gifs["results"][0]["id"]

search_term = "excited"

r = requests.get("https://tenor.googleapis.com/v2/registershare?id=%s&key=%s&client_key=%s&q=%s" % (shard_gifs_id, apikey, ckey, search_term))

if r.status_code == 200:
    pass
    # move on
else:
    pass
    # handle error

Android/Java

import android.app.Application;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;

public class App extends Application {

    private static final String API_KEY = "API_KEY";
    private static final String CLIENT_KEY = "my_test_app";
    private static final String LogTag = "TenorTest";

    @Override
    public void onCreate() {
        super.onCreate();

        new Thread() {
            @Override
            public void run() {

                // test values for the share example
                final String gifId = "16989471141791455574";
                final String searchTerm = "excited";

                // make the register share call
                JSONObject shareResult = registerShare(gifId, searchTerm);

                // load the results for the user
                Log.v(LogTag, "Share Results: " + shareResult.toString());

            }
        }.start();
    }

    /**
     * Register the GIF share
     */
    public static JSONObject registerShare(String gifId, String searchTerm) {

        // make register share request - using default locale of EN_US
        final String url = String.format("https://tenor.googleapis.com/v2/registershare?key=%1$s&client_key=%2$s&id=%3$s&q=%4$s",
                API_KEY, CLIENT_KEY, gifId, searchTerm);
        try {
            return get(url);
        } catch (IOException | JSONException ignored) {
        }
        return null;
    }

    /**
     * Construct and run a GET request
     */
    private static JSONObject get(String url) throws IOException, JSONException {
        HttpURLConnection connection = null;
        try {
            // Get request
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

            // Handle failure
            int statusCode = connection.getResponseCode();
            if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) {
                String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url);
                throw new ConnectException(error);
            }

            // Parse response
            return parser(connection);
        } catch (Exception ignored) {
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return new JSONObject("");
    }

    /**
     * Parse the response into JSONObject
     */
    private static JSONObject parser(HttpURLConnection connection) throws JSONException {
        char[] buffer = new char[1024 * 4];
        int n;
        InputStream stream = null;
        try {
            stream = new BufferedInputStream(connection.getInputStream());
            InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
            StringWriter writer = new StringWriter();
            while (-1 != (n = reader.read(buffer))) {
                writer.write(buffer, 0, n);
            }
            return new JSONObject(writer.toString());
        } catch (IOException ignored) {
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException ignored) {
                }
            }
        }
        return new JSONObject("");
    }
}

Swift 2.0+/iOS

let apikey = "API_KEY"
let clientkey = "my_test_app"

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // test values for the share example
    let gifId = "16989471141791455574"
    let searchTerm = "excited"

    // register the user's share
    registerShare(gifId: gifId, searchTerm: searchTerm)

    return true
  }

  // Function for handling a user's selection of a GIF to share.
  // In a production application, the GIF id should be the "id" field of the GIF response object that the user selected
  // to share. The search term should be the user's last search.
  func registerShare(gifId: String, searchTerm: String) {

    // Register the user's share - using the default locale of en_US
    let shareRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/registershare?key=%@&client_key=%@&id=%@&q=%@",
                                                             apikey,
                                                             clientkey,
                                                             gifId,
                                                             searchTerm))!)
    makeWebRequest(urlRequest: shareRequest, callback: tenorShareHandler)

    // Data will be loaded by each request's callback
  }

  /**
   Async URL requesting function.
   */
  func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ())
  {
    // Make the async request and pass the resulting json object to the callback
    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
      do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] {
          // Push the results to our callback
          callback(jsonResult)
        }
      } catch let error as NSError {
        print(error.localizedDescription)
      }
    }
    task.resume()
  }

  /**
   Web response handler for search requests.
   */
  func tenorShareHandler(response: [String:AnyObject])
  {
   // no response expected from the registershare endpoint

  }

JavaScript

<!DOCTYPE html>
<html>
<script>

// url Async requesting function
function httpGetAsync(theUrl, callback)
{
    // create the request object
    var xmlHttp = new XMLHttpRequest();

    // set the state change callback to capture when the response comes in
    xmlHttp.onreadystatechange = function()
    {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
        {
            callback(xmlHttp.responseText);
        }
    }

    // open as a GET call, pass in the url and set async = True
    xmlHttp.open("GET", theUrl, true);

    // call send with no params as they were passed in on the url string
    xmlHttp.send(null);

    return;
}

// callback for share event
function tenorCallback_share(responsetext)
{
    // no action is needed in the share callback
}


// function to call the register share endpoint
function send_share(search_term,shared_gifs_id)
{
    // set the apikey and limit
    var apikey = "API_KEY";
    var clientkey = "my_test_app";

    var share_url = "https://tenor.googleapis.com/v2/registershare?id=" + shared_gifs_id + "&key=" + apikey + "&client_key=" + clientkey + "&q=" + search_term;

    httpGetAsync(share_url,tenorCallback_share);
}

// SUPPORT FUNCTIONS ABOVE
// MAIN BELOW

// grab search term from cookies or some other storage
search_term = "excited";

// GIF id from the shared gif
// shared_gifs_id = gif_json_response_object_from_search["results"][0]["id"]
shared_gifs_id = "16989471141791455574"; // example

// send the share notifcation back to Tenor
send_share(search_term,shared_gifs_id);

alert("share sent!");


</script>

<body>

</body>
</html>

Objective-C

NSString *apiKey = @"API_KEY";
NSString *clientKey = @"my_test_app";

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [self requestData];
  return YES;
}

/**
 Function for handling a user's selection of a GIF to share.
 In a production application, the GIF id should be the "id" field of the GIF response object that the user selected
 to share. The search term should be the user's last search.
 */
-(void)requestData
{


  // the test search term
  NSString *searchQuery = @"excited";
  NSString *gifId = @"16989471141791455574";

  //  Send the share event for the GIF id and search query
  NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/registershare?id=%d&key=%@&client_key=%@&q=%@", gifId, apiKey, clientKey, searchQuery];
  NSURL *searchUrl = [NSURL URLWithString:UrlString];
  NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl];
  [self makeWebRequest:searchRequest withCallback:tenorSearchResultsHandler];

  // Data will be loaded by each request's callback
}

/**
 Async URL requesting function.
 */
-(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback
{
  // Make the async request and pass the resulting json object to the callback
  NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NStopGifsError *jsonError = nil;
    NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

    if(jsonError != nil) {
      NSLog(@"%@", jsonError.localizedDescription);
      return;
    }

    // Push the results to our callback
    callback(jsonResult);
  }];

  [task resume];
}

/**
 Web response handler for registered shares
 */
void (^tenorShareResultsHandler)(NSDictionary *) = ^void(NSDictionary *response)
{
// no response expected from the registershare endpoint.
};

Parabéns! Você se integrou à Tenor API!

Uma multidão está de pé e comemora

Agora, vamos melhorar a experiência.

Etapa 3: enriquecer a experiência de pesquisa

Nesta etapa, revisamos as práticas recomendadas que ajudam a melhorar a experiência do usuário e aumentar as pesquisas e os compartilhamentos da sua integração do Tenor GIF.

Descobrimos que a melhor experiência inicial é exibir uma caixa de pesquisa limpa. Depois da caixa de pesquisa, exiba as categorias de GIFs, retiradas do endpoint de categorias e os termos de pesquisa em alta, do endpoint de termos de pesquisa em alta. Também é possível exibir GIFs em destaque no endpoint de GIFs em destaque abaixo da caixa de pesquisa.

Opcionalmente, é possível usar o parâmetro locale com o endpoint de categorias para ajustar os resultados para o idioma local. O valor padrão é en_US.

O exemplo a seguir busca categorias Tenor e GIFs em destaque para exibir ao usuário:

Curl

/* Featured GIFs call */
curl "https://tenor.googleapis.com/v2/featured?key=API_KEY&client_key=my_test_app"

/* categories call */
curl "https://tenor.googleapis.com/v2/categories?key=API_KEY&client_key=my_test_app"

Python

import requests
import json

# set the apikey and limit
apikey = "API_KEY"   # click to set to your apikey
ckey = "my_test_app"  # set the client_key for the integration
lmt = 10

# get the top 10 featured GIFs - using the default locale of en_US
r = requests.get("https://tenor.googleapis.com/v2/featured?key=%s&client_key=%s&limit=%s" % (apikey, ckey, lmt))

if r.status_code == 200:
    featured_gifs = json.loads(r.content)
else:
    featured_gifs = None

# get the current list of categories - using the default locale of en_US
r = requests.get("https://tenor.googleapis.com/v2/categories?key=%s&client_key=%s" % (apikey, ckey))

if r.status_code == 200:
    categories = json.loads(r.content)
else:
    categories = None

# load either the featured GIFs or categories below the search bar for the user
# for GIFs use the smaller formats for faster load times
print (featured_gifs)
print (categories)

Android/Java

import android.app.Application;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;

public class App extends Application {

    private static final String API_KEY = "API_KEY";
    private static final String CLIENT_KEY = "my_test_app";
    private static final String LogTag = "TenorTest";

    @Override
    public void onCreate() {
        super.onCreate();

        new Thread() {
            @Override
            public void run() {

                // get the top 10 featured GIFs
                JSONObject featuredGifs = getFeaturedGifs(10);

                // get the current list of categories
                JSONObject categories = getCategories();

                // load the results for the user
                Log.v(LogTag, "Featured GIFS: " + featuredGifs.toString());
                Log.v(LogTag, "GIF Categories: " + categories.toString());

            }
        }.start();
    }

    /**
     * Get featured GIFs
     */
    public static JSONObject getFeaturedGifs(int limit) {

        // get the Featured GIFS - using the default locale of en_US
        final String url = String.format("https://tenor.googleapis.com/v2/featured?key=%1$s&client_key=%2$s&limit=%3$s",
                API_KEY, CLIENT_KEY, limit);
        try {
            return get(url);
        } catch (IOException | JSONException ignored) {
        }
        return null;
    }

    /**
     * Get categories
     */
    public static JSONObject getCategories() {

        // get the categories - using the default locale of en_US
        final String url = String.format("https://tenor.googleapis.com/v2/categories?key=%1$s&client_key=%2$s",
                API_KEY, CLIENT_KEY);
        try {
            return get(url);
        } catch (IOException | JSONException ignored) {
        }
        return null;
    }

    /**
     * Construct and run a GET request
     */
    private static JSONObject get(String url) throws IOException, JSONException {
        HttpURLConnection connection = null;
        try {
            // Get request
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

            // Handle failure
            int statusCode = connection.getResponseCode();
            if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) {
                String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url);
                throw new ConnectException(error);
            }

            // Parse response
            return parser(connection);
        } catch (Exception ignored) {
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return new JSONObject("");
    }

    /**
     * Parse the response into JSONObject
     */
    private static JSONObject parser(HttpURLConnection connection) throws JSONException {
        char[] buffer = new char[1024 * 4];
        int n;
        InputStream stream = null;
        try {
            stream = new BufferedInputStream(connection.getInputStream());
            InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
            StringWriter writer = new StringWriter();
            while (-1 != (n = reader.read(buffer))) {
                writer.write(buffer, 0, n);
            }
            return new JSONObject(writer.toString());
        } catch (IOException ignored) {
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException ignored) {
                }
            }
        }
        return new JSONObject("");
    }
}

Swift 2.0+/iOS

let apikey = "API_KEY"
let clientkey = "my_test_app"

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    requestData()

    return true
  }

  /**
   Execute web requests to retrieve featured GIFs and GIF categories.
   */
  func requestData()
  {
    // Define the results upper limit
    let limit = 10

    // Get the top 10 featured GIFs (updated throughout the day) - using the default locale of en_US
    let featuredRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/featured?key=%@&client_key=%@&limit=%d",
                                                             apikey,
                                                             clientkey,
                                                             limit))!)
    makeWebRequest(urlRequest: featuredRequest, callback: tenorFeaturedResultsHandler)


    // Get the current list of categories - using the default locale of en_US
    let categoryRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/categories?key=%@&client_key=%@",
                                                             apikey, clientkey))!)
    makeWebRequest(urlRequest: categoryRequest, callback: tenorCategoryResultsHandler)

    // Data will be loaded by each request's callback
  }

  /**
   Async URL requesting function.
   */
  func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ())
  {
    // Make the async request and pass the resulting JSON object to the callback
    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
      do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] {
          // Push the results to our callback
          callback(jsonResult)
        }
      } catch let error as NSError {
        print(error.localizedDescription)
      }
    }
    task.resume()
  }

  /**
   Web response handler for featured top 10 GIFs.
   */
  func tenorFeaturedResultsHandler(response: [String:AnyObject])
  {
    // Parse the JSON response
    let topTenGifs = response["results"]!

    // Load the GIFs into your view
    print("Featured Results: (topTenGifs)")
  }

  /**
   Web response handler for GIF categories.
   */
  func tenorCategoryResultsHandler(response: [String:AnyObject])
  {
    // Parse the JSON response
    let categories = response["tags"]!

    // Load the categories into your view
    print("Category Results: (categories)")
  }

  }

JavaScript

<!DOCTYPE html>
<html>
<script>

// url Async requesting function
function httpGetAsync(theUrl, callback)
{
    // create the request object
    var xmlHttp = new XMLHttpRequest();

    // set the state change callback to capture when the response comes in
    xmlHttp.onreadystatechange = function()
    {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
        {
            callback(xmlHttp.responseText);
        }
    }

    // open as a GET call, pass in the url and set async = True
    xmlHttp.open("GET", theUrl, true);

    // call send with no params as they were passed in on the url string
    xmlHttp.send(null);

    return;
}

// callback for featured top 10 GIFs
function tenorCallback_featured(responsetext)
{
    // Parse the JSON response
    var response_objects = JSON.parse(responsetext);

    top_10_gifs = response_objects["results"];

    // load the GIFs -- for our example we will load the first GIFs preview size (nanogif) and share size (gif)

    document.getElementById("preview_gif").src = top_10_gifs[0]["media_formats"]["nanogif"]["url"];

    document.getElementById("share_gif").src = top_10_gifs[0]["media_formats"]["gif"]["url"];

    return;

}

// callback for GIF categories
function tenorCallback_categories(responsetext)
{
    // Parse the JSON response
    var response_objects = JSON.parse(responsetext);

    categories = response_objects["tags"];

    // load the categories - example is for the first category

    // url to load:
    var imgurl = categories[0]["image"];

    // text to overlay on image:
    var txt_overlay = categories[0]["name"];


    // search to run if user clicks the category
    var category_search_path = categories[0]["path"];

    document.getElementById("category_gif").src = imgurl
    document.getElementById("catgif_caption").innerHTML = txt_overlay
    document.getElementById("cat_link").href = category_search_path

    return;
}

// function to call the featured and category endpoints
function grab_data()
{
    // set the apikey and limit
    var apikey = "API_KEY";
    var clientkey = "my_test_app";
    var lmt = 10;

    // get the top 10 featured GIFs (updated throughout the day) - using the default locale of en_US
    var featured_url = "https://tenor.googleapis.com/v2/featured?key=" + apikey + "&client_key=" + clientkey + "&limit=" + lmt;


    httpGetAsync(featured_url,tenorCallback_featured);

    // get the current list of categories - using the default locale of en_US
    var cat_url = "https://tenor.googleapis.com/v2/categories?key=" + apikey + "&client_key=" + clientkey;

    httpGetAsync(cat_url,tenorCallback_categories);

    // data will be loaded by each call's callback
    return;
}


// SUPPORT FUNCTIONS ABOVE
// MAIN BELOW

// start the flow
grab_data();

</script>
<style>
.container {
    position: relative;
    text-align: center;
    color: white;
}
.title {
text-align: center;
}
.centered {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
</style>

<body>

<h2 class="title">GIF loaded - preview image</h2>
<div class="container">
<img id="preview_gif" src="" alt="" style="">
</div>

<h2 class="title">GIF loaded - share image</h2>
<div class="container">
<img id="share_gif" src="" alt="" style="">
</div>

<h2 class="title">GIF Category</h2>
<div class="container">
    <a id="cat_link" href="">
        <img id="category_gif" src="" alt="" style="">
        <div id="catgif_caption" class="centered"></div>
    </a>
</div>

</body>
</html>

Objective-C

NSString *apiKey = @"API_KEY";
NSString *clientKey = @"my_test_app";

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [self requestData];
  return YES;
}

/**
 Execute web requests to retrieve featured GIFs and GIF categories.
 */
-(void)requestData
{
  // Define the results upper limit
  int limit = 10;

  // Get the top 10 featured GIFs (updated throughout the day) - using the default locale of en_US
  NSString *featuredUrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/featured?key=%@&client_key=%@&limit=%d", apiKey, clientKey, limit];
  NSURL *featuredUrl = [NSURL URLWithString:featuredUrlString];
  NSURLRequest *featuredRequest = [NSURLRequest requestWithURL:featuredUrl];
  [self makeWebRequest:featuredRequest withCallback:tenorFeaturedResultsHandler];

  // Get the current list of categories - using the default locale of en_US
  NSString *categoryUrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/categories?key=%@&client_key=%@", apiKey, clientKey];
  NSURL *categoryUrl = [NSURL URLWithString:categoryUrlString];
  NSURLRequest *categoryRequest = [NSURLRequest requestWithURL:categoryUrl];
  [self makeWebRequest:categoryRequest withCallback:tenorCategoryResultsHandler];

  // Data will be loaded by each request's callback
}

/**
 Async URL requesting function.
 */
-(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback
{
  // Make the async request and pass the resulting JSON object to the callback
  NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NSError *jsonError = nil;
    NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

    if(jsonError != nil) {
      NSLog(@"%@", jsonError.localizedDescription);
      return;
    }

    // Push the results to our callback
    callback(jsonResult);
  }];

  [task resume];
}

/**
 Web response handler for featured top 10 GIFs.
 */
void (^tenorFeaturedResultsHandler)(NSDictionary *) = ^void(NSDictionary *response)
{
  // Parse the JSON response
  NSDictionary *topTenGifs = response[@"results"];

  // Load the GIFs into your view
  NSLog(@"Featured Results: %@", topTenGifs);
};

/**
 Web response handler for GIF categories.
 */
void (^tenorCategoryResultsHandler)(NSDictionary *) = ^void(NSDictionary *response)
{
  // Parse the JSON response
  NSDictionary *categories = response[@"tags"];

  // Load the categories into your view
  NSLog(@"Category Results: %@", categories);
};

B: sugestões de preenchimento automático

Se você exibir opções de pesquisa de preenchimento automático para os usuários enquanto eles digitam, os usuários poderão concluir pesquisas GIF mais rapidamente, o que aumenta o uso e a retenção de GIFs.

Recomendamos que você informe pelo menos dois caracteres e a localidade do usuário. O parâmetro locale ajusta os resultados para o idioma local. O valor padrão é en_US.

O exemplo a seguir chama o endpoint de Autocomplete com um termo de pesquisa parcial de exc. Os resultados são classificados pela probabilidade de gerar uma parcela para qualquer termo parcial.

Curl

/* autocomplete */
curl "https://tenor.googleapis.com/v2/autocomplete?key=API_KEY&client_key=my_test_app&q=exc"

Python

apikey = "API_KEY"   # click to set to your apikey
ckey = "my_test_app"  # set the client_key for the integration
lmt = 5

# partial search
psearch = "exc"

r = requests.get(
    "https://tenor.googleapis.com/v2/autocomplete?key=%s&client_key=%s&q=%s&limit=%s" % (apikey, ckey, psearch, lmt))

if r.status_code == 200:
    # return the search predictions
    search_term_list = json.loads(r.content)["results"]
    print(search_term_list)
else:
    # handle a possible error
    search_term_list = []

Android/Java

import android.app.Application;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;

public class App extends Application {

    private static final String API_KEY = "API_KEY";
    private static final String CLIENT_KEY = "my_test_app";
    private static final String LogTag = "TenorTest";

    @Override
    public void onCreate() {
        super.onCreate();

        new Thread() {
            @Override
            public void run() {

                // for testing, the partial search
                final String partialSearch = "exc";
                int limit = 5;

                // make the autocomplete call
                JSONObject autoCompleteResult = autoCompleteRequest(partialSearch, limit);

                // load the results for the user
                Log.v(LogTag, "AutoComplete Results: " + autoCompleteResult.toString());

            }
        }.start();
    }

    /**
     * Autocomplete Request
     */
    public static JSONObject autoCompleteRequest(String partialSearch, int limit) {

        // make an autocomplete request - using default locale of EN_US
        final String url = String.format("https://tenor.googleapis.com/v2/autocomplete?key=%1$s&client_key=%2$s&q=%3$s&limit=%4$s",
                API_KEY, CLIENT_KEY, partialSearch, limit);
        try {
            return get(url);
        } catch (IOException | JSONException ignored) {
        }
        return null;
    }

    /**
     * Construct and run a GET request
     */
    private static JSONObject get(String url) throws IOException, JSONException {
        HttpURLConnection connection = null;
        try {
            // Get request
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

            // Handle failure
            int statusCode = connection.getResponseCode();
            if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) {
                String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url);
                throw new ConnectException(error);
            }

            // Parse response
            return parser(connection);
        } catch (Exception ignored) {
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return new JSONObject("");
    }

    /**
     * Parse the response into JSONObject
     */
    private static JSONObject parser(HttpURLConnection connection) throws JSONException {
        char[] buffer = new char[1024 * 4];
        int n;
        InputStream stream = null;
        try {
            stream = new BufferedInputStream(connection.getInputStream());
            InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
            StringWriter writer = new StringWriter();
            while (-1 != (n = reader.read(buffer))) {
                writer.write(buffer, 0, n);
            }
            return new JSONObject(writer.toString());
        } catch (IOException ignored) {
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException ignored) {
                }
            }
        }
        return new JSONObject("");
    }
}

Swift 2.0+/iOS

let apikey = "API_KEY"
let clientkey = "my_test_app"

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    requestData()

    return true
  }

  /**
   Execute web requests to get autocomplete suggestions.
   */
  func requestData()
  {
    // for testing, the partial search
    let partialSearch = "exc"
    let limit = 5

    // Get up to 5 results from the autocomplete suggestions - using the default locale of en_US
    let autoRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/autocomplete?key=%@&client_key=%@&q=%@&limit=%d",
                                                             apikey,
                                                             clientkey,
                                                             partialSearch,
                                                             limit))!)
    makeWebRequest(urlRequest: autoRequest, callback: tenorAutoCompleteResultsHandler)

    // Data will be loaded by each request's callback
  }

  /**
   Async URL requesting function.
   */
  func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ())
  {
    // Make the async request and pass the resulting JSON object to the callback
    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
      do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] {
          // Push the results to our callback
          callback(jsonResult)
        }
      } catch let error as NSError {
        print(error.localizedDescription)
      }
    }
    task.resume()
  }

  /**
   Web response handler for autocomplete requests.
   */
  func tenorAutoCompleteResultsHandler(response: [String:AnyObject])
  {
    // Parse the JSON response
    let autoSuggestions = response["results"]!

    // Load the GIFs into your view
    print("Autocomplete Results: (autoSuggestions)")
  }

  }

JavaScript

<!DOCTYPE html>
<html>
<script>

// url Async requesting function
function httpGetAsync(theUrl, callback)
{
    // create the request object
    var xmlHttp = new XMLHttpRequest();

    // set the state change callback to capture when the response comes in
    xmlHttp.onreadystatechange = function()
    {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
        {
            callback(xmlHttp.responseText);
        }
    }

    // open as a GET call, pass in the url and set async = True
    xmlHttp.open("GET", theUrl, true);

    // call send with no params as they were passed in on the url string
    xmlHttp.send(null);

    return;
}

// callback for share event
function tenorCallback_autocomplete(responsetext)
{
    var response_objects = JSON.parse(responsetext);

    predicted_words = response_objects["results"];

    document.getElementById("ac_1").innerHTML = predicted_words[0];
    document.getElementById("ac_2").innerHTML = predicted_words[1];
}

// SUPPORT FUNCTIONS ABOVE
// MAIN BELOW

//partial search term
psearch_term = "exc";

// set the apikey and limit
var apikey = "API_KEY";
var clientkey = "my_test_app";
var lmt = 5;

// using default locale of en_US
var autoc_url = "https://tenor.googleapis.com/v2/autocomplete?key=" + apikey + "&client_key=" + clientkey + "&q=" + psearch_term + "&limit=" + lmt;

// send autocomplete request
httpGetAsync(autoc_url,tenorCallback_autocomplete);


</script>

<body>

<h2>Partial Search "exc":</h2>
<h3 id = "ac_1"></h3>
<h3 id = "ac_2"></h3>

</body>
</html>

Objective-C

NSString *apiKey = @"API_KEY";
NSString *clientKey = @"my_test_app";

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [self requestData];
  return YES;
}

/**
   Execute web requests to get autocomplete suggestions.
   */
-(void)requestData
{
  // Define the results upper limit
  int limit = 8;

  // the test search term
  NSString *partialSearch = @"exc";

  // Get the auto complete predictions for the given partial search - using the default locale of en_US
  NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/autocomplete?key=%@&client_key=%@&q=%@&limit=%d", apiKey, clientKey, partialSearch, limit];
  NSURL *searchUrl = [NSURL URLWithString:UrlString];
  NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl];
  [self makeWebRequest:searchRequest withCallback:tenorAutoCompleteResultsHandler];

  // Data will be loaded by each request's callback
}

/**
 Async URL requesting function.
 */
-(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback
{
  // Make the async request and pass the resulting JSON object to the callback
  NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NStopGifsError *jsonError = nil;
    NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

    if(jsonError != nil) {
      NSLog(@"%@", jsonError.localizedDescription);
      return;
    }

    // Push the results to our callback
    callback(jsonResult);
  }];

  [task resume];
}

/**
 Web response handler for auto complete predictions
 */
void (^tenorAutoCompleteResultsHandler)(NSDictionary *) = ^void(NSDictionary *response)
{
  // Parse the JSON response
  NSDictionary *results = response[@"results"];

  // Load the GIFs into your view
  NSLog(@"Auto Complete Result: %@", results);
};

C: Sugestões de pesquisa

As sugestões de pesquisa ajudam o usuário a restringir os termos de pesquisa ou descoberta para encontrar um GIF mais preciso.

Muitas vezes, os usuários não sabem exatamente o que estão procurando, e as sugestões de pesquisa ajudam a corrigir erros de ortografia ou encontram termos mais semelhantes.

A API retorna resultados na ordem de probabilidade de gerar um compartilhamento de GIF para um determinado período. O exemplo a seguir retorna as cinco principais sugestões de pesquisa para o termo de pesquisa smile:

Curl

/* search suggestion */
curl "https://tenor.googleapis.com/v2/search_suggestions?key=API_KEY&client_key=my_test_app&q=smile&limit=5"

Python

# set the apikey and limit the # coming back
apikey = "API_KEY"   # click to set to your apikey
ckey = "my_test_app"  # set the client_key for the integration
lmt = 5

# partial search
search = "smile"

r = requests.get(
 "https://tenor.googleapis.com/v2/search_suggestions?key=%s&client_key=%s&q=%s&limit=%s" % (apikey, ckey, search, lmt))

if r.status_code == 200:
    # return the search suggestions
    search_suggestion_list = json.loads(r.content)["results"]
    print search_suggestion_list
else:
    # handle a possible error
    search_suggestion_list = []

Android/Java

import android.app.Application;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;

public class App extends Application {

    private static final String API_KEY = "API_KEY";
    private static final String CLIENT_KEY = "my_test_app";
    private static final String LogTag = "TenorTest";

    @Override
    public void onCreate() {
        super.onCreate();

        new Thread() {
            @Override
            public void run() {

                // for testing, the last search
                final String lastSearch = "smile";
                int limit = 5;

                // make the search suggestion call
                JSONObject searchSuggestionResult = searchSuggestionRequest(lastSearch, limit);

                // load the results for the user
                Log.v(LogTag, "Search Suggestion Results: " + searchSuggestionResult.toString());

            }
        }.start();
    }

    /**
     * Autocomplete Request
     */
    public static JSONObject searchSuggestionRequest(String lastSearch, int limit) {

        // make an autocomplete request - using default locale of EN_US
        final String url = String.format("https://tenor.googleapis.com/v2/search_suggestions?key=%1$s&client_key=%2$s&q=%3$s&limit=%4$s",
                API_KEY, CLIENT_KEY, lastSearch, limit);
        try {
            return get(url);
        } catch (IOException | JSONException ignored) {
        }
        return null;
    }

    /**
     * Construct and run a GET request
     */
    private static JSONObject get(String url) throws IOException, JSONException {
        HttpURLConnection connection = null;
        try {
            // Get request
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

            // Handle failure
            int statusCode = connection.getResponseCode();
            if (statusCode != HttpURLConnection.HTTP_OK && statusCode != HttpURLConnection.HTTP_CREATED) {
                String error = String.format("HTTP Code: '%1$s' from '%2$s'", statusCode, url);
                throw new ConnectException(error);
            }

            // Parse response
            return parser(connection);
        } catch (Exception ignored) {
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return new JSONObject("");
    }

    /**
     * Parse the response into JSONObject
     */
    private static JSONObject parser(HttpURLConnection connection) throws JSONException {
        char[] buffer = new char[1024 * 4];
        int n;
        InputStream stream = null;
        try {
            stream = new BufferedInputStream(connection.getInputStream());
            InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
            StringWriter writer = new StringWriter();
            while (-1 != (n = reader.read(buffer))) {
                writer.write(buffer, 0, n);
            }
            return new JSONObject(writer.toString());
        } catch (IOException ignored) {
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException ignored) {
                }
            }
        }
        return new JSONObject("");
    }
}

Swift 2.0+/iOS

let apikey = "API_KEY"
let clientkey = "my_test_app"

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    requestData()

    return true
  }

  /**
   Execute web requests to get search suggestions.
   */
  func requestData()
  {
    // for testing, the partial search
    let lastsearch = "smile"
    let limit = 5

    // Get the top 5 search suggestions - using the default locale of en_US
    let suggestRequest = URLRequest(url: URL(string: String(format: "https://tenor.googleapis.com/v2/search_suggestions?key=%@&client_key=%@&q=%@&limit=%d",
                                                             apikey,
                                                             clientkey,
                                                             lastsearch,
                                                             limit))!)
    makeWebRequest(urlRequest: suggestRequest, callback: tenorSuggestResultsHandler)

    // Data will be loaded by each request's callback
  }

  /**
   Async URL requesting function.
   */
  func makeWebRequest(urlRequest: URLRequest, callback: @escaping ([String:AnyObject]) -> ())
  {
    // Make the async request and pass the resulting JSON object to the callback
    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
      do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] {
          // Push the results to our callback
          callback(jsonResult)
        }
      } catch let error as NSError {
        print(error.localizedDescription)
      }
    }
    task.resume()
  }

  /**
   Web response handler for search suggestion requests.
   */
  func tenorSuggestResultsHandler(response: [String:AnyObject])
  {
    // Parse the JSON response
    let searchSuggestion = response["results"]!

    // Load the GIFs into your view
    print("Search Suggestion Results: (searchSuggestion)")
  }

  }

JavaScript

<!DOCTYPE html>
<html>
<script>

// url Async requesting function
function httpGetAsync(theUrl, callback)
{
    // create the request object
    var xmlHttp = new XMLHttpRequest();

    // set the state change callback to capture when the response comes in
    xmlHttp.onreadystatechange = function()
    {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
        {
            callback(xmlHttp.responseText);
        }
    }

    // open as a GET call, pass in the url and set async = True
    xmlHttp.open("GET", theUrl, true);

    // call send with no params as they were passed in on the url string
    xmlHttp.send(null);

    return;
}

// callback for share event
function tenorCallback_searchSuggestion(responsetext)
{
    var response_objects = JSON.parse(responsetext);

    predicted_words = response_objects["results"];

    document.getElementById("ac_1").innerHTML = predicted_words[0];
    document.getElementById("ac_2").innerHTML = predicted_words[1];
    document.getElementById("ac_3").innerHTML = predicted_words[2];
    document.getElementById("ac_4").innerHTML = predicted_words[3];
}


// SUPPORT FUNCTIONS ABOVE
// MAIN BELOW

//search term
psearch_term = "smile";

// set the apikey and limit
var apikey = "API_KEY";
var clientkey = "my_test_app";
var lmt = 5;

// using default locale of en_US
var autoc_url = "https://tenor.googleapis.com/v2/search_suggestions?key=" + apikey + "&client_key=" + clientkey + "&q=" + psearch_term + "&limit=" + lmt;

// send search suggestion request
httpGetAsync(autoc_url,tenorCallback_searchSuggestion);


</script>

<body>

<h2>Search Suggestion for "smile":</h2>
<h3 id = "ac_1"></h3>
<h3 id = "ac_2"></h3>
<h3 id = "ac_3"></h3>
<h3 id = "ac_4"></h3>

</body>
</html>

Objective-C

NSString *apiKey = @"API_KEY";
NSString *clientKey = @"my_test_app";

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  [self requestData];
  return YES;
}

/**
   Execute web requests to get search suggestions.
   */
-(void)requestData
{
  // Define the results upper limit
  int limit = 5;

  // the test search term
  NSString *lastSearch = @"smile";

  // Get the search suggestions for the given last search - using the default locale of en_US
  NSString *UrlString = [NSString stringWithFormat:@"https://tenor.googleapis.com/v2/search_suggestions?key=%@&client_key=%@&q=%@&limit=%d", apiKey, clientKey, lastSearch, limit];
  NSURL *searchUrl = [NSURL URLWithString:UrlString];
  NSURLRequest *searchRequest = [NSURLRequest requestWithURL:searchUrl];
  [self makeWebRequest:searchRequest withCallback:tenorSearchSuggestionResultsHandler];

  // Data will be loaded by each request's callback
}

/**
 Async URL requesting function.
 */
-(void)makeWebRequest:(NSURLRequest *)urlRequest withCallback:(void (^)(NSDictionary *))callback
{
  // Make the async request and pass the resulting JSON object to the callback
  NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NStopGifsError *jsonError = nil;
    NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

    if(jsonError != nil) {
      NSLog(@"%@", jsonError.localizedDescription);
      return;
    }

    // Push the results to our callback
    callback(jsonResult);
  }];

  [task resume];
}

/**
 Web response handler for search suggestions
 */
void (^tenorSearchSuggestionResultsHandler)(NSDictionary *) = ^void(NSDictionary *response)
{
  // Parse the JSON response
  NSDictionary *results = response[@"results"];

  // Load the GIFs into your view
  NSLog(@"Search Suggestion Result: %@", results);
};