Developer Guide · Java

How to add e-signatures
in Java

Add legally binding e-signatures to a Java app in four steps using Java 11's built-in HttpClient: get a token, create an envelope with a multipart upload, send the signing link, and handle the completion webhook in Spring Boot.

Get free API keys →
1

Get a bearer token

Exchange your OAuth2 client credentials for a short-lived access token using Java 11+'s built-in HttpClient — no Apache HttpComponents or OkHttp required.

java
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import com.fasterxml.jackson.databind.ObjectMapper;

HttpClient client = HttpClient.newHttpClient();
ObjectMapper mapper = new ObjectMapper();

String body = "grant_type=client_credentials"
    + "&client_id="     + URLEncoder.encode(System.getenv("GETSIGNED_CLIENT_ID"),     StandardCharsets.UTF_8)
    + "&client_secret=" + URLEncoder.encode(System.getenv("GETSIGNED_CLIENT_SECRET"), StandardCharsets.UTF_8);

HttpRequest tokenReq = HttpRequest.newBuilder()
    .uri(URI.create("https://api.getsigned.app/oauth/token"))
    .header("Content-Type", "application/x-www-form-urlencoded")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<String> tokenRes = client.send(tokenReq, HttpResponse.BodyHandlers.ofString());
String token = (String) mapper.readValue(tokenRes.body(), java.util.Map.class).get("access_token");
2

Create an envelope

Upload the PDF and declare signers and fields with a multipart/form-data request. Java 11 HttpClient supports multipart via a custom BodyPublisher.

java
import java.nio.file.*;
import java.util.*;

String boundary = "----GetSignedBoundary" + System.currentTimeMillis();
byte[] pdfBytes  = Files.readAllBytes(Path.of("nda.pdf"));

String signers = """
    [{"name":"Jamie","email":"jamie@client.io"}]""";
String fields  = """
    [{"type":"signature","page":1,"x":420,"y":580}]""";

// Build multipart body
byte[] CRLF = "\r\n".getBytes();
var parts = new ArrayList<byte[]>();
// -- document part
parts.add(("--" + boundary + "\r\n").getBytes());
parts.add("Content-Disposition: form-data; name=\"document\"; filename=\"nda.pdf\"\r\n".getBytes());
parts.add("Content-Type: application/pdf\r\n\r\n".getBytes());
parts.add(pdfBytes); parts.add(CRLF);
// -- signers & fields as text parts (omitted for brevity — same pattern)
parts.add(("--" + boundary + "--\r\n").getBytes());

HttpRequest envReq = HttpRequest.newBuilder()
    .uri(URI.create("https://api.getsigned.app/v1/envelopes"))
    .header("Authorization", "Bearer " + token)
    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
    .POST(HttpRequest.BodyPublishers.ofByteArrays(parts))
    .build();

HttpResponse<String> envRes = client.send(envReq, HttpResponse.BodyHandlers.ofString());
String envelopeId = (String) mapper.readValue(envRes.body(), Map.class).get("id");
3

Send for signing

Sending generates a tokenized, single-use link per signer and emails it. Signers verify identity with email/SMS OTP.

java
HttpRequest sendReq = HttpRequest.newBuilder()
    .uri(URI.create("https://api.getsigned.app/v1/envelopes/" + envelopeId + "/send"))
    .header("Authorization", "Bearer " + token)
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();

client.send(sendReq, HttpResponse.BodyHandlers.discarding());
4

Handle the completion webhook

When the last signer finishes, GetSigned POSTs envelope.completed to your endpoint. Verify the HMAC-SHA256 signature over the raw body before trusting it. Spring Boot example below.

java
// Spring Boot webhook controller
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;

@RestController
public class WebhookController {

    private static final byte[] SECRET =
        System.getenv("GETSIGNED_WEBHOOK_SECRET").getBytes(StandardCharsets.UTF_8);
    private final ObjectMapper mapper = new ObjectMapper();

    @PostMapping("/webhooks/getsigned")
    public ResponseEntity<Void> handleWebhook(
            @RequestBody byte[] raw,   // raw bytes, before JSON parsing
            @RequestHeader("X-GetSigned-Signature") String sig) throws Exception {

        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(SECRET, "HmacSHA256"));
        StringBuilder hex = new StringBuilder();
        for (byte b : mac.doFinal(raw)) hex.append(String.format("%02x", b));
        // MessageDigest.isEqual is constant-time
        if (!MessageDigest.isEqual(
                hex.toString().getBytes(StandardCharsets.UTF_8),
                sig.getBytes(StandardCharsets.UTF_8))) {
            return ResponseEntity.status(401).build();
        }

        Map<String, Object> payload = mapper.readValue(raw, new TypeReference<>() {});
        if ("envelope.completed".equals(payload.get("event"))) {
            String envelopeId = (String) payload.get("envelope_id");
            // GET /v1/envelopes/{envelopeId}/document -> sealed PDF
            // Persist, notify counterparties, update your database, etc.
        }
        return ResponseEntity.ok().build();
    }
}

Frequently asked questions

How do I add e-signatures in Java?

Use Java 11+'s built-in java.net.http.HttpClient to call the GetSigned REST API: POST client credentials to /oauth/token for a bearer token, create an envelope by uploading a PDF with signers and fields as a multipart/form-data request, send it to generate signing links, then handle the envelope.completed webhook in Spring Boot or Jakarta Servlet. No third-party HTTP library is required.

Do I need Apache HttpComponents or OkHttp for Java?

No. Java 11 introduced java.net.http.HttpClient as a standard, non-blocking HTTP client. It supports POST, custom headers, multipart bodies via BodyPublishers, and async requests. For a three-endpoint integration like GetSigned, the standard library is sufficient. Use Apache HttpComponents or OkHttp only if your project already depends on them.

How do I handle multipart file uploads in Java without a library?

Construct a multipart body manually: choose a boundary string, build each part as a byte array with the correct Content-Disposition and Content-Type headers, separate parts with the boundary, and terminate with boundary--. Pass the assembled byte arrays to HttpRequest.BodyPublishers.ofByteArrays(). This is verbose but has zero dependencies.

Does this work with Spring Boot?

Yes. The java.net.http.HttpClient calls can be made from anywhere — a Spring @Service, a @Scheduled task, or a @RestController. For the webhook handler, create a @RestController with @PostMapping — Spring Boot automatically deserializes the JSON payload. Add the endpoint to your CSRF exclusion list if you use Spring Security.

Is there a free tier to build against?

Yes. The free Starter plan includes full REST API access, PKCS#7 sealing, OTP verification, and webhooks, with 5 envelopes per month — enough to build and test a complete Java integration.

Other stacks: Node.js · Python · PHP · Go · Ruby · Language-agnostic guide

Ship signing in your Java app today

Get free API keys →