Vaarta Identity Studio
Platform
API security

Every call identified, scoped and on the record

Servers, browsers, services and devices each get the right kind of credential. Keys are hashed at rest, shown once, scoped, and rotated with overlap. Identity changes reach your systems as signed webhooks.

Book a demoWebhook signatures
SDK credentials · Objiq · productionLive
Backend keyscopes: auth, user, org
Browser key[your domain] only
Service keyscopes: metering
Shownonce, at creation
StoredSHA-256 hash

Each environment is its own application with its own keys, signing keys and issuer.

Why it matters

A leaked key should be small, short-lived and visible

A small blast radius

Scopes, domain and address limits, and per-environment applications keep one key from reaching everything.

Secrets are never shown twice

Keys and webhook secrets appear once. Echoes in responses are redacted.

Your systems hear about changes

Signed webhooks tell you when a member is removed or an account is locked.

How it works

A signed webhook, end to end

  1. 1Identity StudioSomething changesFor example member.removed or account.locked.
  2. 2Identity StudioSign the deliveryX-Webhook-Signature: t=<time>,v1=HMAC-SHA256(secret, "<t>.<body>").
  3. 3Your endpointCheck and dedupeVerify the signature and time; dedupe on X-Webhook-Event-Id.
  4. 4Identity StudioRetry what failed5xx, 408 and 429 retried with backoff, up to 5 attempts; redirects never followed.
Capabilities

The controls on every credential

ControlHow it worksStatus
Credential typesBackend, browser and service keys, plus OAuth machine clients. Key format {app_key}.<random>; only the hash is stored.Live
Scopesauth, sso, user, org, rbac, billing, metering, notify, governance and more. Unknown scopes are refused. Machine clients carry up to 50 scopes your API defines.Live
EnvironmentsDevelopment, staging and production are separate applications with separate keys, JWKS and issuer, so a test key cannot reach production.Live
Browser keys bound to domainsallowed_domains checked against the Origin (exact host or *.domain), plus an optional IP range allow-list per key.Live
Rotation and revocationRotate with 0 to 7 days of overlap; constant-time comparison; the last public key cannot be revoked by mistake.Live
Rate limitsPer-address limits on every sign-in door, plan windows per customer (429 with Retry-After), and 60 a minute per machine client.Live
Per-key budgetsSign-in budgets per SDK credential (600 a minute), counted today and enforced on request.Early access
Signed webhooksHMAC-SHA256 over the timestamp and body; 10 identity events plus notification triggers.Live
Durable event outboxIdentity events written in the same transaction as the change and swept until delivered.Early access
CORSAllowed origins come from your keys' domains. Narrowing each app path to its own domains is in early access.Live
Security headersHSTS for two years, nosniff, frame and referrer policy, permissions policy on the web tier; a full nonce CSP on hosted pages is in early access.Live
AuditEvery key created, rotated, revoked or restricted is a critical audit row, written in the same commit or not at all.Live
Configuration

What you set per credential and webhook

OptionValuesDefault
credential_typebe_sdk, fe_sdk, servicerequired
scopesFrom the SDK scope listby type
allowed_domains · allowed_ip_cidrsHosts and address rangesno limit
expires_in_daysDays until the key stops workingnever
Rotation overlap0 to 604,800 seconds0
Webhook eventsEvent names, or allall
Webhook retriesmax_attempts up to 5 · timeout up to 10 s · backoff up to 30 s3 · 5 s · 30 s
Under the hood

What protects it

From the code
services/webhook_delivery.pyhow deliveries are signed
def sign(secret: str, timestamp: int, body: bytes) -> str:
    """`hmac_sha256(secret, "<timestamp>.<body>")`, hex."""
    mac = hmac.new(
        secret.encode("utf-8"),
        f"{timestamp}.".encode("utf-8") + body,
        hashlib.sha256,
    )
    return mac.hexdigest()

def signature_header(secret, timestamp, body) -> str:
    return f"t={timestamp},v1={sign(secret, timestamp, body)}"
Security notes
  • Webhook secrets are stored as a hash plus an encrypted envelope, and returned only once.
  • Echoed secrets are redacted in every form: escaped, URL-encoded, base64 and hex.
  • Shared rate limits fail open if their store is unreachable, so an outage never locks people out.
  • Key hashes are never written to logs or the audit trail.
Works with

Part of one platform

AI agents & MCP Agents call APIs without holding keys.OAuth & OpenID Connect Machine clients and scopes.SDKs Packages that use these keys.Audit & SIEM export Every key event on record.
Which plans include it, and the limits that apply, are on the plans page.See plans →

Lock down your API surface

Create scoped keys per environment and subscribe to signed identity events.

Book a demoStart free trial