Security Model
Urblock implements defense-in-depth across API authentication, wallet management, and data isolation. Every layer enforces security independently so a single failure doesn't compromise the system.
Security Overview
┌───────────────────────────────────────────────────────────┐
│ TLS Transport │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Rate Limiting (per tenant) │ │
│ │ ┌───────────────────────────────────────────────┐ │ │
│ │ │ API Key / JWT Authentication │ │ │
│ │ │ ┌─────────────────────────────────────────┐ │ │ │
│ │ │ │ Scope Authorization │ │ │ │
│ │ │ │ ┌───────────────────────────────────┐ │ │ │ │
│ │ │ │ │ Input Validation (DTOs) │ │ │ │ │
│ │ │ │ │ ┌─────────────────────────────┐ │ │ │ │ │
│ │ │ │ │ │ Tenant Isolation (DB) │ │ │ │ │ │
│ │ │ │ │ │ ┌───────────────────────┐ │ │ │ │ │ │
│ │ │ │ │ │ │ Encrypted Storage │ │ │ │ │ │ │
│ │ │ │ │ │ └───────────────────────┘ │ │ │ │ │ │
│ │ │ │ │ └─────────────────────────────┘ │ │ │ │ │
│ │ │ │ └───────────────────────────────────┘ │ │ │ │
│ │ │ └─────────────────────────────────────────┘ │ │ │
│ │ └───────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘
API Key Security
| Aspect | Implementation |
|---|---|
| Key format | sk_live_..., sk_test_..., pk_live_..., pk_test_... |
| Storage | bcrypt hash in PostgreSQL — no plain keys stored |
| Exposure | Plain key returned only at creation (POST /v1/api_keys) |
| Transport | TLS only — keys sent via Authorization: Bearer header |
| Rotation | POST /v1/api_keys/:id/rotate — seamless rotation without downtime |
| Scopes | Fine-grained permission control per key |
| IP allowlist | Optional allowed_ips restriction |
| Expiration | Optional expires_at for auto-expiring keys |
Key Types
| Prefix | Access Level | Use Case |
|---|---|---|
sk_live_ | Full (mainnet) | Server-side production |
sk_test_ | Full (testnet) | Server-side development |
pk_live_ | Read-only (mainnet) | Client-side read operations |
pk_test_ | Read-only (testnet) | Client-side development |
Key Lifecycle Best Practices
// 1. Create a scoped, time-limited key
const key = await urblock.apiKeys.create({
name: "ci-deploy-key",
scopes: ["tokens:write", "transactions:write"],
expires_at: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), // 24h
allowed_ips: ["10.0.0.0/8"],
});
// key.api_key = "sk_test_..." — store in CI secrets, never commit
// 2. Rotate before compromise
const rotated = await urblock.apiKeys.rotate(key.id);
// Old key revoked immediately, new key returned
// 3. Audit key usage
const keys = await urblock.apiKeys.list();
for (const k of keys.data) {
console.log(`${k.name}: last used ${k.last_used_at}, scopes: ${k.scopes}`);
}
Wallet Security
Urblock handles managed signing so your application does not need to store tenant private keys in application code.
| Component | Protection |
|---|---|
| Root wallet material | Kept server-side and never returned by the public API |
| Signing keys | Encrypted at rest before persistence |
| Transaction signing | Performed only inside controlled signing flows |
| Wallet addresses | Treated as public identifiers |
Private keys are never exposed in normal API responses. Signing happens within the platform's transaction pipeline and only for authorized requests.
Tenant Isolation
Urblock enforces tenant scoping across request handling, data storage, caching, and background processing.
- No cross-tenant data access — resources are always resolved in tenant context
- No shared signing context — each tenant operates within its own platform boundary
- Scoped resources — tokens, transactions, webhooks, and related records belong to exactly one tenant
- Isolated background work — asynchronous processing preserves tenant ownership metadata
Tenant scoping is enforced in multiple layers so a mistake in one layer does not automatically expose another tenant's data.
Input Validation
All API inputs are validated before processing:
- Schema validation on every request payload
- Strict typing for values such as token amounts and identifiers
- Required vs optional fields enforced at the API boundary
- Business validation for addresses, networks, and resource-specific rules
- Parameterized data access to avoid injection-style attacks
Rate Limiting
| Default | Value |
|---|---|
| Requests per minute | 100 per tenant |
| Headers | X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset |
| Exceeded | HTTP 429 with rate_limit_error |
Request Security
| Protection | Implementation |
|---|---|
| Request ID | X-Request-Id header on every response |
| CORS | Configured per environment |
| Logging | Authorization headers never logged |
| Webhook signing | HMAC-SHA256 with per-endpoint secret |
Platform Security Operations
Urblock uses standard production controls for secret management, token signing, auditability, and incident response.
For API consumers, the important guarantees are:
- sensitive credentials are not exposed in normal API workflows
- authentication material is managed server-side
- security-relevant events are auditable internally
- operational rotation and incident procedures exist for internal responders
Detailed operator runbooks and deployment procedures are intentionally kept outside the public developer documentation.
Idempotency
All blockchain write operations accept an idempotency_key:
- First request: executes normally, stores result
- Duplicate request: returns stored result without re-executing
- Prevents double-spend, duplicate deploys, and duplicate mints
Roles & Access Control
On-chain access control is managed via OpenZeppelin's AccessControl:
| Role | Permission |
|---|---|
DEFAULT_ADMIN_ROLE | Grant/revoke any role |
MINTER_ROLE | Mint new tokens |
PAUSER_ROLE | Pause/unpause transfers |
BURNER_ROLE | Burn tokens |
Roles are managed via the Roles API and enforced at the smart contract level.
Integration Security Checklist
Use this checklist when shipping your integration:
-
sk_live_keys stored only in backend secrets -
pk_live_keys used for all client-side code (never exposesk_keys) - API keys scoped to minimum required permissions
-
allowed_ipsset on production secret keys when applicable -
expires_atset on temporary and CI/CD keys - Webhook signature verification enabled in your handler
- Application retry logic respects rate limits and idempotency
- Regular API key rotation schedule established
Next Steps
- Authentication — how API authentication works
- Architecture — system architecture overview
- API Keys API — API key management endpoints
- Roles API — on-chain access control