@WorkerThread
    @NonNull
    public static ImageResult addLogImage(final String logId, final Image image) {
        //1) Get CSRF Token from "Edit Log" page. URL is https://www.geocaching.com/live/log/GLxyz
        final String csrfToken = getCsrfToken();
        if (csrfToken == null) {
            Log.w("Log Image Post: unable to extract CSRF Token in new Log Flow Page");
            return generateImageLogError("No CSRFToken found");
        }

        //2) Create a new "image" attached to the log, uploading only image data
        //   (Do not yet upload name + description, for some reason this results in a server timeout)
        // via POST to https://www.geocaching.com/api/live/v1/logs/GLxyz/images with image payload
        try (GCWebLogImageResponse imgResponse = websiteReq().uri("/api/live/v1/logs/" + logId + "/images")
                .method(HttpRequest.Method.POST)
                .headers(HTML_HEADER_CSRF_TOKEN, csrfToken)
                .bodyForm(null, "image", "image/jpeg", image.getFile())
                .requestJson(GCWebLogImageResponse.class).blockingGet()) {
            if (imgResponse.guid == null || imgResponse.url == null) {
                return generateImageLogError("Problem posting image, logId='" + logId + "', response is: " + imgResponse);
            }

            //3) Post the image name + description via PUT
            final ImageResult resp = putChangeImageData(logId, imgResponse.guid + "::", csrfToken, image.getTitle(), image.getDescription());
            if (resp != null) {
                return resp;
            }

            return ImageResult.ok(imgResponse.url, getLogImageId(imgResponse.guid, null));
        }
    }
Provides methods to handle all aspects of creating, editing and deleting Log entries for GC.com (both caches and trackables)
main/src/main/java/cgeo/geocaching/connector/gc/GCLogAPI.java