This is the official Didit Java and Kotlin SDK. It follows docs/DESIGN.md, the contract shared by all seven Didit server SDKs: when the code and the design disagree, the code is wrong.
- JDK 21 to build (the code compiles to Java 11 bytecode). Gradle downloads other JDKs for the test matrix when they are missing.
- Python 3.10 or newer for the code generator (standard library only).
| Task | Command |
|---|---|
| Regenerate the generated layer | python3 codegen/generate.py |
| Check that it is up to date | python3 codegen/generate.py --check |
| Generator tests | python3 -m unittest discover -s codegen/tests -t codegen |
| All tests and checks | ./gradlew build |
| Tests on another Java version | ./gradlew test -PtestJavaVersion=11 |
| Core coverage (90 % gate) | ./gradlew jacocoTestCoverageVerification |
| Live sandbox smoke tests | DIDIT_SANDBOX_API_KEY=... ./gradlew liveTest |
| Format | ./gradlew spotlessApply |
| Javadoc | ./gradlew javadoc |
| Examples and Kotlin tests | ./gradlew :examples:build |
| Quickstart against a local mock | ./gradlew :examples:quickstartDemo |
| Spec sync, by hand | python3 codegen/spec_sync.py --summary /tmp/summary.md |
openapi/: the API contract.verification.json,account.jsonandwebhook-vectors.jsonare upstream copies, never edited by hand;overlay.jsonholds the SDK naming (DESIGN 4);deprecated-operations.json(when present) keeps removed operations for one minor version.codegen/: the generator (Python). It reads onlyopenapi/.src/main/java/me/didit/resources,src/main/java/me/didit/types,src/test/java/me/didit/resources: generated. Every file starts withCode generated by codegen from openapi/*.json. DO NOT EDIT.src/main/java/me/didit/core,errors,webhooks,authenticationandDidit.java: the hand-written core.examples/: runnable examples and webhook receivers, built in CI.
- Never edit generated files: change
codegen/oropenapi/overlay.jsonand regenerate. CI fails when the committed code is stale. - A new API operation without a name fails the generator with a message naming it; add an entry to
openapi/overlay.json(or ask forx-didit-sdkupstream). - Public API changes need tests, README updates and a conventional commit type that matches their semver impact (
feat:,fix:,feat!:or aBREAKING CHANGE:footer). - A change to core behaviour that DESIGN.md describes (client options, errors, retries, pagination, webhooks, Authentication) is made in all seven SDK repositories, one pull request each, and DESIGN.md changes in all seven in the same words.
- Unit tests never touch the network. Use synthetic data only; webhook secrets in tests start with
whsec_test_, and Authentication keys are generated at test time.
.github/workflows/spec-sync.yml runs daily. When the published API documents change it regenerates the SDK, runs every check and opens a pull request titled chore(spec): sync API spec YYYY-MM-DD, with the added, removed and changed operations and schemas. Removed operations stay, deprecated, until the next minor version; the contract test fails once that version is reached, as a reminder to delete them.
You can push commits to the sync branch (for example hand-written webhook or Authentication changes): while the open sync pull request has a commit of yours, the workflow leaves it alone. Keep the BREAKING CHANGE: footer of the sync commit when you merge. The workflow reads the branch with its token, so it also works while the repository is private; if that read fails, the run fails instead of rebuilding the branch.
Releases are cut by release-please from conventional commits; CHANGELOG.md is generated and never edited by hand. The first release, 1.0.0, shipped on 2026-10-29 with Alex's approval; every release after that publishes straight from the repository (DESIGN 13).
- The workflow
.github/workflows/release-please.ymlruns while the repository variableRELEASES_ENABLEDistrue(set since 1.0.0). Merging the release pull request is the release approval (Alex, 2026-10-29); nobody tags or publishes by hand. - On each push to
main, release-please updates a release pull request (version ingradle.properties,Version.javaand the README, plusCHANGELOG.md). - Merging it creates the
vX.Y.Ztag and the GitHub release. Thepublishjob then runs in themaven-centralenvironment (it holds the secrets; no reviewers), runs./gradlew check, signs and uploads to Maven Central (Central Portal), and attests the jars. - If a publish fails after the tag exists: when the cause is outside the code (an expired token, a missing secret, a Central Portal outage), fix it and rerun the failed
publishjob of that workflow run. A rerun builds the tag's commit, so it never picks up a fix merged tomainlater; when the code has to change, merge the fix tomainand release the next patch version instead.
One-time setup (done for 1.0.0 on 2026-10-29):
- Maven Central: the
me.diditnamespace verified on central.sonatype.com, and a Central Portal user token. - A GPG signing key, with its public key on a key server.
- Secrets of the
maven-centralenvironment:MAVEN_CENTRAL_USERNAME,MAVEN_CENTRAL_PASSWORD,MAVEN_SIGNING_KEY(ASCII-armored private key) andMAVEN_SIGNING_KEY_PASSWORD. - A
maven-centralenvironment holding those secrets, with no required reviewers. The Central Portal token expires on 2027-04-29: generate a new one and replace the two secrets before then. - Optionally
RELEASE_PLEASE_TOKENandSPEC_SYNC_TOKEN(a GitHub App or fine-grained token), so CI runs on the release and sync pull requests. - Finally, the variable
RELEASES_ENABLED=true.