How it fits together
1
Send the hash of the key
When your gate issues a key at account creation, send its SHA-256 as
issued_credential.sha256 on the assessment. Each SDK has a helper that calculates it: hashIssuedCredential in Node, hash_issued_credential in Python. The key itself does not leave your backend.2
Record each request in your gateway
In your API gateway, record every request that uses an issued key. Record the key and the client IP. If you have them, also record the user agent, the model and the token counts. The SDK buffer hashes the key, puts the facts in batches, and sends them to
POST /v1/key_usage/batches in the background.3
Read the reason on the account
A key can get requests from 20 or more IP addresses, or from 3 or more countries, within 24 hours. Then every account whose assessment carried that key gets the
shared_api_key reason (weight 30) in its current risk. You read it on GET /v1/accounts/{account_id}, and in the account of every assessment of that account.The reason stays for 30 days after the last batch that found the key over the limit. This applies only while NoResponse keeps the assessment that carried the key. An assessment that you deleted, or that is past your retention, does not link the key to its account.shared_api_key belongs to the account, so it changes account.risk and the decision for the account. The detail.risk of an assessment does not carry it. NoResponse counts IPv6 addresses by their /64. Thus the rotating addresses of one device count once.
Buffer usage in your gateway
Make one buffer for each process, with a key that has theassess scope. Record each request, and close the buffer on shutdown. record does not block and does not throw, so it is safe on your request path.
TypeScript
key, the SDK hashes it in your process. If you already store the hash, pass keySha256 (key_sha256 in Python).
The buffer sends a batch in two cases:
- When the queue holds
batchSizefacts (default 100, at most 500). - At each
flushIntervalMs(default 5,000 ms). In Python it isflush_interval, in seconds.
maxQueue facts (default 10,000). When the queue is full, the buffer drops the oldest fact and counts it. Thus a slow network costs you old facts, not memory. stats() gives the number of facts that are queued, sent, dropped, failed and refused.
Each batch carries its own Idempotency-Key. The SDK sends the same key on every retry of that batch. Thus NoResponse counts once a batch that the SDK retried after a lost answer. If a batch still fails after the retries, the SDK counts it in failed and passes it to onError (on_error).
The other SDKs give the route as a method that sends one batch: KeyUsage.Record in Go, keyUsage().record in Java, KeyUsage.RecordAsync in C#, keyUsage->record in PHP and key_usage.record in Ruby. Put the events in batches yourself, at most 500 for each call.
Sampling
If your gateway serves more requests than you want to report, record a part of them. SetsampleRate (sample_rate) to a value above 0 and at most 1, such as 0.1. The buffer records that part of the facts at random, and sends the rate with each event. Thus the request and token totals stay correct. The counts of distinct IPs and countries see only the events that you send. Thus with a low rate, a shared key shows up later.
What NoResponse keeps
NoResponse keeps no raw event.
Each organisation has its own digest key. Thus the same IP in two organisations gives two unrelated digests. Some events add nothing, and the
ignored count of the answer includes them:
- An event whose IP is private, reserved or unreadable.
- An event whose time is more than 24 hours old, or more than 5 minutes in the future.
NoResponse also counts a key that no assessment carried. When an assessment carries its hash in
issued_credential.sha256, the usage applies to the account of that assessment.