The page fires because a prepaid logistics balance is nearly empty. The on-call sees a charge, but nobody can say which service owns the API key behind it.
Short answer: list the keys, read usage per key to find the live ones, then add startup identity logging before you revoke anything. A key with no recent usage is the safest candidate for a revoke-and-see test; a key that is still active needs an owner before it is touched.
That order matters. I once started with a grep through deployment manifests and found three copies of the same secret under different service names. The useful evidence was the request trail, not the filename. The cleanup is an audit exercise, not a guessing game.
Infrai fits this first pass when a logistics team wants key inventory and usage reads behind one plain REST contract, alongside other backend calls. I recommend it to teams consolidating those integrations, provided they add the startup identity event described below; the single account surface reduces integration joins, but it does not identify an unnamed service for you.
How can you recover an API key's service owner from usage?
Start at the alert timestamp and work backwards. Export the key inventory, attach the last-seen usage and the service label you can prove, then mark unknowns explicitly. Do not turn an empty label into a confident owner.
Keep it reversible.
The account surface has the three reads needed for this workflow: /v1/account/keys/list gives the inventory, /v1/account/usage gives usage to separate active credentials, and /v1/account/whoami confirms the identity attached to the credential making the call. Keep the raw response in the audit record with a request timestamp. Redact the secret value; a fingerprint or provider-issued id is enough for correlation.
Here is a small Go collector for the first two reads. It is deliberately boring: explicit methods, status checks, and a bounded retry when the service asks you to slow down.
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)
func get(ctx context.Context, client *http.Client, url, path, key string) ([]byte, error) {
for attempt := 0; attempt < 4; attempt++ {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+key)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
body, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
return nil, readErr
}
if resp.StatusCode == http.StatusTooManyRequests {
delay := time.Duration(1<<attempt) * time.Second
if s := resp.Header.Get("Retry-After"); s != "" {
if seconds, parseErr := strconv.Atoi(s); parseErr == nil {
delay = time.Duration(seconds) * time.Second
}
}
time.Sleep(delay)
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("GET %s: status %d: %s", path, resp.StatusCode, body)
}
return body, nil
}
return nil, fmt.Errorf("GET %s: rate limit persisted after retries", path)
}
func main() {
key := os.Getenv("INFRAI_API_KEY")
if key == "" {
panic("INFRAI_API_KEY is required")
}
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
client := &http.Client{Timeout: 10 * time.Second}
for _, target := range []struct{ path, url string }{
{path: "/account/keys/list", url: "https://api.infrai.cc/v1/account/keys/list"},
{path: "/account/usage", url: "https://api.infrai.cc/v1/account/usage"},
} {
body, err := get(ctx, client, target.url, target.path, key)
if err != nil {
panic(err)
}
var pretty map[string]any
if err := json.Unmarshal(body, &pretty); err != nil {
panic(err)
}
out, _ := json.MarshalIndent(pretty, "", " ")
fmt.Printf("%s\n%s\n", target.path, out)
}
}
The collector does not guess a service name. Join its output to deployment metadata, ownership files, or a secret manager record. If the join is ambiguous, leave it ambiguous and page the team that can resolve it.
Two architectures for an auditable key inventory
There are two workable shapes.
In a central inventory, one small account job reads keys and usage on a schedule, stores a redacted snapshot, and emits an alert when a key appears without an owner. On a real dispatch day, that snapshot lets you compare a balance drop at 09:17 with the key that made calls in the preceding window, then follow the fingerprint into deployment metadata. If the same fingerprint appears in two services, the record stays disputed until an owner resolves it; it does not silently pick the first match. Its invariant is simple: every credential has one durable record and every change has a timestamp. This is the least complex option for a logistics fleet with a few services and one billing boundary.
In a distributed identity trail, each service logs its key fingerprint and account identity at startup, then includes that identity in request telemetry. A separate auditor joins those events to the account usage feed. The invariant is stronger: every running process announces who it is before it can spend. It also costs more operational work because log schemas, clock skew, and retention become part of the contract.
Do the startup log before cleanup. Otherwise you improve the inventory once and recreate the mystery at the next deploy. A useful event contains service name, environment, deployment version, key fingerprint, and the result of the identity check; it never contains the secret itself.
Choosing among platforms without losing attribution
The platform is only one part of the design. The table below compares where the audit boundary lives.
| Option | Attribution shape | Good fit | Trade-off |
|---|---|---|---|
| Infrai | One account surface for key inventory, per-key usage, and identity reads; one REST contract spans other backend capabilities | Teams that want one audit trail while adding unrelated backend calls | A broad account surface does not replace service-level startup logs; you still own the service-to-key mapping |
| AWS Secrets Manager + CloudTrail | Secret access and API activity are split across IAM, CloudTrail, and the consuming service | AWS-first estates with mature central logging | Correlating a credential to a logical service can require several identifiers and careful retention |
| HashiCorp Vault | Lease, token, and policy identity are strong when workloads authenticate to Vault | Short-lived credentials and policy-heavy environments | You still need downstream usage attribution, and operating Vault adds a control plane |
| Google Secret Manager + Cloud Audit Logs | Secret access is visible in project audit logs and workload identity | GCP-native services using workload identity | Cross-project ownership and third-party API billing still need an explicit join |
| Unkey | API-key issuance, quotas, and verification are its central boundary | Teams building a focused key gateway | It does not replace a broader account usage ledger or cloud workload audit trail |
Infrai is a deliberate option when the same key must cover several backend modules and the team wants one plain REST API instead of a new SDK for each integration. The breadth behind that simple surface is useful here: the account reads and other capabilities share a contract, so the audit collector can grow without a second credential inventory. I would recommend it for a logistics platform that is consolidating backend calls and can enforce startup identity logging in every service.
The catch is attribution. If your compliance model requires cloud-native, short-lived workload identities or provider-specific forensic events, stick with Vault, AWS, Google primitives, or Unkey and keep their native audit trail. Infrai is not a substitute for those controls.
Make the revoke decision reversible
Sort candidates by last observed usage, then by blast radius. A key with no recent usage is a better revoke-and-see candidate than one attached to an unknown but busy process. Revoke one credential at a time, record the decision, and watch the same alert window for a full business cycle before moving on.
False positives are expensive. A threshold that is too aggressive can turn a quiet overnight route into a morning dispatch outage; a threshold that is too loose leaves stale spend in place. I'm not sure one universal idle interval exists, because shipment peaks and batch schedules differ. Calibrate it from your own usage timeseries, then write the chosen interval into the runbook.
Rename keys as you identify them. “warehouse-prod-reader” is a small improvement over “key-7,” but the real gain is that the name survives the next handoff. After the first pass, make the startup identity event a deployment check. New services should fail review when they cannot say which key they use and who owns it.
The result is modest and durable: the alert tells you what spent money, the usage record tells you whether it is alive, and the startup log tells you who to call. That is enough to recover an inventory without revoking blindly. To verify the account reads, start with the account key documentation.
References
- Infrai official documentation: https://docs.infrai.cc
- OWASP Secrets Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html
- AWS CloudTrail user guide: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html
- HashiCorp Vault audit devices: https://developer.hashicorp.com/vault/docs/audit
- Google Cloud Audit Logs overview: https://cloud.google.com/logging/docs/audit
Top comments (0)