# Java SDK

The current Java SDK exposes services for:

- receipt processing
- credit note processing
- matching
- verification
- company provisioning
- store management


Source code and releases: [cheqi-io/cheqi-sdk-java](https://github.com/cheqi-io/cheqi-sdk-java)

## Installation

Current version: `1.1.0`.

```xml
<dependency>
    <groupId>io.cheqi</groupId>
    <artifactId>cheqi-sdk</artifactId>
    <version>1.1.0</version>
</dependency>
```

## Initialization

```java
CheqiSDK sdk = CheqiSDK.builder()
    .apiEndpoint(Environment.SANDBOX)
    .apiKey(System.getenv("CHEQI_API_KEY"))
    .build();
```

Custom endpoint:

```java
CheqiSDK sdk = CheqiSDK.builder()
    .customApiEndpoint("http://localhost:8080")
    .receiptDownloadBaseUrl("http://localhost:5190")
    .apiKey(System.getenv("CHEQI_API_KEY"))
    .build();
```

Production and sandbox environments select their customer-facing receipt origins automatically:

| API environment | Receipt origin |
|  --- | --- |
| `Environment.PRODUCTION` | `https://receipt.cheqi.io` |
| `Environment.SANDBOX` | `https://sandbox.receipt.cheqi.io` |


## Receipt flow

```java
IdentificationDetails customer = IdentificationDetails.builder()
    .paymentType(PaymentType.CARD_PAYMENT)
    .cardDetails(CardDetails.builder()
        .paymentAccountReference("PAR123456789")
        .cardProvider(CardProvider.VISA)
        .build())
    .recipientEmail("customer@example.com")
    .build();

ReceiptTemplateRequest receiptRequest = ReceiptTemplateRequest.builder()
    .documentNumber("INV-2026-001")
    .issueDate(Instant.now())
    .currency("EUR")
    .receiptSubtotal(new BigDecimal("10.00"))
    .totalBeforeTax(new BigDecimal("10.00"))
    .totalTaxAmount(new BigDecimal("2.10"))
    .totalAmount(new BigDecimal("12.10"))
    .addProduct(Product.builder()
        .name("Coffee")
        .identifier("SKU-COFFEE-001")
        .quantity(2.0)
        .unitCode(UnitCode.C62) // C62 = "each" (a single unit); see UnitCode for other UN/ECE codes
        .unitPrice("5.00")
        .subtotal("10.00")
        .total("12.10")
        .addTax(21.0, "VAT", "10.00", "2.10")
        .build())
    .addTax(Tax.builder()
        .rate(21.0)
        .type("VAT")
        .taxableAmount("10.00")
        .amount("2.10")
        .label("VAT 21%")
        .build())
    .buyerCountryCode(matchResponse.getBuyerCountryCode())
    .buyerType(matchResponse.getBuyerType())
    .taxesApplied(true)
    .build();

ReceiptResult result = sdk.getReceiptService()
    .processCompleteReceipt(customer, receiptRequest);
```

`processCompleteReceipt` handles the selected delivery route:

- `DIGITAL` uses normal recipient encryption and delivery.
- `EMAIL_FALLBACK` uses the configured email fallback.
- `DOWNLOAD_FALLBACK` uses a client-encrypted URL whose AES key remains in the URL fragment.
- `routeFound: false` returns customer-not-found when the API is reachable. It does not bypass a disabled download fallback.
- a transient matching or template failure returns `PENDING_DOWNLOAD_TEMPLATE` with a URL that the customer can visit later.
- an ambiguous upload failure returns `PENDING_DOWNLOAD_UPLOAD` with the exact ciphertext that must be retried.


For pending results, your integration owns durable storage, scheduling, retries, monitoring, and retention. The SDK does not run a background worker or choose how your compute is allocated. See [Download links](/receipts/download-fallback) for the online and outage recovery flows.

OAuth overload:

```java
ReceiptResult result = sdk.getReceiptService()
    .processCompleteReceipt(customer, receiptRequest, accessToken);
```

## Matching flow

```java
RecipientResolutionResponse matchResponse = sdk.getMatchingService()
    .matchCustomer(customer);
```

Use the returned `buyerCountryCode`, `buyerType`, and `acceptedFormats` when preparing the template and downstream flow. `buyerCountryCode`, `buyerType`, and `taxesApplied` are mandatory on the receipt template request.

## Verification flow

```java
String cheqiHash = sdk.getVerificationService()
    .calculateCheqiReceiptHash(cheqiReceiptJson);

String ublHash = sdk.getVerificationService()
    .calculateUblHash(ublPurchaseReceiptXml);
```

## Credit note flow

The Java SDK also exposes `sdk.getCreditNoteService()` for full credit note processing against an existing `cheqiReceiptId`. Use this when documenting or implementing returns, not the receipt service.

## Company and store flows

The SDK exposes:

- `sdk.getCompanyService()`
- `sdk.getStoreService()`


Use those services for provisioning and store/location management rather than calling receipt endpoints directly.