Skip to main content
If your product gives each new account an API key, account creation is only half of the story. People can sell a key again, share it in a group chat or leak it in a public repository. Such a key then gets requests from many places at once. Report the usage of your issued keys. NoResponse then links that usage back to the account that got the key.

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 the assess 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
If you pass 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 batchSize facts (default 100, at most 500).
  • At each flushIntervalMs (default 5,000 ms). In Python it is flush_interval, in seconds.
The buffer holds at most 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. Set sampleRate (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.
The request and its limits are in Report key usage.