Java
apikee for Java — Spring Boot with zero-config autoconfiguration.
Java
Installation
<dependency>
<groupId>dev.apikee</groupId>
<artifactId>apikee-spring</artifactId>
<version>0.1.0</version>
</dependency>Gradle:
implementation("dev.apikee:apikee-spring:0.1.0")Zero-config Spring Boot
Add to application.yml — the filter and Swagger customizer are autoconfigured:
apikee:
secrets:
- ${APIKEE_LOCAL_SECRET} # required
header-name: x-api-key # default
# Server mode (optional)
server-key: ${APIKEE_SERVER_KEY:}
project-env: ${APIKEE_PROJECT_ENV:my-app-production}
fail-open: trueThat's it. No @Bean declarations needed for the standard setup.
Accessing claims
Claims are stored as a request attribute after the filter runs:
@GetMapping("/data")
public ResponseEntity<?> getData(HttpServletRequest request) {
ApikeeClaims claims = (ApikeeClaims) request.getAttribute("apikee.claims");
return ResponseEntity.ok(Map.of(
"tenant", claims.tenant(),
"scopes", claims.scopes()
));
}Issuing keys
Inject ApikeeKeyEngine anywhere in your application:
@Service
public class KeyService {
private final ApikeeKeyEngine engine;
public KeyService(ApikeeKeyEngine engine) {
this.engine = engine;
}
public String issueKey(String tenant, List<String> scopes) {
return engine.create(
KeyOptions.builder()
.tenant(tenant)
.scopes(scopes)
.expiresAt(Instant.now().plus(Duration.ofDays(90)))
.meta(Map.of("plan", "pro"))
.build()
);
}
}Swagger / SpringDoc
Auto-configured when springdoc-openapi-starter-webmvc-ui is on the classpath. The ApikeeOpenApiCustomizer bean injects ApikeeAuth into the spec and applies it globally.
To customise manually:
@Bean
public ApikeeOpenApiCustomizer apikeeSwagger() {
return new ApikeeOpenApiCustomizer("x-api-key");
}Scope enforcement
Spring doesn't have a built-in scope guard, but the pattern is straightforward:
private void requireScope(ApikeeClaims claims, String... required) {
for (String s : required) {
if (claims.scopes().contains(s)) return;
}
throw new ResponseStatusException(HttpStatus.FORBIDDEN,
"Required scope(s): " + String.join(", ", required));
}
@DeleteMapping("/items/{id}")
public ResponseEntity<?> deleteItem(@PathVariable int id, HttpServletRequest req) {
requireScope(claims(req), "admin");
// ...
}Manual configuration
When you need full control:
@Configuration
public class ApikeeConfig {
@Bean
public ApikeeKeyEngine engine() {
return new ApikeeKeyEngine(List.of(
System.getenv("APIKEE_LOCAL_SECRET")
));
}
@Bean
public FilterRegistrationBean<ApikeeFilter> filter(ApikeeKeyEngine engine) {
var filter = new ApikeeFilter(engine, "x-api-key", null);
var bean = new FilterRegistrationBean<>(filter);
bean.addUrlPatterns("/*");
bean.setOrder(-100);
return bean;
}
}Configuration reference
| Property | Type | Default | Description |
|---|---|---|---|
apikee.secrets | List<String> | required | Signing secrets. First is current. |
apikee.header-name | String | x-api-key | Header to read the key from. |
apikee.server-key | String | null | apikee.dev project key. Enables server mode. |
apikee.project-env | String | null | apikee.dev project_env slug. |
apikee.auto-register-endpoints | boolean | true | Register endpoints on first request. |
apikee.fail-open | boolean | true | Allow through if server call fails. |
apikee.server-timeout-ms | long | 3000 | Timeout for apikee.dev calls. |
apikee.filter-order | int | -100 | Servlet filter order. |

