Java

Java examples

Six examples ready to copy, from the first call to error handling, with the hosted sample certificate (fictitious data).

Before you start

Three steps, once.

  1. Create an API key

    In the panel, under API Keys.

  2. Put the key in the environment

    In the DOCSOCR_API_KEY variable, which the examples read. The prices example needs no key.

  3. Save and run

    Save each example under the name shown above its code. Its first lines say what it needs to run.

Your first call

Sends the hosted sample certificate (fictitious data) and prints the JSON answer.

FirstCall.java
// Your first call: extract the hosted sample certificate (fictitious data).
// Needs Java 17+ and DOCSOCR_API_KEY in the environment. Run: java FirstCall.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.UUID;

public class FirstCall {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "imageType": "url",
              "imageUrl": "https://docsocr.com/samples/certidao-nascimento-exemplo.jpg",
              "requestId": "%s"
            }""".formatted(UUID.randomUUID()); // one id per document

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.docsocr.com/api/v1/documents/birth-certificate"))
            .timeout(Duration.ofSeconds(120)) // above the API's 90 s extraction budget
            .header("Authorization", "Bearer " + System.getenv("DOCSOCR_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

        // The answer is JSON: read data.dados_pessoais.nome_completo with your JSON library
        System.out.println(response.body());
        if (response.statusCode() != 201 || !response.body().contains("\"success\":true")) {
            System.exit(1);
        }
    }
}

A local file in base64

Reads an image from your machine and sends it in base64, with no public URL needed.

LocalFile.java
// Extract a certificate from a local file, sent in base64.
// Needs Java 17+ and DOCSOCR_API_KEY in the environment. Run: java LocalFile.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Base64;
import java.util.UUID;

public class LocalFile {
    public static void main(String[] args) throws Exception {
        String imageBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("certificate.jpg")));
        String body = """
            {"imageType": "base64", "requestId": "%s", "imageBase64": "%s"}"""
            .formatted(UUID.randomUUID(), imageBase64); // one id per document

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.docsocr.com/api/v1/documents/birth-certificate"))
            .timeout(Duration.ofSeconds(120)) // above the API's 90 s extraction budget
            .header("Authorization", "Bearer " + System.getenv("DOCSOCR_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

        // The answer is JSON: read data.dados_pessoais.nome_completo with your JSON library
        System.out.println(response.body());
        if (response.statusCode() != 201 || !response.body().contains("\"success\":true")) {
            System.exit(1);
        }
    }
}

An image outside our standard

With resizeImage: true, an image outside our size standard is resized on our side for 1 credit more, instead of refused.

Resize.java
// Extract an image outside our standard: resizeImage brings it to the
// standard first, for one extra credit (the 800x640 sample is too small).
// Needs Java 17+ and DOCSOCR_API_KEY in the environment. Run: java Resize.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.UUID;

public class Resize {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "imageType": "url",
              "imageUrl": "https://docsocr.com/samples/certidao-nascimento-exemplo-800x640.jpg",
              "requestId": "%s",
              "resizeImage": true
            }""".formatted(UUID.randomUUID()); // one id per document

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.docsocr.com/api/v1/documents/birth-certificate"))
            .timeout(Duration.ofSeconds(120)) // above the API's 90 s extraction budget
            .header("Authorization", "Bearer " + System.getenv("DOCSOCR_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

        // The answer is JSON: data, imageResized and creditsCharged; read them with your JSON library
        System.out.println(response.body());
        if (response.statusCode() != 201 || !response.body().contains("\"success\":true")) {
            System.exit(1);
        }
    }
}

The fast engine

Asks for the fast engine: it is tried first, at its own price, and the standard engines answer when it cannot. The answer names the engine that answered and what it cost.

Fast.java
// Ask for the fast engine: it is tried first, at its own price, and the
// standard engines follow when it cannot answer. The answer names the engine
// that answered and what it cost.
// Needs Java 17+ and DOCSOCR_API_KEY in the environment. Run: java Fast.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.UUID;

public class Fast {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "imageType": "url",
              "imageUrl": "https://docsocr.com/samples/certidao-nascimento-exemplo.jpg",
              "requestId": "%s",
              "engine": "fast"
            }""".formatted(UUID.randomUUID()); // one id per document

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.docsocr.com/api/v1/documents/birth-certificate"))
            .timeout(Duration.ofSeconds(120)) // above the API's 90 s extraction budget
            .header("Authorization", "Bearer " + System.getenv("DOCSOCR_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

        // The answer is JSON: engine and creditsCharged say who answered and the cost
        System.out.println(response.body());
        if (response.statusCode() != 201 || !response.body().contains("\"success\":true")) {
            System.exit(1);
        }
    }
}

Errors and retries

Handles every answer and retries with the same requestId: for 15 minutes, a repeat of a finished request gets the same answer at no charge, and a repeat of one still running gets a 409, to wait.

Errors.java
// Extract a certificate, handling every answer, with retries that never charge twice.
// Each retry sends the same requestId: a repeat of a finished request gets its
// kept answer at no charge, and a repeat of one still running is told to wait (409).
// Needs Java 17+ and DOCSOCR_API_KEY in the environment. Run: java Errors.java
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Errors {
    static final String ENDPOINT = "https://api.docsocr.com/api/v1/documents/birth-certificate";
    // No engine could answer: nothing was charged, and a retry may succeed
    static final Set<String> RETRY_LATER = Set.of("EXTRACTION_BUSY", "EXTRACTION_TIMEOUT", "EXTRACTION_UNAVAILABLE");
    // Still in progress, too many requests, the service restarting
    static final Set<Integer> RETRY_STATUS = Set.of(409, 429, 502, 503, 504);
    // Read the answer with your JSON library; this sample only needs two fields
    static final Pattern ERROR_CODE = Pattern.compile("\"errorCode\":\"(\\w+)\"");
    static final Pattern RETRY_AFTER = Pattern.compile("\"retryAfter\":(\\d+)");

    static String extract(String imageUrl, int attempts) throws InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        String body = """
            {"imageType": "url", "imageUrl": "%s", "requestId": "%s"}"""
            .formatted(imageUrl, UUID.randomUUID()); // one id per document, the same on every retry
        HttpRequest request = HttpRequest.newBuilder(URI.create(ENDPOINT))
            .timeout(Duration.ofSeconds(120)) // above the API's 90 s extraction budget
            .header("Authorization", "Bearer " + System.getenv("DOCSOCR_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

        for (int attempt = 0; attempt < attempts; attempt++) {
            long backoff = 1L << attempt; // seconds: 1, 2, 4, 8
            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (IOException timeoutOrDroppedConnection) {
                Thread.sleep(backoff * 1000);
                continue;
            }
            int status = response.statusCode();
            String answer = response.body();
            if (status == 201 && answer.contains("\"success\":true")) {
                return answer;
            }
            String errorCode = find(ERROR_CODE, answer).orElse("");
            // Wait as long as the answer asks (retryAfter); a limit that resets
            // later, such as a daily quota, is not worth waiting for
            long wait = find(RETRY_AFTER, answer).map(Long::parseLong).orElse(backoff);
            boolean retry = RETRY_LATER.contains(errorCode) || RETRY_STATUS.contains(status);
            if (retry && wait <= 60) {
                Thread.sleep(wait * 1000);
                continue;
            }
            // 400 the body, 401 the key, 402 NOT_ENOUGH_CREDITS, 422 the image
            // (its errorCode says what to fix), DOCUMENT_NOT_RECOGNIZED: fix it, don't retry
            throw new IllegalStateException(status + " " + errorCode + " " + answer);
        }
        throw new IllegalStateException("No answer after retries: try again later");
    }

    static Optional<String> find(Pattern pattern, String text) {
        Matcher match = pattern.matcher(text);
        return match.find() ? Optional.of(match.group(1)) : Optional.empty();
    }

    public static void main(String[] args) throws InterruptedException {
        try {
            System.out.println(extract("https://docsocr.com/samples/certidao-nascimento-exemplo.jpg", 5));
        } catch (IllegalStateException error) {
            System.err.println(error.getMessage());
            System.exit(1);
        }
    }
}

Prices

Reads the price of an extraction in credits, per engine and for resizeImage. No key needed.

Prices.java
// The price of an extraction, in credits, per engine and for resizeImage.
// A public endpoint: no key needed. Needs Java 17+. Run: java Prices.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class Prices {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.docsocr.com/api/v1/documents/prices"))
            .timeout(Duration.ofSeconds(30))
            .GET()
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

        // The answer is JSON, e.g. {"standard": 1, ...}; read it with your JSON library
        System.out.println(response.body());
        if (response.statusCode() != 200) {
            System.exit(1);
        }
    }
}

Ready to start?

Create your account, get free credits and run the first example with your key.