TheoKanning/openai-java
OpenAI Api Client in Java
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓31+ active contributors
- ✓MIT licensed
- ✓CI configured
Show all 6 evidence items →Show less
- ✓Tests present
- ⚠Stale — last commit 2y ago
- ⚠Concentrated ownership — top contributor handles 63% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/theokanning/openai-java)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/theokanning/openai-java on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: TheoKanning/openai-java
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/TheoKanning/openai-java shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 31+ active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 63% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live TheoKanning/openai-java
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/TheoKanning/openai-java.
What it runs against: a local clone of TheoKanning/openai-java — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in TheoKanning/openai-java | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 731 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of TheoKanning/openai-java. If you don't
# have one yet, run these first:
#
# git clone https://github.com/TheoKanning/openai-java.git
# cd openai-java
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of TheoKanning/openai-java and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "TheoKanning/openai-java(\\.git)?\\b" \\
&& ok "origin remote is TheoKanning/openai-java" \\
|| miss "origin remote is not TheoKanning/openai-java (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "api/src/main/java/com/theokanning/openai/completion/chat/ChatCompletionRequest.java" \\
&& ok "api/src/main/java/com/theokanning/openai/completion/chat/ChatCompletionRequest.java" \\
|| miss "missing critical file: api/src/main/java/com/theokanning/openai/completion/chat/ChatCompletionRequest.java"
test -f "api/src/main/java/com/theokanning/openai/completion/chat/ChatMessage.java" \\
&& ok "api/src/main/java/com/theokanning/openai/completion/chat/ChatMessage.java" \\
|| miss "missing critical file: api/src/main/java/com/theokanning/openai/completion/chat/ChatMessage.java"
test -f "api/src/main/java/com/theokanning/openai/OpenAiResponse.java" \\
&& ok "api/src/main/java/com/theokanning/openai/OpenAiResponse.java" \\
|| miss "missing critical file: api/src/main/java/com/theokanning/openai/OpenAiResponse.java"
test -f "api/src/main/java/com/theokanning/openai/OpenAiError.java" \\
&& ok "api/src/main/java/com/theokanning/openai/OpenAiError.java" \\
|| miss "missing critical file: api/src/main/java/com/theokanning/openai/OpenAiError.java"
test -f "api/build.gradle" \\
&& ok "api/build.gradle" \\
|| miss "missing critical file: api/build.gradle"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 731 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~701d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/TheoKanning/openai-java"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
A Java client library for OpenAI's GPT APIs (GPT-3, ChatGPT, GPT-4) that provides strongly-typed request/response POJOs, a Retrofit-based HTTP client, and a high-level service wrapper. It handles API communication, token management via jtokkit, and supports 11+ OpenAI endpoints including chat completions, embeddings, audio transcription, fine-tuning, and assistants. Three-module Gradle monorepo: api/ contains pure POJOs (DeleteResult, CompletionRequest, etc.) with Jackson annotations; client/ wraps these with Retrofit2 (OpenAiApi interface) + AuthenticationInterceptor; service/ provides OpenAiService convenience layer. All under api/src/main/java/com/theokanning/openai/ with domain-specific subpackages (assistants/, audio/, billing/, completion/, etc.).
👥Who it's for
Java developers integrating OpenAI capabilities into enterprise or backend applications who want compile-time safety and minimal boilerplate. Useful for teams building chatbots, content generation systems, or AI-powered services without writing raw HTTP clients.
🌱Maturity & risk
The project is archived and no longer maintained as of June 6, 2024. It reached a stable production state with full API coverage, solid Gradle/Maven build setup, and GitHub Actions CI (test.yml, pull_request.yml, publish.yml), but is now frozen. Historical adoption was moderate; no breaking changes are being made.
High risk for new projects: project is officially archived with zero ongoing support or security patches. Dependency drift is inevitable—Jackson, Retrofit, and jtokkit versions will become stale. OpenAI API changes (like deprecation of engine-based endpoints already noted in README) will not be addressed. Single original maintainer (TheoKanning) is no longer active.
Active areas of work
Nothing. The repository is archived. No active development, PRs, or commits are expected. The .github/workflows/ directory contains CI pipelines (test.yml, publish.yml) but they will not execute on new pushes.
🚀Get running
git clone https://github.com/TheoKanning/openai-java.git
cd openai-java
./gradlew build
Note: Gradle wrapper is included (gradlew script implied by standard setup). Requires Java 1.8+. API key must be passed at runtime, not committed.
Daily commands:
This is a library, not a runnable application. To use it: add dependency to your Gradle project (implementation 'com.theokanning.openai-gpt3-java:service:0.x.x') and instantiate OpenAiService(apiKey). See service/ module source for example usage patterns. Run tests with ./gradlew test.
🗺️Map of the codebase
api/src/main/java/com/theokanning/openai/completion/chat/ChatCompletionRequest.java— Core request model for chat completions; all ChatGPT/GPT-4 calls flow through this POJO definitionapi/src/main/java/com/theokanning/openai/completion/chat/ChatMessage.java— Fundamental data structure representing conversation messages; required understanding for any chat-based featureapi/src/main/java/com/theokanning/openai/OpenAiResponse.java— Generic response wrapper used across all API endpoints; essential for understanding response deserializationapi/src/main/java/com/theokanning/openai/OpenAiError.java— Error representation shared across all APIs; critical for error handling and debuggingapi/build.gradle— Module build configuration with Jackson dependencies for JSON serialization; defines Java compatibility and publication setupapi/src/main/java/com/theokanning/openai/assistants/Assistant.java— Represents OpenAI's Assistants API entity; core abstraction for stateful agent interactionsapi/src/main/java/com/theokanning/openai/messages/Message.java— Message entity for Assistants API threads; essential for understanding the conversation persistence model
🛠️How to make changes
Add a new API endpoint request/response type
- Create a new Request POJO in an appropriate package (e.g., api/src/main/java/com/theokanning/openai/myfeature/MyFeatureRequest.java) with @Data and @Builder from Lombok (
api/src/main/java/com/theokanning/openai/myfeature/MyFeatureRequest.java) - Create a corresponding Result POJO (e.g., MyFeatureResult.java) with response fields and @Data (
api/src/main/java/com/theokanning/openai/myfeature/MyFeatureResult.java) - Follow Jackson serialization patterns from ChatCompletionRequest.java: use @JsonProperty for snake_case mapping (
api/src/main/java/com/theokanning/openai/completion/chat/ChatCompletionRequest.java) - Add any enum types in the same package (e.g., MyFeatureMode.java) if needed for constrained fields (
api/src/main/java/com/theokanning/openai/myfeature/MyFeatureMode.java)
Add support for a new message content type in Assistants API
- Create a new content class in api/src/main/java/com/theokanning/openai/messages/content/ (e.g., VideoContent.java) extending or parallel to Text.java (
api/src/main/java/com/theokanning/openai/messages/content/Text.java) - Update MessageContent.java to include the new type in its union/interface pattern (
api/src/main/java/com/theokanning/openai/messages/MessageContent.java) - Reference ImageFile.java and FileCitation.java as templates for nested annotation structures (
api/src/main/java/com/theokanning/openai/messages/content/ImageFile.java)
Add a new Assistant tool capability
- Add the tool enum to api/src/main/java/com/theokanning/openai/assistants/AssistantToolsEnum.java (
api/src/main/java/com/theokanning/openai/assistants/AssistantToolsEnum.java) - Create a tool-specific configuration class (e.g., CodeInterpreterTool.java) in the assistants package, following Tool.java pattern (
api/src/main/java/com/theokanning/openai/assistants/Tool.java) - Update AssistantRequest.java and ModifyAssistantRequest.java to accept the new tool in their tools List field (
api/src/main/java/com/theokanning/openai/assistants/AssistantRequest.java)
🔧Why these technologies
- Jackson (Jackson Databind, Jackson Annotations) — Industry-standard JSON serialization for Java with @JsonProperty snake_case mapping; essential for OpenAI API compatibility
- Retrofit (implied by client module structure) — Type-safe REST client with declarative endpoint definitions; abstracts HTTP mechanics for cleaner API wrapper code
- Lombok (@Data, @Builder) — Eliminates boilerplate getters, setters, constructors across 100+ POJO request/response classes
- jtokkit — Provides accurate token counting for prompt/completion validation before API calls; avoids over-billing on token overages
- Java 1.8+ (target 1.8 compatibility) — Ensures broad JVM compatibility for enterprise adoption; Lambda support with minimal runtime overhead
⚖️Trade-offs already made
- Single api module with POJOs only (no HTTP client or service wrappers in core)
- Why:
- Consequence: undefined
🪤Traps & gotchas
OpenAI API Key: Must be supplied at runtime via constructor (OpenAiService(apiKey)) or as environment variable in interceptor; no default or config file lookup. Snake case serialization: All POJOs use @JsonProperty("snake_case") because OpenAI API uses snake_case; requests/responses will fail silently if this mapping is bypassed. Deprecated endpoints: Some classes (e.g., Engine-based APIs) are marked deprecated in code but still present; using them will fail against modern OpenAI API. Java 1.8 requirement: sourceCompatibility/targetCompatibility hardcoded in build.gradle; upgrading Jackson or other deps may force Java 11+. No streaming support: ChatCompletionRequest supports streaming (stream=true), but the client does not natively handle SSE; you must read the raw response stream yourself.
🏗️Architecture
💡Concepts to learn
- Token counting (jtokkit) — OpenAI charges by token, not request; jtokkit is embedded to let developers estimate costs and enforce limits before API calls, critical for production cost control
- Retrofit2 HTTP client with interceptors — OkHttp interceptors (AuthenticationInterceptor) transparently inject auth headers; understanding interceptor chains is essential for customizing API calls or adding logging/retry logic
- Jackson @JsonProperty snake_case mapping — OpenAI API uses snake_case (model_id, max_tokens) but Java convention is camelCase; POJOs rely on @JsonProperty to bridge this; misconfigured mapping silently breaks serialization
- Streaming API responses (Server-Sent Events / SSE) — ChatCompletion endpoint supports stream=true for token-by-token output; this library does not natively parse SSE, requiring raw stream handling by consumers
- Retrofit @Body and converter factories — Custom snake_case + non-null-only converter factory is applied globally; request POJOs with null fields are omitted from JSON, reducing payload and avoiding API errors
- Gradle multi-module project structure — Three modules (api, client, service) have separate concerns and are published independently; understanding module dependencies and dependency constraints is needed for maintenance
- Deprecated endpoints and API versioning — OpenAI deprecated Engine-based APIs; project marks these @Deprecated but does not remove them, creating confusion; understanding OpenAI's versioning strategy is critical for staying current
🔗Related repos
openai/openai-python— Official Python client library for OpenAI API; direct competitor, provides reference for API design and feature coveragelangchain4j/langchain4j— Modern Java LLM framework that wraps multiple AI providers (including OpenAI) with abstractions; addresses same use case but with higher-level interfacesspring-projects/spring-ai— Spring Boot integration for AI APIs (including OpenAI); provides @Configuration and auto-wiring for OpenAI clients in Spring applicationsopenai/node-openai-api— Official Node.js client; sibling project useful for teams polyglot across Java and JavaScript backendsjplush/simple-openai— Lightweight alternative Java OpenAI client with fewer dependencies; useful reference for minimalist approach
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for ChatMessage and ChatCompletionRequest serialization
The chat completion API is the most widely-used endpoint in this library, but there are no visible test files for core chat classes (ChatMessage.java, ChatCompletionRequest.java, ChatCompletionResult.java). Given the complexity of message roles, function calling, and tool use in these classes, unit tests validating Jackson serialization/deserialization edge cases would prevent regressions and make contributions safer. This is critical since the archived status means fewer maintainers will catch serialization bugs.
- [ ] Create api/src/test/java/com/theokanning/openai/completion/chat/ChatMessageTest.java with tests for all ChatMessageRole enum values
- [ ] Create api/src/test/java/com/theokanning/openai/completion/chat/ChatCompletionRequestTest.java testing serialization with and without function_call/tools fields
- [ ] Create api/src/test/java/com/theokanning/openai/completion/chat/ChatCompletionResultTest.java validating deserialization of streaming vs non-streaming responses
- [ ] Add test cases for null/empty values in optional fields to ensure Jackson annotations (@JsonInclude, @JsonProperty) work correctly
Add missing Retrofit service interface for Assistants API endpoints
The api module contains full Assistants API POJOs (Assistant.java, AssistantFile.java, AssistantRequest.java, etc.), but there's no visible Retrofit service interface to actually call these endpoints. The client module likely has a base OpenAiApi interface that needs new methods for assistants operations (create, list, retrieve, modify, delete assistants; manage assistant files; handle threads and runs). This is a concrete gap preventing users from using the assembled API models.
- [ ] Locate the main Retrofit service interface (likely in client/src/main/java/com/theokanning/openai/client/OpenAiApi.java or similar)
- [ ] Add @POST/@GET/@DELETE methods for Assistants CRUD: createAssistant, listAssistants, retrieveAssistant, modifyAssistant, deleteAssistant
- [ ] Add methods for AssistantFile operations: createAssistantFile, listAssistantFiles, deleteAssistantFile
- [ ] Add @POST/@GET methods for Thread and Run endpoints (createThread, createRun, retrieveRun, etc.)
- [ ] Update client module tests to verify these new endpoint mappings work with mock responses
Add validation tests for OpenAiError and OpenAiHttpException error handling across all endpoints
The repo has OpenAiError.java and OpenAiHttpException.java defined, but there are no visible tests validating that API error responses from different endpoints (completions, embeddings, audio, billing) are correctly parsed and wrapped. Since this library is archived and users rely on it to handle production API errors gracefully, adding tests that verify error deserialization and exception messaging would prevent silent failures and improve debugging. This requires testing against actual API error JSON structures.
- [ ] Create api/src/test/java/com/theokanning/openai/OpenAiErrorTest.java with Jackson deserialization tests for the official OpenAI error format (error.code, error.message, error.param, error.type)
- [ ] Create api/src/test/java/com/theokanning/openai/OpenAiHttpExceptionTest.java validating that HTTP status codes (400, 401, 429, 500) are correctly parsed into exception messages
- [ ] Add integration-style tests in client module verifying that Retrofit intercepts HTTP errors and wraps them in OpenAiHttpException
- [ ] Test edge cases: malformed JSON responses, missing error fields, rate-limit headers (retry-after)
🌿Good first issues
- Add ChatCompletionRequest.image_url support: The completion API added vision capabilities; ChatCompletionRequest lacks image_url field in messages. Add the field to api/src/main/java/com/theokanning/openai/completion/chat/ChatMessage.java with @JsonProperty mapping and write a unit test in api/src/test/.
- Document AuthenticationInterceptor configuration: No javadoc or example in client/src/main/java/com/theokanning/openai/AuthenticationInterceptor.java on how to inject custom headers (org_id, api_version for Azure). Add inline comments and update README with real Azure example.
- Add missing tests for billing package: api/src/main/java/com/theokanning/openai/billing/ has POJOs (BillingUsage, DailyCost, etc.) but api/src/test/ likely has no corresponding tests. Create BillingUsageTest and DailyCostTest with Jackson deserialization assertions.
⭐Top contributors
Click to expand
Top contributors
- @TheoKanning — 63 commits
- @vacuityv — 5 commits
- @aaronuu — 2 commits
- @mzhu-ai — 2 commits
- @dehidehidehi — 2 commits
📝Recent commits
Click to expand
Recent commits
2690966— Update README.md (TheoKanning)e7de81c— Remove references to deprecated models (#438) (TheoKanning)84d2af1— Add CONTRIBUTING.md and pull request template (#429) (TheoKanning)41c14c6— Fix fine-tuning test email notifications (#428) (TheoKanning)1f43e06— Update AssistantTest (#427) (TheoKanning)3d60d6e— Update to version 0.18.2 (#417) (TheoKanning)2195b2a— Assistant fixed (#414) (vacuityv)decc9fd— feat(assistant-function): change the function define and a test for assistant funxtion (#415) (vacuityv)650d76b— Update to version 0.18.1 (#410) (TheoKanning)f63d666— fix(assistant-run): run ans run-step (#408) (vacuityv)
🔒Security observations
The OpenAI Java client library has moderate security concerns. The primary issue is that the project is archived and no longer maintained, meaning no security updates will be provided. Dependencies are referenced through a version catalog that wasn't provided for analysis, preventing verification of CVE status. The library appears to be a well-structured API client using industry-standard libraries (Jackson, Retrofit via client module), but the archived status significantly
- High · Project is Archived and No Longer Maintained —
README.md, Project Status. The project has been archived as of June 6th, 2024 and is no longer maintained. This means no security patches, updates, or bug fixes will be provided. Any vulnerabilities discovered in dependencies will not be addressed by the maintainers. Fix: Consider forking the project and maintaining it independently, or migrate to an officially maintained OpenAI Java client library if available. - High · Dependency Version Management Not Specified —
api/build.gradle. The build.gradle file uses variable references (libs.jacksonAnnotations, libs.jacksonDatabind, etc.) without specifying versions. The actual versions are likely defined in a version catalog or gradle.properties file not provided in this analysis. Without seeing the specific versions, it's impossible to identify known CVEs in dependencies. Fix: Provide the version catalog or gradle.properties to verify all dependencies are up-to-date and free of known vulnerabilities. Run 'gradle dependencyCheck' or use OWASP Dependency-Check to scan for CVEs. - Medium · Use of Jackson for Serialization Without Input Validation Details —
api/build.gradle, Multiple POJO files in api/src/main/java/com/theokanning/openai/. The project heavily relies on Jackson for JSON serialization/deserialization (jacksonAnnotations, jacksonDatabind). While Jackson itself is a reputable library, improper configuration could lead to deserialization gadget attacks or XXE vulnerabilities if not properly configured. Fix: Verify that Jackson is configured securely: disable default typing unless explicitly needed, use appropriate security settings in ObjectMapper configuration, validate all deserialized data, and keep Jackson updated to the latest patch version. - Medium · API Key/Secret Handling Not Visible —
api/src/main (client implementation not fully visible). This is an API client library for OpenAI. The codebase likely handles authentication tokens/API keys. Without seeing the client implementation (not provided in file structure), there's a risk of: storing credentials in logs, exposing them in error messages, or hardcoding them. Fix: Ensure API keys are never logged, printed to console, or included in error messages. Use environment variables or secure configuration management for credentials. Implement proper header sanitization in HTTP request/response logging. - Low · Lombok Dependency Usage —
api/build.gradle. Lombok is used as a compile-only dependency with annotation processing. While generally safe, Lombok modifies bytecode at compile time, which could potentially be a vector for supply chain attacks if the Lombok dependency is compromised. Fix: Regularly update Lombok to the latest version. Monitor the Lombok project for security advisories. Consider using Java records (Java 14+) as an alternative if targeting newer Java versions. - Low · Source Compatibility Set to Java 1.8 —
api/build.gradle (compileJava block). The project targets Java 1.8 (sourceCompatibility and targetCompatibility). Java 8 reached end of life for most vendors and no longer receives security updates. This makes the library potentially vulnerable to Java runtime exploits if users are running on unpatched Java 8. Fix: Update minimum Java version requirement to at least Java 11 or higher (currently 21 is LTS). This allows use of newer security features and receives current security patches. - Low · Missing Security Configuration in CI/CD Pipeline —
.github/workflows/. The GitHub workflows (test.yml, pull_request.yml, publish.yml) are not visible in detail. Best practices would include dependency vulnerability scanning, security-focused linting, and SBOM generation. Fix: Add OWASP Dependency-Check or similar tool to CI/CD pipeline. Implement automated security scanning in pull request workflows. Generate and publish Software Bill of Materials (SBOM). Use Snyk or similar tools for continuous dependency monitoring.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.