Skip to content
DikoAPI
API keys

Security guidelines

Open as Markdown

How to store keys, rotate them, what to do after a leak and what an IP allowlist really protects.

Storing keys

An API key grants access to your meetings and library, so treat it like a password.

  • Keep it in a secrets store or an environment variable: a cloud secrets service, your CI secret settings, or a .env file that is in .gitignore.
  • Never put a key in code or a repository, not even a private one. History remains.
  • Never use a key in a browser, a mobile app or any code that ships to users. The API does not allow browser requests (there is no CORS), and a key in client code is no longer a secret. Call the API from your own server.
  • Do not put a key in URLs, logs, error trackers, request dumps or screenshots. A key in a URL is rejected anyway (400 api_key_in_query). On the command line pass the key through an environment variable, not an argument that the process list can show.
  • One key per integration and environment. Then a revocation touches only one system.
  • The smallest scopes that work and a short expiry (see Scopes).

Diko follows the same principle: it stores only the SHA-256 hash of your key, and the key itself is never written to logs, e-mails or error responses. Webhook secrets are stored encrypted.

Key rotation recipe

Rotate keys regularly and every time someone who had access leaves the team. Rotation lets you swap a key without downtime because the old one keeps working for a while.

  1. Create a new key. Under Nustatymai → API (Settings → API, /settings/api) choose Rotuoti raktą (Rotate key) in the key menu, pick the grace period (24 hours by default) and confirm by signing in again. The new key inherits the name, scopes and IP list and is shown once. The old key gets the label Galioja iki … (Valid until …).
  2. Deploy the new key. Put it in your secrets store and redeploy your systems.
  3. Verify. Call GET /me: api_key.id must be the new key’s and api_key.rotated_from the old one’s. In the app, the old key’s Paskutinis panaudojimas (Last used) should stop updating.
  4. Revoke the old key. Revoke it as soon as you are sure nothing uses it any more, or wait for the grace period to end: it then becomes revoked (rotated) automatically.

Keys have a limited lifetime (365 days at most) and Diko reminds you by e-mail 7 days and 1 day before expiry, so rotation becomes a routine rather than firefighting.

A leaked key

If a key may have leaked (it landed in a repository, a log, a screenshot or a departed colleague’s laptop), act at once:

  1. Revoke the key under Nustatymai → API (/settings/api). Revoking needs no re-authentication so that it is quick. The revocation takes effect within 10 seconds at most and is final. It also cancels the key’s imports that are still queued or running, so nothing it started keeps spending credits (see Imports when a key stops working). If you are not sure which key leaked, use Atšaukti visus raktus (Revoke all keys) at the bottom of the page.
  2. Create a new key with the smallest scopes that work and deploy it.
  3. Review the usage. The key’s Paskutinis panaudojimas (Last used), the request statistics and the audit log under Žurnalas (Log, /settings/api/zurnalas) show when and from where the key was used. An IP is shown only when Diko could determine it reliably.
  4. Review your webhooks and, if in doubt, rotate their secrets. A key cannot change webhook endpoints, so the addresses stay as you set them.
  5. Remove the cause. Even after you delete a key from code it remains in the repository history, so consider it unusable and make sure the mistake does not repeat.

GitHub secret scanning

Diko keys have a recognisable prefix dk_live_ and a checksum, so secret scanners find them without false alarms. Diko has an endpoint for GitHub secret scanning reports: when GitHub detects a Diko key in a public repository and reports it, the key is revoked automatically (reason leaked), its queued and running imports are canceled and the owner gets an e-mail. That works only once Diko’s registration in GitHub’s secret scanning program is complete, and only for what GitHub scans (public repositories). It is an extra safety net, not a substitute for care: if you know a key leaked, revoke it yourself right away.

IP allowlist

You can give a key a list of IP addresses (CIDR) it is accepted from. It is an extra layer in case the key leaks.

How it works:

  • Diko believes the client IP only for requests sent to https://api.diko.app/api/v1. There the hosting edge replaces any client-sent X-Forwarded-For header with exactly two addresses, <client>, <edge>, so a forged header never gets through and the first address is the caller’s. Any other header shape is not believed.
  • Through the app domain (https://studio.diko.app/api/v1, served via Vercel) the first address is Vercel’s, not yours. Diko never trusts the client IP there, so a key with an IP allowlist always gets ip_not_allowed on that domain.
  • A key with a list is accepted only from a reliably determined IP that is on the list. Otherwise the API returns 403 ip_not_allowed. This is “fail closed” behaviour: when in doubt, the request is rejected.
  • The IP is checked before any key-state error, so a leaked key used from a foreign address cannot learn whether it is still valid.
  • The list can hold up to 20 entries. Changing the IP list needs re-authentication.

Practical tips:

  • The outbound addresses of cloud and serverless platforms often change. An IP allowlist does not suit such an environment unless you have a fixed outbound address.
  • Mind IPv4 and IPv6: your server may reach the API over a different protocol than you expect.
  • Diko stores last_used_ip, the audit trail and e-mail IPs only when the IP was determined reliably; otherwise null is shown. Treat these addresses as hints, not as proof of where a request came from.
  • Debugging. If every call returns ip_not_allowed, call GET /me with a key that has no IP restriction and check the request field. request.ip is the address Diko saw and request.ip_trusted says whether Diko believes it. If ip_trusted is false, check that you call api.diko.app.

Team oversight

A team owner and administrator see the key metadata of current members (name, hint, scopes, status, last use) and can revoke those keys. They never see a key secret, and they do not see another person’s IP address or IP allowlist either. The rules:

  • an administrator cannot act on the owner’s or other administrators’ keys;
  • everyone manages their own keys through their own list, not through the team section;
  • when a key is revoked, the member gets an e-mail and the action is recorded in the audit trail.

Membership and plan changes

Keys belong personally to you, because the API data is your meetings and your library.

  • You leave a team or are removed. Keys are not deleted, but every request checks the plan again. If you no longer have a Verslas plan, requests return 403 plan_required. The change takes effect at once.
  • You downgrade or a subscription ends. Keys stay, but the API does not work until the plan allows it. When the plan is restored, the keys work again. GET /me always shows access.allowed and the reason.
  • The account is disabled or archived. All its keys are revoked (user_disabled) and webhook endpoints are switched off.
  • You change or reset your password. You get an e-mail listing the active keys and webhooks with an Atšaukti visus (Revoke all) link (an endpoint is named by its host and ID only, never by its full address, because the path of a webhook address is often a secret), and the API page in the app shows a warning for 7 days.
  • API access suspension. A Diko administrator can suspend an account’s API access: then requests get 403 api_access_suspended.

Security checklist

  • The key is in a secrets store, not in code.
  • The key is used only from a server.
  • Every integration has its own key with the smallest scopes.
  • The expiry is short and rotation is scheduled.
  • The webhook receiver checks the signature and the timestamp.
  • You know how to revoke a key within a minute.

Search for a topic, an endpoint or an error code.

Search across all documentation pagesesc close