Skip to content

Java SDK

The official Java SDK targets Java 17+ and uses the JDK’s built-in HttpClient (no Apache HTTP Client dependency).

<dependency>
<groupId>com.zutax</groupId>
<artifactId>zutax</artifactId>
<version>0.1.0</version>
</dependency>
import com.zutax.ZutaxClient;
import java.util.List;
import java.util.Map;
ZutaxClient client = new ZutaxClient(
"zk_test_...",
"https://staging-api.getzutax.com"
);
Map<String, Object> payload = Map.of(
"external_id", "INV-2026-0042",
"issue_date", "2026-05-03",
"due_date", "2026-06-03",
"customer", Map.of(
"external_id", "C-100",
"legal_name", "Acme Industries Limited",
"tin", "12345678-0001"
),
"lines", List.of(
Map.of(
"name", "Consulting services — May 2026",
"quantity", "1",
"unit_price_naira", "250000.00",
"vat_rate", "7.5"
)
)
);
Map<String, Object> result = client.invoices.transmit(payload, "INV-2026-0042");
System.out.println(result.get("invoice_id"));
import com.zutax.exception.*;
try {
client.invoices.transmit(payload);
} catch (ValidationException e) {
e.getErrors().forEach(err ->
System.out.println(err.get("loc") + ": " + err.get("msg")));
} catch (RateLimitException e) {
System.out.println("Slow down, retry in " + e.getRetryAfter() + "s");
}

IdempotencyKey.scoped uses a ThreadLocal, so it works for synchronous work but does not propagate across executors. If you dispatch transmits to a thread pool, set the key inside the worker:

import com.zutax.IdempotencyKey;
IdempotencyKey.scoped("INV-2026-0042", () -> client.invoices.transmit(payload));
client.invoices // transmit, get, getByExternalId, list, cancel
client.parties // create, get, getByExternalId, list
client.products // create, get, getByExternalId, list
client.creditNotes // create, get, getByExternalId, list

Zulaiy/zutax/zutax-sdks/java/