Security
Your private key stays yours
Anis never sees your private key — only its public half, at enrolment. Keep the private half where you keep your most sensitive secrets: a key vault, a hardware security module, or a file only your service can read.
- Never put it in a settings file, an environment variable, source control or anywhere a log or crash report can reach.
- Signing only needs something that can sign bytes with ECDSA P-256 and return the 64-byte signature. A vault or hardware module that signs on your behalf can do it without the key ever entering your application — the SDKs accept any such signer.
Anis signs the answers that matter
Anis signs an answer when it moves money, delivers the cards, establishes your key or stops access. On those calls every answer is signed — the success and every refusal — and your client requires the signature and checks it before acting; see Verifying answers. An answer from one of these calls that has no signature, or whose signature does not check, is a failure: throw it away, never act on it, never log it and carry on. Never write “verify the signature if there is one” — on these calls a missing signature is exactly what a forger sends.
| Anis signs every answer of | Why |
|---|---|
| Add or remove an allowed address — Staging only — testing endpoints, not available in production | the answer confirms an access-network change |
| Suspend your application and revoke a key | the answer confirms access stopped |
| Place an order and read an order | money moves, and the answer is the order’s outcome |
| Create or read a meter charge | the answer reports charging and its tokens or refund |
| Create, read or correct a direct recharge | the answer reports payment or delivery, or accepts a recipient correction with signed 202, Location and the three-member processing acknowledgement, without an direct recharge or order body |
| Set the webhook endpoint, test or redeliver | the answer confirms a delivery-management change |
| Reveal a card and reveal an invoice | the answer delivers the card codes |
| The four enrolment calls: read an invitation, submit a key, prove you hold it, read the status | the answer establishes your key |
| Check your signature | the call exists to test signatures |
The answers of every other call are not signed: your profile, the wallets, the five catalogue calls, the list
of owned cards and one owned card. They carry no Signature and no Signature-Input, but they still carry
Content-Digest and X-Request-Id. There is nothing to verify on them — TLS protects them — and a refusal from
one of these calls is not signed either. Anis’s public key document is not signed, as before.
Meter packages and charge lists, direct recharge products, locations, quotes and lists, webhook endpoint reads and webhook event lists have unsigned answers. Their requests are still signed. Incoming webhooks use their own verification profile, described in Verifying webhooks.
Your own requests do not change: you still sign every request, on every call, exactly as in Signing requests.
One address per deployment
Each Anis deployment is fully separate — its own address, keys and data. There is no setting that switches between them; the address you call decides. A key enrolled with one deployment means nothing to another.
Replacing and revoking your key
- Replacing: Anis staff start the replacement and send you a new invitation; enrol the new key. Both keys work
during the overlap Anis staff set — up to 30 days, counted from when the new key starts working. When the overlap ends, the old key is refused as
invalid_credentialsby itself — nobody needs to do anything. Move your signer to the new key id before then. - Your key’s end date:
keyExpiresAton the enrolment status is the date your active key stops working (absent until the key is active). Ask Anis staff for a replacement weeks before it: a key past its end date is refused asinvalid_credentialson every call, including reveals of cards you already bought. - Revoking: from the moment a key is revoked, every call signed with it is refused as
invalid_credentials. To sign again, enrol a new key from a new invitation. - If you think your key leaked, use self-service stop and report it to support@anis.ly at once.
Stop access yourself
Use Suspend your application to stop all access for your application, or
Revoke an application key to stop one key, as soon as you suspect a compromise or need
an emergency stop. Both take a required reason of 1 to 500 characters after trimming. Sign the body digest and
use a fresh nonce; neither needs a scope or an idempotency key for an admitted request.
The stop is immediate. Only Anis staff can resume a suspended application. A revoked key never works again; revoking the key you are using requires a new invitation and enrolment before you can sign again. Every stop, including one made by staff, emails your technical contact; a stop made by your team also emails support@anis.ly.
If you have lost the private key entirely, you cannot sign a stop request: contact support@anis.ly immediately. Report any suspected compromise there at once, even after using self-service stop. Read the draft Evidence and disputes terms.
Allowed networks
Your application may only be called from the networks agreed with Anis. Tell Anis staff the networks you will call
from when you ask for access (see Getting access). A call from any other address is refused
as insufficient_scope — the same answer as a missing permission, on purpose.
To tell the two apart, call GET /v1/profile from the same host. If it is refused as
insufficient_scope too, the network is the cause (or your application lacks profile:read). If it succeeds, the
network is fine: compare the permissions it lists with the one the refused route needs.
Card codes are secrets
Card codes appear in exactly two places: the answer that first reports a completed order, and a reveal. Store them where you keep secrets, and never write them to logs, traces or error reports.
Clock
Signatures carry their time, and so do Anis’s signed answers. Keep your server clock synchronised (NTP): a clock
that drifts gets requests refused as invalid_credentials and signed answers
discarded as too old.
Sign for 60 seconds or less — see Signing requests.
Reporting a security issue
Write to support@anis.ly and quote the request ids involved.
Get allowed addresses: Staging only — testing endpoints, not available in production. Its answer is unsigned; add/remove answers, including refusals, require signature verification. These three routes are permanently excluded from SDKs.