https://api.echonova.aiDevelopers
Security best practices
How to keep an API key from leaking, limit what a leaked key can do, replace a key safely, trust only genuine webhooks, and audit what your keys did.
An API key is a bearer token: whoever holds it can spend your workspace's credits until you disable or delete it, and the API cannot tell your server from an attacker who copied the key. The controls below exist so that a key is hard to leak, does little damage if it leaks, and is easy to replace. The same thinking applies to a webhook, which is an endpoint anyone can post to once they know its URL.
Keep the key where only your server can read it
The API checks the Authorization header and nothing else: no origin, no
IP address, no client certificate. A key that reaches a browser bundle, a
mobile app, a desktop build or a public repository is a key anyone can
extract and use from anywhere. Keep it on a server you control, read it from
an environment variable or a secrets manager at start-up, and have the
server call the API on behalf of your clients. The secret cannot be
recovered after creation, by you or by anyone else: the portal shows it
once and afterwards displays only the first 8 characters.
Recommended
- A backend route of your own that your app calls; the route holds the key and calls the API.
Less effective
- The key in a mobile app's configuration, calling the API directly from the device.
Never send an API key to a user's device, and never commit one to source control. If a key has been exposed, disable it in the portal at once, then create a replacement. A disabled key is rejected on the next request.
Give each system its own key with only the access it needs
The portal lets you shape a key when you create or Edit it:
| Control | What it limits | What happens outside the limit |
|---|---|---|
| Services | Which of Text to Speech and Speech to Text the key may call. Grant Access to the ones the system needs and leave the rest on No Access. | 403 with This API key does not have access to Text-to-Speech services or the Speech to Text equivalent. |
| Credit Limit | How many credits the key may spend per billing cycle. | Text to Speech calls are rejected with 429 and Monthly spending limit exhausted before they run. Speech to Text calls run and are counted afterwards. |
| The row switch | Whether the key is accepted at all. | 401 on every request until you enable it again. |
Create one key per system that calls the API, named after that system. When one leaks you disable that one, and the others keep working. When the request log shows a call you do not recognise, the key name tells you which system made it. The portal will not save a key without at least one service, so grant exactly what the system needs. A key made before this change with no service selected can still call every service, so open it and choose its services.
Cap the damage with a credit limit
A credit limit is the only control that bounds spend on a key before you
notice a problem. Set it on every key that runs unattended, at a level a
little above the system's normal monthly use. Then subscribe a webhook to
the two spending events, spending.warning at 80% of the limit and
spending.exhausted at the limit, so that an unexpected surge reaches you
as a message rather than as an invoice. Both events carry the key's id;
Webhook events has the bodies. The
count resets on the key's first metered call of a new billing cycle;
see Credits for the
arithmetic.
Replace a key instead of hoping it is still secret
A key's secret is fixed at creation. To replace it, create a new key, deploy it, then delete the old one:
| Step | What to do |
|---|---|
| Create | Create a new key with the same services and credit limit. Copy or download the secret; it is shown once. |
| Deploy | Put the new secret in your server's configuration and restart or reload so it is used. |
| Verify | Make one request with the new key and confirm 200. The old key's Last Used date stops moving once nothing uses it. |
| Delete | Delete the old key. Deleting cannot be undone, and requests with it get 401 from then on. |
Do this on a schedule you can keep, and at once when a person who knew a secret leaves or a machine that held one is decommissioned. If you are unsure whether a key leaked, disable it first with the row switch, which is reversible, and decide about deletion afterwards. The request log keeps a deleted key's entries, so nothing is lost for audit.
Trust a webhook only after you verify it
Your webhook endpoint is public. Anyone who learns its URL can post a JSON
body that looks like job.completed with an audioUrl of their choosing,
or a spending.exhausted that makes you disable a key. EchoNova signs every
delivery with the webhook's secret over the timestamp and the body, so a
forged or altered request fails the check. Verify before you act, compare in
constant time, and reject a timestamp far from your clock; the steps are on
Verify a webhook signature.
| Fact | Why it matters |
|---|---|
| The signing secret is returned once, at creation. | Store it with the same care as an API key. To get a new one, create a second webhook and delete the first, as on the verification page. |
The portal accepts https endpoint URLs only. |
Keep a valid TLS certificate on the endpoint. The body and the headers, including the signature, always cross the network encrypted. |
| A retry carries a fresh timestamp and signature but the same body. | De-duplicate on the content, not on the signature. |
| Deliveries do not come from a fixed, published set of IP addresses. | Do not rely on an IP allowlist for authenticity; rely on the signature. |
| Only the status code of your response matters. | Answer 2xx once the signature checks out and process afterwards. |
Audit what your keys did
Every request whose API key is found is recorded with its method, path,
status, key and time, and the portal shows the most recent ones on the
Request Log tab. Use it to answer "did our system make this call?" and
to spot a key being used from a system that should not have it. A 403 and the
first per-key 429 of each limit window are in the log; a 401, the per-IP
429 and later per-key 429s in the same window are not. The
log holds no request or response body and no header, and it is read in the
portal only. Keep your own log of every request your server makes, with the
key name and the jobId it received, so that the two can be matched. The
page Read the request log explains each
column.
The workspace owner can create, edit and delete keys and webhooks and read the log. Anyone who can create a key can spend your credits, so protect the owner's sign-in with two-factor authentication.
FAQ
A key leaked. What do I do first?
Turn it off with the row switch under Developers, API Keys. The
next request with it gets 401. Then create a replacement, deploy it, and
delete the old key.
Can I restrict a key to my server's IP address?
No. The API checks the Authorization header only. Keep the key on your
server and put a credit limit on it.
Can I get the secret back if I lose it?
No. Create a new key and delete the old one.
Can I rotate a webhook secret in place?
No. Create a second webhook for the same URL and events, deploy its secret, then delete the first. Your endpoint must accept both secrets during the overlap.
Who in my workspace can create keys?
The workspace owner, whose role has developer_api.manage. A key spends
your credits, so keep the owner's account secure.