From 7ec8c7aaba6747a33e9357d1d635ce28c992d715 Mon Sep 17 00:00:00 2001 From: Andrew Kent Date: Fri, 14 Aug 2026 12:45:54 -0600 Subject: [PATCH] low level api client docs and example --- README.md | 4 + docs/api-client.md | 40 ++++++++++ examples/api-client/build.gradle | 15 ++++ .../braintrust/examples/ApiClientExample.java | 75 +++++++++++++++++++ settings.gradle | 1 + 5 files changed, 135 insertions(+) create mode 100644 docs/api-client.md create mode 100644 examples/api-client/build.gradle create mode 100644 examples/api-client/src/main/java/dev/braintrust/examples/ApiClientExample.java diff --git a/README.md b/README.md index 853b6830..65de4694 100644 --- a/README.md +++ b/README.md @@ -129,3 +129,7 @@ The SDK uses a standard slf4j logger and will use the default log level (or not All Braintrust loggers will log into the `dev.braintrust` namespace. To adjust the log level, consult your logger documentation. For example, to enable debug logging for slf4j-simple you would set the system property `org.slf4j.simpleLogger.log.dev.braintrust=DEBUG` + +## See Also + +- [Low-level Braintrust API client](./docs/api-client.md) — talk to the Braintrust REST API directly diff --git a/docs/api-client.md b/docs/api-client.md new file mode 100644 index 00000000..caddfb68 --- /dev/null +++ b/docs/api-client.md @@ -0,0 +1,40 @@ +# Braintrust API client + +The SDK ships a low-level HTTP client for the [Braintrust REST API](https://api.braintrust.dev). + +> If you just want to run evals or trace AI calls, prefer +> [`dev.braintrust.eval.Eval`](../braintrust-sdk/src/main/java/dev/braintrust/eval) and +> `dev.braintrust.trace.BraintrustTracing`. Reach for the API client only when you need +> raw REST access. + +The client is **generated code**. Every resource, method, and model comes from Braintrust's +public OpenAPI spec: + +- Spec repo: +- The exact commit we generate against is pinned as `braintrustOpenApiRef` in + [`gradle.properties`](../gradle.properties). + +## Basic usage + +```java +import dev.braintrust.api.BraintrustOpenApiClient; +import dev.braintrust.config.BraintrustConfig; +import dev.braintrust.openapi.api.ProjectsApi; +import dev.braintrust.openapi.model.CreateProject; +import dev.braintrust.openapi.model.Project; + +var client = BraintrustOpenApiClient.of(BraintrustConfig.fromEnvironment()); +var projects = new ProjectsApi(client); + +// Create a project. Model classes use fluent setters (not a builder). +Project created = projects.postProject( + new CreateProject().name("my-project").description("created from java")); + +System.out.println(created.getId() + " " + created.getName()); +``` + +### Runnable example + +A complete, runnable example can be found in [`examples/api-client`](../examples/api-client). + +Run it with `BRAINTRUST_API_KEY=sk-... ./gradlew :examples:api-client:run`. diff --git a/examples/api-client/build.gradle b/examples/api-client/build.gradle new file mode 100644 index 00000000..7a5873a8 --- /dev/null +++ b/examples/api-client/build.gradle @@ -0,0 +1,15 @@ +application { + mainClass = 'dev.braintrust.examples.ApiClientExample' +} + +dependencies { + // The OpenAPI-generated client (dev.braintrust.openapi.*) is bundled into the published + // braintrust-sdk jar, so real consumers get it transitively. This example uses a Gradle + // project() dependency, which doesn't expose the embedded classes, so depend on the + // generated client subproject directly for compilation. + implementation project(':braintrust-api') +} + +run { + description = 'Read projects, experiments, prompts, and datasets via the low-level API client' +} diff --git a/examples/api-client/src/main/java/dev/braintrust/examples/ApiClientExample.java b/examples/api-client/src/main/java/dev/braintrust/examples/ApiClientExample.java new file mode 100644 index 00000000..941eefd5 --- /dev/null +++ b/examples/api-client/src/main/java/dev/braintrust/examples/ApiClientExample.java @@ -0,0 +1,75 @@ +package dev.braintrust.examples; + +import dev.braintrust.api.BraintrustOpenApiClient; +import dev.braintrust.config.BraintrustConfig; +import dev.braintrust.openapi.api.DatasetsApi; +import dev.braintrust.openapi.api.ExperimentsApi; +import dev.braintrust.openapi.api.ProjectsApi; +import dev.braintrust.openapi.api.PromptsApi; +import dev.braintrust.openapi.model.Dataset; +import dev.braintrust.openapi.model.Experiment; +import dev.braintrust.openapi.model.Prompt; + +/** + * Demonstrates the low-level, OpenAPI-generated Braintrust API client for raw REST access beyond + * what the {@code Eval} and {@code BraintrustTracing} helpers cover. See docs/api-client.md for the + * full walkthrough. + * + *

Run with: + * + *

+ *   BRAINTRUST_API_KEY=sk-... ./gradlew :examples:api-client:run
+ * 
+ */ +public class ApiClientExample { + // Cap each listing so the example prints a manageable amount. + private static final int LIMIT = 5; + + public static void main(String[] args) { + // BraintrustOpenApiClient is an ApiClient with the base URL, bearer auth, and TLS + // wired up from the config. Every *Api class takes it in its constructor. + var client = BraintrustOpenApiClient.of(BraintrustConfig.fromEnvironment()); + + // Resolve the org name (login() is a Braintrust helper on top of the generated client) + // and grab the first project to read from. + var orgName = client.login().orgInfo().get(0).name(); + var project = + new ProjectsApi(client) + .getProject(1, null, null, null, null, null) + .getObjects() + .get(0); + var projectId = project.getId(); + System.out.println("Reading project " + project.getName() + " from org " + orgName); + + // List endpoints share the leading pagination/filter args and return a page wrapper + // whose getObjects() holds the results. Pass null for filters you don't need; the + // first arg is the page-size limit, and here we scope each list to projectId. + + // ── Experiments ─────────────────────────────────────────────────────────── + var experiments = new ExperimentsApi(client); + var experimentPage = + experiments.getExperiment(LIMIT, null, null, null, null, null, projectId, null); + System.out.println("\nExperiments:"); + for (Experiment e : experimentPage.getObjects()) { + System.out.println(" " + e.getName() + " (" + e.getId() + ")"); + } + + // ── Prompts ─────────────────────────────────────────────────────────────── + var prompts = new PromptsApi(client); + var promptPage = + prompts.getPrompt( + LIMIT, null, null, null, null, null, projectId, null, null, null, null); + System.out.println("\nPrompts:"); + for (Prompt p : promptPage.getObjects()) { + System.out.println(" " + p.getName() + " (" + p.getId() + ")"); + } + + // ── Datasets ────────────────────────────────────────────────────────────── + var datasets = new DatasetsApi(client); + var datasetPage = datasets.getDataset(LIMIT, null, null, null, null, null, projectId, null); + System.out.println("\nDatasets:"); + for (Dataset d : datasetPage.getObjects()) { + System.out.println(" " + d.getName() + " (" + d.getId() + ")"); + } + } +} diff --git a/settings.gradle b/settings.gradle index 9fc11e67..7fadeb0b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -22,6 +22,7 @@ include 'examples:remote-eval' include 'examples:remote-eval-with-params' include 'examples:trace-scoring' include 'examples:classifiers' +include 'examples:api-client' include 'braintrust-java-agent' include 'braintrust-java-agent:bootstrap' include 'braintrust-java-agent:internal'