Cavos

Dashboard

The Cavos console — organizations and roles, apps, sponsorship, API keys, webhooks, and the audit log.

Everything the SDK needs at runtime comes from one place: an app in the Cavos console. This page describes what lives there, so you know where a value in your config came from and where to look when something is rejected.

Organizations and apps

An organization owns billing, team members, API keys, and the gas balance. Inside it you create apps; each app has a development and a production environment from the moment it exists.

Org-level sections: Applications, Activity, Gas & usage, Webhooks, Team, API keys, Billing, Audit log, Settings.

Each app then has its own tabs:

TabWhat it is for
OverviewHealth, recent traffic, and the app's appId.
WalletsEvery wallet derived under this app, with its devices and transactions.
Devices & recoveryPending device-approval requests, enrolled factors, recovery state.
ActivityThe event stream (also the source of webhooks).
SponsorshipGas funding and the relay decisions made for this app.
AuthenticationProviders, OAuth client IDs, callback URLs, social-recovery config.
EmailsTemplates for magic link, OTP, device approval, and password reset.
ProgramsThe Solana program allowlist (see below).
EnvironmentsPer-environment origins, keys, and social recovery.
SettingsName, logo, and the device_approval_url the emails link to.

appSalt is not a dashboard value — it lives in your code and derives every address. Changing it moves every user to a new, empty wallet. See Troubleshooting.

Team roles

Invitations are sent by email and accepted at /dashboard/invitations/accept. Roles: owner, admin, developer, support, billing, viewer.

Two thresholds matter in practice:

  • API keys — create, rotate, revoke: owner or admin.
  • Webhook endpoints — create: owner, admin, or developer.

Reading the console (apps, wallets, activity) is open to every member of the organization.

API keys

Server-side credentials, issued per environment with read and/or write scopes. A key is shown once at creation — only its hash is stored — and can be rotated or given an expiry.

Terminal
curl https://cavos.xyz/api/v1/apps \
  -H "Authorization: Bearer cav_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"My App","organization_id":"..."}'

An API key (cav_…) is an operator credential: it acts on your organization from a server. It is not the same thing as the appId or the Starknet paymasterApiKey, both of which are app-scoped and client-visible by design. Never ship a cav_… key to a browser or a mobile bundle.

Sponsorship and gas

Gas is metered per environment, so test traffic never drains production. The Starknet gas tank is an on-chain balance read per organization; Solana and Stellar relayers are funded through the same Gas & usage section.

When the balance runs out, sponsored operations are rejected rather than silently charged to the user — relay.rejected and gas.balance_low are webhook events for exactly this reason.

Solana program allowlist

The relayer signs as fee payer, so it decides what it is willing to sponsor. A safe set is always allowed: System, SPL Token, Token-2022, and Associated Token. Anything else your wallets call through executeInstructions must be added on the app's Programs tab — the tab offers the common ones (Jupiter, Meteora, Raydium CLMM, Marinade, Stake, Memo) as presets and accepts any program id.

A call to a program that is not allowlisted is refused by the relayer at submit time, not on-chain.

Webhooks

Signed operational events, delivered to one HTTPS endpoint, scoped to a single app environment. Event types:

EventFires when
wallet.createdA wallet was derived and deployed.
wallet.creation_failedDeployment failed.
device.addition_requestedA new device asked to be authorized.
device.addition_approvedThe owner approved it.
relay.rejectedThe relayer refused to sponsor an operation.
gas.balance_lowThe environment's gas balance crossed its threshold.

Creating an endpoint returns a whsec_… signing secret once, and immediately delivers a ping event so you can confirm the route works.

Payload

POST your-endpoint
{
  "version": "2026-07-21",
  "delivery_id": "…",
  "event": {
    "id": "…",
    "type": "wallet.created",
    "status": "success",
    "severity": "info",
    "network": "solana-devnet",
    "request_id": "…",
    "tx_reference": "…",
    "created_at": "2026-08-19T12:00:00.000Z",
    "metadata": {}
  }
}

Headers: X-Cavos-Delivery (the delivery id) and X-Cavos-Signature-256 (sha256= + an HMAC-SHA256 of the raw request body with your signing secret).

Verify the signature

app/api/cavos/route.ts
import { createHmac, timingSafeEqual } from "node:crypto";

export async function POST(request: Request) {
  const raw = await request.text();               // the raw body, not the parsed JSON
  const expected =
    "sha256=" + createHmac("sha256", process.env.CAVOS_WEBHOOK_SECRET!).update(raw).digest("hex");
  const received = request.headers.get("X-Cavos-Signature-256") ?? "";

  const a = Buffer.from(expected), b = Buffer.from(received);
  if (a.length !== b.length || !timingSafeEqual(a, b)) {
    return new Response("bad signature", { status: 401 });
  }

  const { event } = JSON.parse(raw);
  // …handle event.type
  return new Response("ok");
}

Sign over the raw body. Re-serializing the parsed JSON changes the bytes and the HMAC will never match.

Delivery, retries, and disabling

Each attempt has an 8-second timeout; any non-2xx response counts as a failure. Failed deliveries retry up to 5 attempts at roughly 15s, 1min, 10min, and 1h. After 10 consecutive failures the endpoint is deactivated — recreate it once your receiver is healthy.

Deliveries are visible per endpoint in the console, with status, response code, and duration.

Audit log

Administrative actions on the organization are recorded with the actor, the resource, and the result — API key creation and rotation, team invitations and joins, webhook creation, social-recovery enroll/cancel, and reveals of a wallet's external id.

This is the org's own accountability record. It is separate from Activity, which is the runtime event stream your users generate.

On this page