Security Model
The split that matters most: the platform owns the key, your code owns the broadcast. Everything in this page is a consequence of that split.
What the platform owns
Section titled “What the platform owns”| Thing | Where | Why |
|---|---|---|
| The private key | AWS KMS, never exported | KMS is FIPS 140-2 validated; raw key material is unreadable to humans and software alike. |
| The signing operation | KMS Sign API | The platform never holds your key in plaintext, even briefly. |
| Policy enforcement | Pre-sign gate | Caps, allow-lists, and time windows are checked before the key is invoked. A blocked tx is never signed. |
The mapping (projectId, userId) → wallet | Platform DB | Lets you address wallets by your own user ID without storing addresses yourself. |
What your code owns
Section titled “What your code owns”| Thing | Where | Why |
|---|---|---|
The userId | Your DB / message queue | The platform stores it too, but you address wallets by your own ID — there’s no “platform user ID” you need to track. |
| The transaction recipient and value | Your application logic | The platform signs what you ask it to (within policy). It does not synthesize transactions on your behalf. |
| The nonce | Your DB or live RPC | The platform has no view of your broadcasting state. Nonce tracking is yours. |
| The RPC endpoint | Your code | You pick where the signed tx is broadcast. The platform never makes the network call. |
| The confirmation strategy | Your code | Block polling, websockets, fire-and-forget — entirely up to you. |
Trust boundaries
Section titled “Trust boundaries”┌─────────────────────────────────┐│ Your Node.js server ││ ─ holds API key ││ ─ holds userId mapping ││ ─ holds the chosen RPC │└────────────┬────────────────────┘ │ HTTPS, signed with API key ▼┌─────────────────────────────────┐│ 0xGasless API ││ ─ resolves userId → wallet ││ ─ enforces policy ││ ─ calls KMS Sign │└────────────┬────────────────────┘ │ AWS internal ▼┌─────────────────────────────────┐│ AWS KMS ││ ─ holds raw key material ││ ─ never exports it ││ ─ returns signed bytes only │└─────────────────────────────────┘There are exactly three places that can produce a signature:
- Anyone holding your API key can request signatures from the platform.
- The platform itself is the only caller permitted on KMS.
- KMS is the only system that ever touches the raw key.
If any of these is compromised the others limit the blast radius:
- Stolen API key → attacker can request signatures from the platform, but every request still goes through your policy rules. Tight policies (per-tx cap, allow-list, time windows) make a stolen key much less valuable.
- Compromised platform process → attacker can call KMS for any project’s wallets they can authenticate against, but cannot extract the underlying key material.
- Compromised KMS → out of scope: the platform’s threat model assumes AWS KMS itself is not breached.
Your API key
Section titled “Your API key”The project API key is the credential. Treat it like a database password:
- Never check it into git. Use
.env, KMS, Secrets Manager, or your platform’s secret store. - Never expose it to browser code. The SDK is for server-side use only.
- Rotate it from the dashboard if you suspect leakage.
- Set narrow policies in the dashboard so a leaked key has bounded blast radius.
A leaked API key gives an attacker the ability to call the platform on your behalf. They cannot exfiltrate private keys, but they can request signatures for any wallet in your project — bounded by your policies. The defense-in-depth is tight policies, not just key secrecy.
What the platform does NOT do
Section titled “What the platform does NOT do”| Thing | Why |
|---|---|
| Broadcast transactions. | Sign-and-broadcast as a single platform action would centralize broadcast logic and make multi-chain support brittle. Keeping broadcast in your code means you choose the RPC, retry policy, and confirmation method. |
| Track nonces. | Nonce tracking has to know what’s been broadcast. The platform doesn’t know — your code does. |
| Track balances. | Same reason. The chain has the authoritative view; your code reads it. |
| Hold gas for you. | Server wallets are EOAs. They pay their own gas in the chain’s native token. Top them up via the dashboard or any standard transfer. |
| Reveal the private key. | KMS never exports raw key material. There is no “export to seed phrase” flow. If you need that property, server wallets are the wrong tool — use a self-custodial wallet instead. |
What end users see
Section titled “What end users see”For bot deployments, the typical end-user model is:
- The user knows their wallet exists (you show them the address on
/wallet). - The user doesn’t know there’s a key in KMS. From their POV the wallet is “their bot wallet”.
- The user cannot sign with the wallet from outside your bot. There’s no seed phrase to export.
- You enforce limits. Policies in the dashboard cap per-tx amounts, daily totals, and allowed recipients.
This is the right shape for Telegram bots, trading agents, and AI workers — environments where the human never holds the key in the first place. It’s the wrong shape for “give the user a key they can take elsewhere” — for that, use Embedded Wallets, where the key lives in the user’s browser.
Auditability
Section titled “Auditability”Every server-wallet operation is logged in the dashboard:
- Wallet creation (with
userId,projectId, chain). - Sign requests (with target address, value, chain, policy decision).
- Policy violations (with reason).
This is the audit trail you’d otherwise build yourself. Use it to monitor for runaway scripts, debug policy false-positives, and produce a paper trail for compliance reviews.
What’s next
Section titled “What’s next”- API reference — every method.
- Errors — recovery patterns.