@NonNull
    @WorkerThread
    private static SearchResult retrieveCaches(@NonNull final OCApiConnector connector, @NonNull final GeocacheFilter filter, final int take, final int skip) {

        final List<BaseGeocacheFilter> filters = filter.getAndChainIfPossible();

        final Geopoint searchCoords;
        final String radius;

        final DistanceGeocacheFilter df = GeocacheFilter.findInChain(filters, DistanceGeocacheFilter.class);
        if (df != null) {
            searchCoords = df.getEffectiveCoordinate();
            radius = df.getMaxRangeValue() == null ? DEFAULT_RADIUS : "" + (df.getMaxRangeValue().intValue() * 1000);
        } else {
            // search around current position by default
            searchCoords = null;
            radius = DEFAULT_RADIUS;
        }

        //fill in the defaults
        final Parameters params = new Parameters("search_method", METHOD_SEARCH_ALL);
        final Map<String, String> valueMap = new LinkedHashMap<>();
        valueMap.put("limit", "" + take);
        valueMap.put("offset", "" + skip);
        fillSearchParameterCenter(valueMap, params, searchCoords, radius);

        String finder = null;

        for (BaseGeocacheFilter baseFilter : filter.getAndChainIfPossible()) {
            if (baseFilter instanceof OriginGeocacheFilter && !((OriginGeocacheFilter) baseFilter).allowsCachesOf(connector)) {
                return new SearchResult(); //no need to search if connector is filtered out itself
            }
            if (baseFilter instanceof LogEntryGeocacheFilter) {
                finder = ((LogEntryGeocacheFilter) baseFilter).getFoundByUser();
            }
            fillForBasicFilter(baseFilter, params, valueMap, connector);
        }

        //do the search
        final Pair<List<Geocache>, Boolean> rawResult = requestCachesWithMore(connector, params, valueMap, true);
        final SearchResult result = new SearchResult(rawResult.first);

        //store metainfo needed for later for paging
        result.setLeftToFetch(connector, rawResult.second ? 1 : 0);
        result.setPartialResult(connector, rawResult.second);
        result.setToContext(connector, b -> b.putString(SEARCH_CONTEXT_FILTER, filter.toConfig()));
        result.setToContext(connector, b -> b.putInt(SEARCH_CONTEXT_TOOK_TOTAL, skip + rawResult.first.size()));

        if (finder != null) {
            final SearchCacheData scd = new SearchCacheData();
            scd.addFoundBy(finder);
            result.setCacheData(scd);
        }
        return result;

    }
Client for the OpenCaching API (Okapi).

@see <a href="http://www.opencaching.de/okapi/introduction.html">Okapi overview</a>
main/src/main/java/cgeo/geocaching/connector/oc/OkapiClient.java