Kevo Docs

API Reference

Complete reference for the Kevo REST API. Base URL: https://api.kevo.ws

Most wallet endpoints require a Bearer token in the Authorization header. The token is the accessToken from a KevoSession. Public auth endpoints use a project identifier or publishable key instead.

Authentication

http
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Health

GET/health

Returns server health status. No auth required.

json
{ "status": "ok", "ts": 1743588000000 }

Email Auth

GET/v1/auth/meBearer

Returns the current authenticated user, profile metadata, auth methods, and linked email.

json
{
  "user": {
    "id": "uuid",
    "did": "did:kevo:...",
    "email": "[email protected]",
    "profile": {
      "name": "Jane Doe",
      "username": "jane",
      "avatarUrl": "https://..."
    },
    "authMethods": [{ "type": "google", "identifier": "..." }],
    "createdAt": "2026-04-02T12:00:00.000Z"
  }
}
POST/v1/auth/send-otp

Sends a 6-digit OTP to the given email address.

http
POST /v1/auth/send-otp
Content-Type: application/json

{
  "email": "[email protected]",
  "projectId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "publishableKey": "pk_live_..."
}

# Response: 204 No Content
POST/v1/auth/verify-otp

Verifies the OTP and issues a session.

http
POST /v1/auth/verify-otp
Content-Type: application/json

{
  "email": "[email protected]",
  "code": "123456",
  "projectId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "publishableKey": "pk_live_..."
}

# Response:
{
  "accessToken": "eyJ...",
  "expiresIn": 900
}
# Set-Cookie: kevo_refresh_token=...; HttpOnly; Secure; SameSite=Strict
POST/v1/auth/link-email/requestBearer

Sends an OTP to link an email to the already authenticated user.

POST/v1/auth/link-email/confirmBearer

Verifies the OTP and links the email to the current user account.

http
POST /v1/auth/link-email/request
Authorization: Bearer <token>
Content-Type: application/json

{ "email": "[email protected]" }

---

POST /v1/auth/link-email/confirm
Authorization: Bearer <token>
Content-Type: application/json

{ "email": "[email protected]", "code": "123456" }

# Response:
{ "ok": true }

OAuth (Social)

GET/v1/auth/google

Redirects to Google OAuth consent screen.

GET/v1/auth/google/callback

Google OAuth callback.

GET/v1/auth/x

Redirects to X OAuth.

GET/v1/auth/x/callback

X OAuth callback.

GET/v1/auth/apple

Redirects to Apple Sign In.

GET/v1/auth/apple/callback

Apple Sign In callback.

OAuth flows are normally initiated by the SDK popup. You typically do not call these endpoints directly.

Google profile data can include email, name, and picture. X profile data can include name, username, and profile image, but not email. Apple can include email and name, usually during the first consent. Use the link-email endpoints when an authenticated user needs an email for export OTP.

Wallet Auth

GET/v1/auth/wallet/nonce

Returns a sign-in challenge message for an EVM address.

POST/v1/auth/wallet/verify

Verifies an EVM signature and issues a session.

GET/v1/auth/sol-wallet/nonce

Returns a sign-in challenge message for a Solana address.

POST/v1/auth/sol-wallet/verify

Verifies a Solana signature and issues a session.

Session

POST/v1/auth/refresh

Issues a new access token using the refresh token cookie.

POST/v1/auth/logoutCookie

Invalidates the refresh token and clears the cookie.

Embedded EVM Wallet

GET/v1/wallets/meBearer

Returns the current user's EVM wallet, or null if none exists.

json
{
  "wallet": {
    "id": "uuid",
    "address": "0xChecksummedAddress",
    "createdAt": "2026-04-02T12:00:00.000Z"
  }
}
POST/v1/wallets/me/ensureBearer

Creates the current user's EVM wallet if needed, then returns it.

POST/v1/wallets/me/signBearer

Signs an EVM payload such as a message, typed data, transaction, or userOp.

http
POST /v1/wallets/me/sign
Authorization: Bearer <token>
Content-Type: application/json

{
  "kind": "message",
  "message": "Hello from Kevo!"
}

# Response:
{ "signature": "0x..." }

Embedded Solana Wallet

GET/v1/wallets/me/solanaBearer

Returns the current user's Solana wallet, or null if none exists.

POST/v1/wallets/me/solana/ensureBearer

Creates the current user's Solana wallet if needed, then returns it.

POST/v1/wallets/me/solana/signBearer

Signs a Solana message or transaction payload.

Export

POST/v1/wallets/me/export/requestBearer

Sends an OTP to start private key export.

POST/v1/wallets/me/export/confirmBearer

Confirms export of the EVM private key after OTP verification.

POST/v1/wallets/me/export/solana/confirmBearer

Confirms export of the Solana private key after OTP verification.

Export OTP requires a verified email auth method on the user. Social providers that do not return email, especially X, should prompt the user to link an email first.

Delegation

GET/v1/wallets/me/delegationBearer

Returns the active delegation for the current user, or null.

POST/v1/wallets/me/delegation/grantBearer

Grants or replaces a delegation for backend-controlled signing.

DELETE/v1/wallets/me/delegation/revokeBearer

Revokes the current user's active delegation.

Gas Sponsorship

POST/v1/wallets/me/sponsor-tx/quoteBearer

Builds and returns the UserOperation quote for an ERC-4337 sponsored send.

POST/v1/wallets/me/sponsor-tx/submitBearer

Submits the signed sponsored send and returns the outer transaction hash.

Onramp & Transaction Reporting

POST/v1/wallets/me/onramp/sessionBearer

Creates an onramp session for the current user.

GET/v1/wallets/me/onramp/sessions/:idBearer

Returns a single onramp session.

GET/v1/wallets/me/onramp/sessionsBearer

Lists onramp sessions for the current user.

POST/v1/wallets/me/transactionBearer

Reports a wallet transaction back to Kevo for tracking and webhooks.

Error Model

ts
401 Unauthorized          // missing or invalid access token
403 Forbidden             // feature disabled or policy violation
404 Not Found             // wallet, user, or delegation not found
409 Conflict              // duplicate or invalid state transition
422 Unprocessable Entity  // malformed request payload
429 Too Many Requests     // auth/export/rate limit exceeded
502 / 504                 // internal signer or upstream RPC unavailable