Endpoints¶
Learn how InspeKtor documents your Ktor route definitions.
HTTP Methods¶
InspeKtor automatically detects all standard HTTP methods:
route("/resource") {
get { /* GET /resource */ }
post { /* POST /resource */ }
put { /* PUT /resource */ }
patch { /* PATCH /resource */ }
delete { /* DELETE /resource */ }
head { /* HEAD /resource */ }
options { /* OPTIONS /resource */ }
}
Route Definitions¶
Simple Routes¶
Nested Routes¶
route("/api") {
route("/v1") {
route("/users") {
get {
// Documented as GET /api/v1/users
}
}
}
}
Path Parameters¶
Path parameters are automatically detected from the {param} syntax:
route("/users/{userId}") {
get {
// Documented with path parameter 'userId'
val userId = call.parameters["userId"]
}
route("/posts/{postId}") {
get {
// Documented with both 'userId' and 'postId' parameters
}
}
}
Generated OpenAPI:
/users/{userId}:
get:
parameters:
- name: userId
in: path
required: true
schema:
type: string
/users/{userId}/posts/{postId}:
get:
parameters:
- name: userId
in: path
required: true
schema:
type: string
- name: postId
in: path
required: true
schema:
type: string
Organizing Routes¶
Separate Route Functions¶
Split your routes into separate functions for better organization:
@GenerateOpenApi
fun Application.module() {
routing {
userRoutes()
productRoutes()
orderRoutes()
}
}
fun Route.userRoutes() {
route("/users") {
get { /* ... */ }
post { /* ... */ }
}
}
fun Route.productRoutes() {
route("/products") {
get { /* ... */ }
post { /* ... */ }
}
}
Route Extensions¶
Use extension functions for cleaner code:
fun Route.crudRoutes(path: String, handler: CrudHandler) {
route(path) {
get { handler.list(call) }
post { handler.create(call) }
route("/{id}") {
get { handler.get(call) }
put { handler.update(call) }
delete { handler.delete(call) }
}
}
}
Multiple API Versions¶
Document multiple API versions:
@GenerateOpenApi
fun Application.module() {
routing {
route("/api/v1") {
@Tag(["v1"])
route("/users") {
get { /* v1 implementation */ }
}
}
route("/api/v2") {
@Tag(["v2"])
route("/users") {
get { /* v2 implementation */ }
}
}
}
}
Base Path¶
All routes are documented relative to the server URL configured in your build.gradle.kts:
swagger {
documentation {
servers = listOf(
"https://api.example.com",
"http://localhost:8080"
)
}
}
Authenticated Routes¶
Routes under Ktor's authenticate block work the same way:
routing {
// Public routes
get("/health") { /* ... */ }
authenticate("auth-jwt") {
// Protected routes - document security in build.gradle.kts
route("/users") {
get { /* ... */ }
}
}
}
Deprecated Endpoints¶
Deprecation comes from Kotlin's own @Deprecated annotation. Annotate a route function — every endpoint it defines (including nested routes) is marked deprecated:
@Deprecated("Use /api/v2/users instead")
fun Route.legacyUserRoutes() {
@KtorDescription(summary = "Get user (deprecated)")
get("/api/v1/users/{id}") {
// Old implementation
}
}
Generated — the @Deprecated message is appended to the operation description, since OpenAPI's deprecated field is a plain boolean:
/api/v1/users/{id}:
get:
summary: "Get user (deprecated)"
description: "Deprecated: Use /api/v2/users instead"
deprecated: true
Note
Kotlin does not allow @Deprecated directly on a get(...)/post(...) expression — its targets don't include expressions. Place it on the Route extension function (or the @GenerateOpenApi module function) that declares the endpoints. When nested functions carry their own @Deprecated, the innermost message wins.
Wildcard Routes¶
Wildcard routes are documented with the wildcard syntax:
route("/files/{path...}") {
get {
// Documented as /files/{path}
val path = call.parameters.getAll("path")
}
}
Static Content¶
Static content routes are generally excluded from API documentation. If you need to document file serving endpoints, use explicit routes: