Ktor
Installation
Add the dependency:
1
2
3
4
5
<dependency>
<groupId>com.botbye</groupId>
<artifactId>kotlin-module</artifactId>
<version>3.0.1</version>
</dependency>
1
implementation("com.botbye:kotlin-module:3.0.1")
Configuration
Phishing lives in its own dedicated BotbyePhishingClient, separate from the evaluate Botbye client. It is identified by a public, browser-safe clientKey, so it needs no server key — create it once at startup and reuse it across requests. On construction it makes a one-off, best-effort server-integration init handshake that reports this server-side integration to BotBye; it is non-blocking and never affects your request path.
BotbyePhishingConfig takes 2 values: endpoint (optional, defaults to https://verify.botbye.com) and clientKey.
Getting clientKey
clientKey is the public, browser-safe identifier of your phishing project. It travels in the asset URL path, so it is safe to expose — no secret token and no Base64 encoding are required.
Find it on the Get Started screen of your phishing project in the BotBye dashboard.
1
2
3
4
5
6
7
8
9
import com.botbye.phishing.BotbyePhishingClient
import com.botbye.phishing.BotbyePhishingConfig
val phishing = BotbyePhishingClient(
BotbyePhishingConfig(
endpoint = "https://verify.botbye.com",
clientKey = "<public-client-key>",
)
)
Usage
Expose a single Ktor route that proxies phishing pixel requests. fetchImage is a suspend function, so it can be called directly inside route handlers.
When you use an SVG image, your application must also expose an endpoint on the client origin that handles requests to /{imageId}.png, where imageId is the value that arrives in the forwarded pixel query as image_id.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
routing {
get("/api/phishing/image") {
val origin = call.request.header("Origin")
val query = call.request.queryParameters.entries()
.associate { (k, v) -> k to v.first() }
val response = phishing.fetchImage(origin = origin, query = query)
if (response.error != null) {
call.respondText(response.error?.message ?: "upstream error", status = HttpStatusCode.BadGateway)
return@get
}
val contentType = response.headers["Content-Type"] ?: "image/png"
call.response.header(HttpHeaders.ContentType, contentType)
call.respondBytes(bytes = response.body, status = HttpStatusCode.fromValue(response.status))
}
}
Settings
Configuration parameters for phishing integration:
| Setting | Description | Required | Default Value |
|---|---|---|---|
| endpoint | Host of the phishing API | no | https://verify.botbye.com |
| clientKey | Public client-key of your phishing project | yes | - |