src/main/java/com/fooock/shodan/model/host/HostReport.java
public class HostReport {

    private final int total;

    @SerializedName("matches")
    private final List<Banner> banners;
    private final FacetReport facets;

    public HostReport(int total, List<Banner> hosts, FacetReport facets) {
        this.total = total;
        this.banners = hosts;
        this.facets = facets;
    }

    public List<Banner> getBanners() {
        return banners;
    }

    public FacetReport getFacet() {
        return facets;
    }

    public int getTotal() {
        return total;
    }

    @Override
    public String toString() {
        return "HostReport{" +
                "total=" + total +
                ", banners=" + banners +
                ", facets=" + facets +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/protocol/Protocol.java
public class Protocol {

    private final String name;
    private final String description;

    Protocol(String name, String description) {
        this.name = name;
        this.description = description;
    }

    /**
     * @return Name of the protocol
     */
    public String getName() {
        return name;
    }

    /**
     * @return Basic description of the protocol
     */
    public String getDescription() {
        return description;
    }

    @Override
    public String toString() {
        return "Protocol{" +
                "name='" + name + '\'' +
                ", description='" + description + '\'' +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/tag/TagReport.java
public class TagReport {

    private final int total;

    @SerializedName("matches")
    private final List<Property> tags;

    TagReport(int total, List<Property> tags) {
        this.total = total;
        this.tags = tags;
    }

    public List<Property> getTags() {
        return tags;
    }

    public int getTotal() {
        return total;
    }

    @Override
    public String toString() {
        return "TagReport{" +
                "total=" + total +
                ", tags=" + tags +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/token/TokenReport.java
public class TokenReport {

    @SerializedName("string")
    private String query;

    private String[] filters;
    private String[] errors;

    private Attributes attributes;

    TokenReport() {

    }

    public String getQuery() {
        return query;
    }

    public String[] getFilters() {
        return filters;
    }

    public String[] getErrors() {
        return errors;
    }

    public Attributes getAttributes() {
        return attributes;
    }

    @Override
    public String toString() {
        return "TokenReport{" +
                "query='" + query + '\'' +
                ", filters=" + Arrays.toString(filters) +
                ", errors=" + Arrays.toString(errors) +
                ", attributes=" + attributes +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/host/Host.java
public class Host {

    private long ip;

    private double latitude;
    private double longitude;

    private int[] ports;

    private String[] hostnames;
    private String[] tags;

    @SerializedName("vulns")
    private String[] vulnerabilities;

    @SerializedName("region_code")
    private String regionCode;

    @SerializedName("area_code")
    private String areaCode;

    @SerializedName("postal_code")
    private String postalCode;

    @SerializedName("dma_code")
    private String dmaCode;

    @SerializedName("country_code")
    private String countryCode;

    @SerializedName("org")
    private String organization;
    private String asn;
    private String city;
    private String isp;

    @SerializedName("last_update")
    private String lastUpdate;

    @SerializedName("country_code3")
    private String countryCode3;

    @SerializedName("country_name")
    private String countryName;

    @SerializedName("ip_str")
    private String ipStr;
    private String os;

    @SerializedName("data")
    private List<Banner> banners;

    Host() {

    }

    public long getIp() {
        return ip;
    }

    public double getLatitude() {
        return latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public int[] getPorts() {
        return ports;
    }

    public String[] getHostnames() {
        return hostnames;
    }

    public String[] getTags() {
        return tags;
    }

    public String[] getVulnerabilities() {
        return vulnerabilities;
    }

    public String getRegionCode() {
        return regionCode;
    }

    public String getAreaCode() {
        return areaCode;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public String getDmaCode() {
        return dmaCode;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public String getOrganization() {
        return organization;
    }

    public String getAsn() {
        return asn;
    }

    public String getCity() {
        return city;
    }

    public String getIsp() {
        return isp;
    }

    public String getLastUpdate() {
        return lastUpdate;
    }

    public String getCountryCode3() {
        return countryCode3;
    }

    public String getCountryName() {
        return countryName;
    }

    public String getIpStr() {
        return ipStr;
    }

    public String getOs() {
        return os;
    }

    public List<Banner> getBanners() {
        return banners;
    }

    @Override
    public String toString() {
        return "Host{" +
                "ip=" + ip +
                ", latitude=" + latitude +
                ", longitude=" + longitude +
                ", ports=" + Arrays.toString(ports) +
                ", hostnames=" + Arrays.toString(hostnames) +
                ", tags=" + Arrays.toString(tags) +
                ", vulnerabilities=" + Arrays.toString(vulnerabilities) +
                ", regionCode='" + regionCode + '\'' +
                ", areaCode='" + areaCode + '\'' +
                ", postalCode='" + postalCode + '\'' +
                ", dmaCode='" + dmaCode + '\'' +
                ", countryCode='" + countryCode + '\'' +
                ", organization='" + organization + '\'' +
                ", asn='" + asn + '\'' +
                ", city='" + city + '\'' +
                ", isp='" + isp + '\'' +
                ", lastUpdate='" + lastUpdate + '\'' +
                ", countryCode3='" + countryCode3 + '\'' +
                ", countryName='" + countryName + '\'' +
                ", ipStr='" + ipStr + '\'' +
                ", os='" + os + '\'' +
                ", banners=" + banners +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/query/QueryReport.java
public class QueryReport {

    private final int total;

    @SerializedName("matches")
    private final List<Query> queries;

    public QueryReport(int total, List<Query> queries) {
        this.total = total;
        this.queries = queries;
    }

    public int getTotal() {
        return total;
    }

    public List<Query> getQueries() {
        return queries;
    }

    @Override
    public String toString() {
        return "QueryReport{" +
                "total=" + total +
                ", queries=" + queries +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/host/FacetReport.java
public class FacetReport {

    private final int total;
    private final List<Facet> facets;

    FacetReport(int total, List<Facet> facets) {
        this.total = total;
        this.facets = facets;
    }

    public int getTotal() {
        return total;
    }

    public List<Facet> getFacets() {
        return facets;
    }

    @Override
    public String toString() {
        return "FacetReport{" +
                "total=" + total +
                ", facets=" + facets +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/user/HttpHeader.java
public class HttpHeader {

    private final List<Value> headers;

    HttpHeader(List<Value> headers) {
        this.headers = headers;
    }

    public List<Value> getHeaders() {
        return headers;
    }
}
src/main/java/com/fooock/shodan/model/user/ApiStatus.java
public class ApiStatus {

    private boolean https;
    private boolean unlocked;
    private boolean telnet;

    @SerializedName("query_credits")
    private int queryCredits;

    @SerializedName("scan_credits")
    private int scanCredits;

    private String plan;

    ApiStatus() {

    }

    public boolean isHttps() {
        return https;
    }

    void setHttps(boolean https) {
        this.https = https;
    }

    public boolean isUnlocked() {
        return unlocked;
    }

    void setUnlocked(boolean unlocked) {
        this.unlocked = unlocked;
    }

    public boolean isTelnet() {
        return telnet;
    }

    void setTelnet(boolean telnet) {
        this.telnet = telnet;
    }

    public int getQueryCredits() {
        return queryCredits;
    }

    void setQueryCredits(int queryCredits) {
        this.queryCredits = queryCredits;
    }

    public int getScanCredits() {
        return scanCredits;
    }

    void setScanCredits(int scanCredits) {
        this.scanCredits = scanCredits;
    }

    public String getPlan() {
        return plan;
    }

    void setPlan(String plan) {
        this.plan = plan;
    }

    @Override
    public String toString() {
        return "ApiStatus{" +
                "https=" + https +
                ", unlocked=" + unlocked +
                ", telnet=" + telnet +
                ", queryCredits=" + queryCredits +
                ", scanCredits=" + scanCredits +
                ", plan='" + plan + '\'' +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/dns/DnsIp.java
public class DnsIp {

    private final String hostname;
    private final String ip;

    DnsIp(String hostname, String ip) {
        this.hostname = hostname;
        this.ip = ip;
    }

    public String getHostname() {
        return hostname;
    }

    public String getIp() {
        return ip;
    }

    @Override
    public String toString() {
        return "DnsIp{" +
                "hostname='" + hostname + '\'' +
                ", ip='" + ip + '\'' +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/user/Account.java
public class Account {

    private final int credits;
    private final boolean member;

    @SerializedName("display_name")
    private final String displayName;
    private final String created;

    Account(boolean member, int credits, String displayName, String created) {
        this.member = member;
        this.credits = credits;
        this.displayName = displayName;
        this.created = created;
    }

    public boolean isMember() {
        return member;
    }

    public int getCredits() {
        return credits;
    }

    public String getDisplayName() {
        return displayName;
    }

    public String getCreated() {
        return created;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Account account = (Account) o;

        if (credits != account.credits) {
            return false;
        }
        if (member != account.member) {
            return false;
        }
        if (displayName != null ? !displayName.equals(account.displayName)
                : account.displayName != null) {
            return false;
        }
        return created.equals(account.created);
    }

    @Override
    public int hashCode() {
        int result = credits;
        result = 31 * result + (member ? 1 : 0);
        result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
        result = 31 * result + created.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "Account{" +
                "credits=" + credits +
                ", member=" + member +
                ", displayName='" + displayName + '\'' +
                ", created='" + created + '\'' +
                '}';
    }
}
src/main/java/com/fooock/shodan/model/dns/DnsHostname.java
public class DnsHostname {

    private final String ip;
    private final String[] hostnames;

    DnsHostname(String ip, String[] hostnames) {
        this.ip = ip;
        this.hostnames = hostnames;
    }

    public String getIp() {
        return ip;
    }

    public String[] getHostnames() {
        return hostnames;
    }

    @Override
    public String toString() {
        return "DnsHostname{" +
                "ip='" + ip + '\'' +
                ", hostnames=" + Arrays.toString(hostnames) +
                '}';
    }
}


Question: import com.fooock.shodan.model.query.QueryReport;
import com.fooock.shodan.model.tag.TagReport;
import com.fooock.shodan.model.token.TokenReport;
import com.fooock.shodan.model.user.Account;
import com.fooock.shodan.model.user.ApiStatus;
import com.fooock.shodan.model.user.HttpHeader;
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
import java.util.List;
import com.fooock.shodan.model.dns.DnsHostname;
import com.fooock.shodan.model.dns.DnsIp;
import com.fooock.shodan.model.host.FacetReport;
import com.fooock.shodan.model.host.Host;
import com.fooock.shodan.model.host.HostReport;
import com.fooock.shodan.model.protocol.Protocol;
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2017 Newhouse (nhitbh at gmail dot com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.fooock.shodan;



/**
 * This API provides methods to queries Shodan, look up hosts, get summary information on queries
 * and a variety of utility methods to make developing easier
 */
public interface ApiService {

    /**
     * This method returns an object containing all the protocols that can be used when launching an
     * Internet scan.
     *
     * @param apiKey account api key
     */
    @GET("shodan/protocols")
    Observable<List<Protocol>> protocols(@Query(Constants.KEY) String apiKey);

    /**
     * Look up the hostnames that have been defined for the given list of IP addresses.
     *
     * @param apiKey account api key
     * @param ips    Comma-separated list of IP addresses; example "74.125.227.230,204.79.197.200"
     */
    @GET("dns/reverse")
    Observable<List<DnsHostname>> reverseDns(@Query(Constants.KEY) String apiKey,
                                             @Query(Constants.IPS) String ips);

    /**
     * Look up the IP address for the provided list of hostnames.
     *
     * @param apiKey    account api key
     * @param hostnames Comma-separated list of hostnames; example "google.com,bing.com"
     */
    @GET("dns/resolve")
    Observable<List<DnsIp>> resolveDns(@Query(Constants.KEY) String apiKey,
                                       @Query(Constants.HOSTNAMES) String hostnames);

    /**
     * This method returns a list of port numbers that the crawlers are looking for.
     *
     * @param apiKey account api key
     */
    @GET("shodan/ports")
    Observable<List<Integer>> ports(@Query(Constants.KEY) String apiKey);

    /**
     * This method lets you determine which filters are being used by the query string and what
     * parameters were provided to the filters.
     *
     * @param apiKey account api key
     * @param query  Shodan search query. The provided string is used to search the database of banners
     *               in Shodan, with the additional option to provide filters inside the search query using a
     *               "filter:value" format.
     */
    @GET("shodan/host/search/tokens")
    Observable<TokenReport> tokens(@Query(Constants.KEY) String apiKey,
                                   @Query(Constants.QUERY) String query);

    /**
     * Use this method to obtain a list of search queries that users have saved in Shodan.
     *
     * @param apiKey account api key
     */
    @GET("shodan/query")
    Observable<QueryReport> queries(@Query(Constants.KEY) String apiKey);

    /**
     * Use this method to obtain a list of search queries that users have saved in Shodan.
     *
     * @param apiKey account api key
     * @param page   Page number to iterate over results; each page contains 10 items
     */
    @GET("shodan/query")
    Observable<QueryReport> queries(@Query(Constants.KEY) String apiKey,
                                    @Query(Constants.PAGE) int page);

    /**
     * Use this method to obtain a list of search queries that users have saved in Shodan.
     *
     * @param apiKey account api key
     * @param page   Page number to iterate over results; each page contains 10 items
     * @param sort   Sort the list based on a property. Possible values are: votes, timestamp
     */
    @GET("shodan/query")
    Observable<QueryReport> queries(@Query(Constants.KEY) String apiKey,
                                    @Query(Constants.PAGE) int page,
                                    @Query(Constants.SORT) String sort);

    /**
     * Use this method to obtain a list of search queries that users have saved in Shodan.
     *
     * @param apiKey account api key
     * @param page   Page number to iterate over results; each page contains 10 items
     * @param sort   Sort the list based on a property. Possible values are: votes, timestamp
     * @param order  Whether to sort the list in ascending or descending order. Possible values are:
     *               asc, desc
     */
    @GET("shodan/query")
    Observable<QueryReport> queries(@Query(Constants.KEY) String apiKey,
                                    @Query(Constants.PAGE) int page,
                                    @Query(Constants.SORT) String sort,
                                    @Query(Constants.ORDER) String order);

    /**
     * Use this method to queries the directory of queries that users have saved in Shodan. For
     * default this method only return the first ten queries
     *
     * @param apiKey account api key
     * @param query  What to queries for in the directory of saved queries queries.
     */
    @GET("shodan/query/search")
    Observable<QueryReport> searches(@Query(Constants.KEY) String apiKey,
                                     @Query(Constants.QUERY) String query);

    /**
     * Use this method to queries the directory of queries that users have saved in Shodan.
     *
     * @param apiKey account api key
     * @param query  What to queries for in the directory of saved queries queries.
     * @param page   Page number to iterate over results; each page contains 10 items
     */
    @GET("shodan/query/search")
    Observable<QueryReport> searches(@Query(Constants.KEY) String apiKey,
                                     @Query(Constants.QUERY) String query,
                                     @Query(Constants.PAGE) int page);

    /**
     * Use this method to obtain a list of popular tags for the saved queries in Shodan. This method
     * only return the first ten tags
     *
     * @param apiKey account api key
     */
    @GET("shodan/query/tags")
    Observable<TagReport> tags(@Query(Constants.KEY) String apiKey);

    /**
     * Use this method to obtain a list of popular tags for the saved queries in Shodan.
     *
     * @param apiKey    account api key
     * @param tagNumber The number of tags to return (default 10).
     */
    @GET("shodan/query/tags")
    Observable<TagReport> tags(@Query(Constants.KEY) String apiKey,
                               @Query(Constants.SIZE) int tagNumber);

    /**
     * Returns all services that have been found on the given host IP.
     *
     * @param ip     Host IP address
     * @param apiKey account api key
     */
    @GET("shodan/host/{ip}")
    Observable<Host> hostByIp(@Path(Constants.IP) String ip, @Query(Constants.KEY) String apiKey);

    /**
     * Returns all services that have been found on the given host IP with all historical data if the
     * history param is true (default is false)
     *
     * @param ip      Host IP address
     * @param apiKey  account api key
     * @param history True if all historical banners should be returned (default false)
     */
    @GET("shodan/host/{ip}")
    Observable<Host> hostByIp(@Path(Constants.IP) String ip,
                              @Query(Constants.KEY) String apiKey,
                              @Query(Constants.HISTORY) boolean history);

    /**
     * Returns all services that have been found on the given host IP. If the minify param is true
     * this method returns only the list of ports and the general host information, no banners. If the
     * history param is true and minify also, then the history not takes effect
     *
     * @param ip      Host IP address
     * @param apiKey  account api key
     * @param history True if all historical banners should be returned (default false)
     * @param minify  True to only return the list of ports and the general host information, no
     *                banners (default false)
     */
    @GET("shodan/host/{ip}")
    Observable<Host> hostByIp(@Path(Constants.IP) String ip,
                              @Query(Constants.KEY) String apiKey,
                              @Query(Constants.HISTORY) boolean history,
                              @Query(Constants.MINIFY) boolean minify);

    /**
     * This method behaves identical to "/shodan/host/search" with the only difference that this
     * method does not return any host results, it only returns the total number of results that
     * matched the query and any facet information that was requested. As a result this method does
     * not consume query credits.
     *
     * @param apiKey account api key
     * @param query  Shodan search query. The provided string is used to search the database of banners
     *               in Shodan, with the additional option to provide filters inside the search query using a
     *               "filter:value" format
     */
    @GET("shodan/host/count")
    Observable<FacetReport> hostCount(@Query(Constants.KEY) String apiKey,
                                      @Query(Constants.QUERY) String query);

    /**
     * This method behaves identical to "/shodan/host/search" with the only difference that this
     * method does not return any host results, it only returns the total number of results that
     * matched the query and any facet information that was requested. As a result this method does
     * not consume query credits.
     *
     * @param apiKey account api key
     * @param query  Shodan search query. The provided string is used to search the database of banners
     *               in Shodan, with the additional option to provide filters inside the search query using a
     *               "filter:value" format
     * @param facets A comma-separated list of properties to get summary information on. Property
     *               names can also be in the format of "property:count", where "count" is the number of facets that
     *               will be returned for a property
     */
    @GET("shodan/host/count")
    Observable<FacetReport> hostCount(@Query(Constants.KEY) String apiKey,
                                      @Query(Constants.QUERY) String query,
                                      @Query(Constants.FACETS) String facets);

    /**
     * Search Shodan using the same query syntax as the website and use facets to get summary
     * information for different properties. This method may use API query credits depending on usage.
     * If any of the following criteria are met, your account will be deducated 1 query credit: <ul>
     * <li>The search query contains a filter.</li> <li>Accessing results past the 1st page using the
     * "page". For every 100 results past the 1st page 1 query credit is deducted.</li> </ul>
     *
     * @param apiKey account api key
     * @param query  Shodan search query. The provided string is used to search the database of banners
     *               in Shodan, with the additional option to provide filters inside the search query using a
     *               "filter:value" format.
     */
    @GET("shodan/host/search")
    Observable<HostReport> hostSearch(@Query(Constants.KEY) String apiKey,
                                      @Query(Constants.QUERY) String query);

    /**
     * Search Shodan using the same query syntax as the website and use facets to get summary
     * information for different properties. This method may use API query credits depending on usage.
     * If any of the following criteria are met, your account will be deducated 1 query credit: <ul>
     * <li>The search query contains a filter.</li> <li>Accessing results past the 1st page using the
     * "page". For every 100 results past the 1st page 1 query credit is deducted.</li> </ul>
     *
     * @param apiKey account api key
     * @param query  Shodan search query. The provided string is used to search the database of banners
     *               in Shodan, with the additional option to provide filters inside the search query using a
     *               "filter:value" format.
     * @param facets A comma-separated list of properties to get summary information on. Property
     *               names can also be in the format of "property:count", where "count" is the number of facets that
     *               will be returned for a property
     */
    @GET("shodan/host/search")
    Observable<HostReport> hostSearch(@Query(Constants.KEY) String apiKey,
                                      @Query(Constants.QUERY) String query,
                                      @Query(Constants.FACETS) String facets);

    /**
     * Search Shodan using the same query syntax as the website and use facets to get summary
     * information for different properties. This method may use API query credits depending on usage.
     * If any of the following criteria are met, your account will be deducated 1 query credit: <ul>
     * <li>The search query contains a filter.</li> <li>Accessing results past the 1st page using the
     * "page". For every 100 results past the 1st page 1 query credit is deducted.</li> </ul>
     *
     * @param apiKey account api key
     * @param query  Shodan search query. The provided string is used to search the database of banners
     *               in Shodan, with the additional option to provide filters inside the search query using a
     *               "filter:value" format.
     * @param facets A comma-separated list of properties to get summary information on. Property
     *               names can also be in the format of "property:count", where "count" is the number of facets that
     *               will be returned for a property
     * @param page   The page number to page through results 100 at a time (default: 1)
     */
    @GET("shodan/host/search")
    Observable<HostReport> hostSearch(@Query(Constants.KEY) String apiKey,
                                      @Query(Constants.QUERY) String query,
                                      @Query(Constants.FACETS) String facets,
                                      @Query(Constants.PAGE) int page);

    /**
     * Returns information about the Shodan account linked to the api key.
     *
     * @param apiKey account api key
     */
    @GET("account/profile")
    Observable<Account> account(@Query(Constants.KEY) String apiKey);

    /**
     * Returns information about the API plan belonging to the given API key.
     *
     * @param apiKey account api key
     */
    @GET("api-info")
Answer:     Observable<ApiStatus> info(@Query(Constants.KEY) String apiKey);