request through Keman
# prod-api, called from 192.0.2.20 (DE, AS64502)
POST /v1/chat/completions
Authorization: Bearer kmn_MjI3yW5z_…
{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "hi"}]}
HTTP/1.1 200 OK
{
"id": "chatcmpl-demo",
"object": "chat.completion",
"model": "gpt-4o-mini",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "Hello from the demo upstream."},
"finish_reason": "stop"
}
],
"usage": {"prompt_tokens": 2316, "completion_tokens": 448, "total_tokens": 2764}
}
Forwarded. Keman swaps in the real key and streams the provider’s answer back untouched. In the demo, the provider is a local mock.
# prod-api, called from 203.0.113.200 (BR, AS64510)
POST /v1/chat/completions
Authorization: Bearer kmn_MjI3yW5z_…
{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "hi"}]}
HTTP/1.1 403 Forbidden
X-Keman-Error: network_not_allowed
{
"error": {
"type": "keman_error",
"code": "network_not_allowed",
"message": "This client network is not allowed for this virtual key."
}
}
Refused before it reaches OpenAI. The address is outside the key’s network. Five refusals in five minutes raise an alert.
# prod-api, called from 192.0.2.20 (DE, AS64502)
POST /v1/chat/completions
Authorization: Bearer kmn_MjI3yW5z_…
{"model": "o3", "messages": [{"role": "user", "content": "hi"}]}
HTTP/1.1 403 Forbidden
X-Keman-Error: model_not_allowed
{
"error": {
"type": "keman_error",
"code": "model_not_allowed",
"message": "This model is not allowed for this virtual key."
}
}
Refused. prod-api may only call gpt-4o and gpt-4o-mini, so a stolen copy can’t run up a bill on a pricier model.
# billing-svc, called from 192.0.2.30 (DE, AS64502)
POST /v1/payouts
Authorization: Bearer kmn_2M1MxJLa_…
{"amount": 250000, "currency": "usd"}
HTTP/1.1 403 Forbidden
X-Keman-Error: path_not_allowed
{
"error": {
"type": "keman_error",
"code": "path_not_allowed",
"message": "This path is not allowed for this virtual key."
}
}
Refused. Generic APIs need a path allowlist. This key may create charges and read customers. Payouts were never on the list.
# old-intern, called from 198.51.100.200 (SG, AS64512)
POST /v1/chat/completions
Authorization: Bearer kmn_a2gxDT24_…
{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "hi"}]}
HTTP/1.1 401 Unauthorized
X-Keman-Error: key_disabled
{
"error": {
"type": "keman_error",
"code": "key_disabled",
"message": "This virtual key is disabled."
}
}
Refused, and you hear about it. Any use of a disabled key raises a high-severity alert with the address it came from.
# support-bot, called from 203.0.113.200 (BR, AS64510)
POST /v1/messages
x-api-key: kmn_qWmeK8lJ_…
{"model": "claude-opus-4-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "hi"}]}
HTTP/1.1 401 Unauthorized
X-Keman-Error: key_revoked
{
"error": {
"type": "keman_error",
"code": "key_revoked",
"message": "This virtual key has been revoked."
}
}
Dead the moment you rotated. The app’s new key keeps working, and every attempt with the old one still raises an alert.
# repo-decoy, called from 192.0.2.200 (NL, AS64511)
POST /v1/chat/completions
Authorization: Bearer kmn_ZNDo8sy2_…
{"model": "gpt-4o", "messages": [{"role": "user", "content": "hi"}]}
HTTP/1.1 401 Unauthorized
{
"error": {
"message": "Incorrect API key provided.",
"type": "invalid_request_error",
"param": null,
"code": "invalid_api_key"
}
}
Answered exactly like OpenAI answers a bad key, so the thief learns nothing. It never reaches OpenAI, and it raises a critical alert.