# Java

URL: https://pieowl.com/docs/sdks/java





Pieowl doesn't ship a Java SDK. You send events from Java with a plain HTTP request to the [Track API](/docs/api/track). The example below uses `java.net.http.HttpClient`, which is built into Java 11 and later. It works the same in Spring Boot, Quarkus, Micronaut or plain Java.

Before you start [#before-you-start]

You need a client ID and a client secret. Find them in the dashboard under **Settings → Developers → Keys**. Server requests must include the secret, so keep it on your server and load it from an environment variable.

Send an event [#send-an-event]

Every request is a `POST` to `https://api.pieowl.com/track` with a JSON body of `{ "type": ..., "payload": ... }`.

```java title="Pieowl.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.concurrent.CompletableFuture;

public final class Pieowl {
    private static final URI TRACK_URL = URI.create("https://api.pieowl.com/track");
    private static final HttpClient CLIENT = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(5))
            .build();

    // json is the full body, for example {"type":"track","payload":{...}}
    public static CompletableFuture<HttpResponse<String>> send(String json) {
        HttpRequest request = HttpRequest.newBuilder(TRACK_URL)
                .timeout(Duration.ofSeconds(5))
                .header("Content-Type", "application/json")
                .header("pieowl-client-id", System.getenv("PIEOWL_CLIENT_ID"))
                .header("pieowl-client-secret", System.getenv("PIEOWL_CLIENT_SECRET"))
                // Optional: forward the visitor's IP for location data
                // .header("pieowl-client-ip", visitorIp)
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .build();
        return CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString());
    }
}
```

`sendAsync` doesn't block your request thread. Call `.join()` on the result if you need to wait.

The examples below write the JSON by hand to stay short. In a real app, build it with the JSON library you already use, like Jackson or Gson, so values are escaped correctly.

Usage [#usage]

Tracking events [#tracking-events]

```java
Pieowl.send("""
    {"type":"track","payload":{"name":"signup","profileId":"user_123","properties":{"plan":"pro"}}}
    """);
```

Identifying users [#identifying-users]

```java
Pieowl.send("""
    {"type":"identify","payload":{"profileId":"user_123","firstName":"Joe","lastName":"Doe","email":"joe@doe.com","properties":{"tier":"premium"}}}
    """);
```

Incrementing and decrementing properties [#incrementing-and-decrementing-properties]

`value` is optional and defaults to 1.

```java
Pieowl.send("""
    {"type":"increment","payload":{"profileId":"user_123","property":"visits","value":1}}
    """);
Pieowl.send("""
    {"type":"decrement","payload":{"profileId":"user_123","property":"credits","value":1}}
    """);
```

Tracking revenue [#tracking-revenue]

A purchase is a `revenue` event with these properties:

* `__amount`: in normal units, like `49.99`, not cents.
* `__currency`: an ISO 4217 code, like `EUR`. Optional, your site currency by default.
* `__orderId`: your order number. The same order sent twice counts once.
* `__deviceId`: the visitor's device ID, from `pieowl.getDeviceId()` in the browser. The purchase is credited to their visit.

For a refund, send the same event with `__refund` set to true. Leave out `__amount` to refund the whole order. See [Revenue attribution](/docs/revenue-attribution).

```java
Pieowl.send("""
    {"type":"track","payload":{"name":"revenue","properties":{"__amount":49.99,"__currency":"EUR","__orderId":"A-1001","__deviceId":"DEVICE_ID"}}}
    """);

// Refund the whole order
Pieowl.send("""
    {"type":"track","payload":{"name":"revenue","properties":{"__orderId":"A-1001","__refund":true}}}
    """);
```

The text blocks (`"""`) need Java 15 or later. On Java 11, use normal strings.

Good to know [#good-to-know]

* **Errors:** Pieowl answers with a `2xx` status when it accepts a request. Check `response.statusCode()` and log anything else, for example a bad client secret or an invalid payload.
* **Kotlin:** The same code works from Kotlin on the JVM. See the [Kotlin page](/docs/sdks/kotlin) for an Android example.
* **More event types:** Groups and the full request schema are in the [Track API reference](/docs/api/track).
