sten.wtf logo
STEN.WTF
Reference: API_Console
API Reference

Two APIs, one gateway.

The AutoSecure Engine streams securing operations over WebSocket. The Accounts Toolkit manages your own stock over REST. Same key, same gateway — pick the surface that fits the job.

AutoSecure Engine · WebSocket

Drive the securing engine, live.

Open one socket and operate the real thing: pull proofs, fire an OTP, poll an authenticator prompt, hand over an MSA token, and watch each secure land through streamed log and event_response frames as it happens. This is the same engine the dashboard runs on — event in, acknowledgement out, progress on the wire. One connection per user; authenticate first, then command it.

Socket wss://sten.wtf/api/

Requires API access (redeem a code in Settings → API Keys). Generate keys with WebSocket API Access enabled.

WebSocket API Tester

API Key: You need an API key with "WebSocket API Access" enabled. Generate one in Settings → API Keys with the WebSocket option checked.
○ Disconnected

Connection & Authentication

Connect to the WebSocket API and authenticate with your API key:

json
const ws = new WebSocket('wss://sten.wtf/api/');

ws.onopen = () => {
    // Step 1: Authenticate
    ws.send(JSON.stringify({
        type: 'auth',
        data: { api_key: 'sk_your_api_key_here' }
    }));
};

ws.onmessage = (event) => {
    const message = JSON.parse(event.data);

    // Handle different message types
    switch (message.type) {
        case 'event_response':
            if (message.event === 'auth') {
                console.log('✓ Authenticated:', message.success);
            } else {
                console.log('Final result:', message);
            }
            break;

        case 'acknowledgement':
            console.log('✓ Request queued, UID:', message.uid);
            break;

        case 'log':
            console.log('Progress:', message.message);
            break;
    }
};

Complete Example

Full example showing all message types in order:

json
// 1. Send secure request
ws.send(JSON.stringify({
    type: 'event',
    event: 'recoverycode',
    id: 'req_001',
    data: {
        email: 'user@outlook.com',
        recovery_code: 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
    }
}));

// 2. Receive acknowledgement (immediate)
// { type: 'acknowledgement', uid: 'abc123', ... }

// 3. Receive log messages (during processing)
// { type: 'log', message: 'Logging in...', ... }
// { type: 'log', message: 'Changing password...', ... }
// { type: 'log', message: 'Adding 2FA...', ... }

// 4. Receive final result (after ~30-60 seconds)
// { type: 'event_response', success: true, ... }

Security & Limits

  • 1 connection per user - Only one active WebSocket connection allowed per user account
  • Rate limiting - 30 requests per 60 seconds. Exceeding triggers a 5-minute block
  • Account isolation - Users can only access their own accounts via getaccounts

Events

Available operations. All events return results via WebSocket response.

EventDescription
SECURE OPERATIONS
otpSecure account with email OTP code
seckeySecure account with TOTP secret key
recoverycodeSecure account with recovery code
msaauthSecure account with MSA auth token
OTP FLOW (Get proofs before securing)
getproofsGet authentication proofs for an email
sendotpSend OTP to a specific proof
authappPoll authenticator app for approval (returns MSAAUTH)
DATA & UTILITIES
getaccountsGet your secured accounts
statusGet status of a secure operation by UID
mailFetch emails for an address
lunarGet Lunar Client cosmetics

Use type: "status" (not event) to check connection status and rate limits.

Event: getaccounts

Get your secured accounts. No user_id needed - automatically returns your accounts.

json
{
    "type": "event",
    "event": "getaccounts",
    "id": "req_001",
    "data": {
        "filters": {                    // Optional filters
            "tags": ["Premium"],        // Only accounts with these tags
            "exclude_tags": ["SOLD"],   // Exclude accounts with these tags
            "limit": 50                 // Max results to return
        }
    }
}

Event: getproofs

Get available authentication proofs for an email. Use this before sending OTP or polling auth app.

json
{
    "type": "event",
    "event": "getproofs",
    "id": "req_gp1",
    "data": {
        "email": "user@outlook.com"  // Required
    }
}

// Response - OTP proofs available:
{
    "type": "event_response",
    "event": "getproofs",
    "success": true,
    "auth_app": false,
    "proofs": [
        {"id": "j***@outlook.com", "display": "j***@outlook.com", "type": "email"},
        {"id": "+1*****1234", "display": "+1*****1234", "type": "phone"}
    ]
}

// Response - Auth app required:
{
    "type": "event_response",
    "event": "getproofs",
    "success": true,
    "auth_app": true,
    "session_id": "abc123...",
    "entropy": "42"  // Display this number to user for approval
}

Event: sendotp

Send OTP to a specific proof obtained from getproofs.

json
{
    "type": "event",
    "event": "sendotp",
    "id": "req_so1",
    "data": {
        "email": "user@outlook.com",    // Required
        "proof_id": "j***@outlook.com"  // Required: proof ID from getproofs
    }
}

// Response:
{
    "type": "event_response",
    "event": "sendotp",
    "success": true,
    "message": "Code sent"
}

Event: authapp

Poll for authenticator app approval. Display the entropy number to the user - they must select this number in their authenticator app.

json
{
    "type": "event",
    "event": "authapp",
    "id": "req_aa1",
    "data": {
        "email": "user@outlook.com",
        "session_id": "session_from_getproofs",  // Required
        "timeout": 120  // Optional: seconds to wait (default 120)
    }
}

// Response - Success (returns MSAAUTH token):
{
    "type": "event_response",
    "event": "authapp",
    "success": true,
    "msaauth": "EwAIA..."  // Use with msaauth event to secure
}

// Response - Timeout:
{ "success": false, "error": "expired" }

// Response - Wrong number:
{ "success": false, "error": "rejected" }

Event: otp

Secure an account using an email OTP code. Typical completion: 30-60 seconds.

json
{
    "type": "event",
    "event": "otp",
    "id": "req_002",
    "data": {
        // === REQUIRED ===
        "email": "user@example.com",    // Account email
        "otp": "123456",                // 6-digit OTP code from email

        // === OPTIONAL SETTINGS (see reference table below) ===
        "domain": "yourdomain.com",     // Custom domain for aliases
        "tfa": true,                    // Enable 2FA (default)
        "sign_out": true,               // Sign out sessions (default)
        "devices": true,                // Remove devices (default)
        "oauths": true,                 // Remove OAuth apps (default)
        "family": true,                 // Leave family (default)

        // Profile changes (all default to false)
        "change_ign": false,            // Change Minecraft name
        "change_name": false,           // Change MS account name
        "change_pfp": false,            // Change profile picture
        "pfp_url": "https://...",       // Custom pfp (requires change_pfp)
        "first_name": "John",           // New first name (requires change_name)
        "last_name": "Doe"              // New last name (requires change_name)
    }
}

Event: seckey

Secure an account using a TOTP secret key (authenticator app). Typical completion: 30-60 seconds.

json
{
    "type": "event",
    "event": "seckey",
    "id": "req_003",
    "data": {
        // === REQUIRED ===
        "email": "user@example.com",       // Account email
        "password": "currentpass",         // Current password
        "secret_key": "JBSWY3DPEHPK3PXP", // TOTP secret (base32)

        // === OPTIONAL (same as otp event, see reference table) ===
        "domain": "yourdomain.com",
        "tfa": true,        // default
        "sign_out": true,   // default
        "devices": true,    // default
        "oauths": true,     // default
        "family": true      // default
    }
}

Event: recoverycode

Secure an account using a recovery code. Typical completion: 30-60 seconds.

json
{
    "type": "event",
    "event": "recoverycode",
    "id": "req_004",
    "data": {
        // === REQUIRED ===
        "email": "user@example.com",
        "recovery_code": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX",

        // === OPTIONAL (same as otp event, see reference table) ===
        "domain": "yourdomain.com",
        "tfa": true,        // default
        "sign_out": true,   // default
        "devices": true,    // default
        "oauths": true,     // default
        "family": true      // default
    }
}

Event: msaauth

Secure an account using an MSA auth token (from browser session). Typical completion: 20-40 seconds.

json
{
    "type": "event",
    "event": "msaauth",
    "id": "req_005",
    "data": {
        // === REQUIRED ===
        "msaauth": "11-M.C505_BAY.0.U...",  // MSA auth token from browser

        // === OPTIONAL (same as otp event, see reference table) ===
        "domain": "yourdomain.com",
        "tfa": true,        // default
        "sign_out": true,   // default
        "devices": true,    // default
        "oauths": true,     // default
        "family": true      // default
    }
}

Event: status (Operation Status)

Get the status of a secure operation by UID. Can optionally validate the account.

json
{
    "type": "event",
    "event": "status",
    "id": "req_010",
    "data": {
        "uid": "abc123xyz",      // Required: UID from a secure operation
        "validate": false        // Optional: Re-validate the account
    }
}

Event: mail

Fetch emails from the mail service for a given address.

json
{
    "type": "event",
    "event": "mail",
    "id": "req_011",
    "data": {
        "email": "user@yourdomain.com"  // Required
    }
}

Event: lunar

Get Lunar Client cosmetics for an account using its access token.

json
{
    "type": "event",
    "event": "lunar",
    "id": "req_012",
    "data": {
        "accessToken": "eyJhbGciOiJIUzI1NiIs..."  // Required: MC access token
    }
}

Connection Status (not an event)

Check your connection status and rate limit info. Use type: "status" directly.

json
{
    "type": "status",
    "id": "req_013"
}

// Response:
{
    "type": "event_response",
    "event": "status",
    "id": "req_013",
    "success": true,
    "message": "Connection authenticated",
    "authenticated": true,
    "api_key": "sk_abc123...",
    "user_id": "12345",
    "is_admin": false,
    "allowed_events": ["otp", "seckey", "..."],
    "connected_at": 1705612800.123,
    "rate_limit": {
        "requests_in_window": 5,
        "max_requests": 30,
        "window_seconds": 60,
        "is_blocked": false
    }
}

Optional Settings Reference

These optional settings can be included in otp, seckey, recoverycode, and msaauth events:

ParameterTypeDefaultDescription
CORE SETTINGS
domainstringnullDomain for email aliases (e.g., "example.com"). Uses system default if not provided.
tfabooltrueEnable 2FA (TOTP authenticator). Generates new secret key.
sign_outbooltrueSign out all other active sessions
PROFILE MODIFICATIONS
change_ignboolfalseChange Minecraft in-game name (random 3-16 char name)
change_nameboolfalseChange Microsoft account name (requires first_name/last_name)
change_pfpboolfalseChange profile picture (uses pfp_url or random if not provided)
pfp_urlstringnullCustom profile picture URL (requires change_pfp: true)
first_namestringnullNew first name (requires change_name: true)
last_namestringnullNew last name (requires change_name: true)
CLEANUP & SECURITY
devicesbooltrueRemove all linked devices and trusted locations
oauthsbooltrueRemove OAuth app connections (Discord, Steam, etc.)
familybooltrueLeave Microsoft family group if member

Response Flow

All secure operations follow a two-step response pattern:

Step 1: Acknowledgement (Immediate)

Sent immediately when your request is received and queued for processing:

json
{
    "type": "acknowledgement",
    "event": "otp",
    "id": "req_002",
    "success": true,
    "message": "Request received",
    "uid": "abc123xyz"
}

Step 2: Final Result (After Processing)

Sent when the operation completes (successful or failed):

json
// Success Response
{
  "type": "event_response",
  "event": "otp",
  "success": true,
  "uid": "abc123xyz",
  "status": "Secured Successfully",
  "old_name": "PlayerName",
  "new_name": "PlayerName",
  "old_email": "player@gmail.com",
  "email": "player.a1b2c3d4@yourdomain.com",
  "recoveryCode": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX",
  "tfa": "xxxx xxxx xxxx xxxx",
  "password": "xXxGeneratedPass123",
  "time_taken": 45,
  "capes": "Migrator, Cherry Blossom",
  "stats": {
    "username": "PlayerName",
    "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "Rank": "MVP+",
    "NW": 50000000,
    "LVL": 250,
    "hypixel": { "rank": "MVP+", "networkLevel": 250, "bedwars": {...}, "skyblock": {...} },
    "totalAccountValue": 125.50
  },
  "ogi": {
    "first_name": "John",
    "last_name": "Doe",
    "cards": [],
    "devices": "Removed",
    "sign_out": "Signed out",
    "xbox_gamertag": "PlayerName"
  },
  "lunar": { "cosmetics": { "cosmeticamount": 25 } }
}

Log Messages (During Processing)

While processing, you'll receive log messages showing progress:

json
{
    "type": "log",
    "event": "otp",
    "id": "req_002",
    "uid": "abc123xyz",
    "message": "Logging into Microsoft account...",
    "timestamp": 1705612800.123
}

Error Responses

If an operation fails, you'll receive an error response with details:

json
// Validation Error (Immediate)
{
    "type": "event_response",
    "event": "otp",
    "id": "req_002",
    "success": false,
    "message": "Missing required field: email",
    "error": "invalid_request"
}

// Authentication Error (After Processing)
{
    "type": "event_response",
    "event": "recoverycode",
    "id": "req_004",
    "success": false,
    "message": "Invalid recovery code",
    "error": "1300",
    "uid": "abc123xyz",
    "status": "failed_recovery_1300"
}

Rate Limit Error

json
{
    "type": "event_response",
    "event": "otp",
    "id": "req_002",
    "success": false,
    "message": "Rate limit exceeded. Try again in 300 seconds.",
    "error": "rate_limit_exceeded",
    "retry_after": 300
}

WebSocket Error Codes

Comprehensive list of all error codes you may encounter:

Error CodeDescription
AUTHENTICATION & AUTHORIZATION
missing_api_keyNo API key provided in auth message
invalid_api_keyAPI key is invalid, expired, or deactivated
not_authenticatedRequest made before authentication completed
permission_deniedAPI key lacks WebSocket access permission
rate_limit_exceededToo many requests (30/60s limit). Retry after cooldown.
VALIDATION ERRORS
invalid_requestMissing required field (email, password, otp, recovery_code, etc.)
parse_errorInvalid JSON in WebSocket message
unknown_eventEvent type not recognized
unknown_typeMessage type not recognized (use 'event', 'auth', or 'status')
SECURE OPERATION ERRORS
invalid_otpOTP code is incorrect or expired
invalid_recovery_codeRecovery code is incorrect or already used
invalid_credentialsEmail or password is incorrect
1300Microsoft error: Invalid recovery code
6001Microsoft error: Account requires additional verification
failed_loginFailed to login to Microsoft account
account_lockedMicrosoft account is locked/suspended
tfa_requiredAccount has 2FA enabled, cannot proceed with this method
secure_failedSecure operation failed (check logs for details)
SYSTEM ERRORS
handler_errorInternal server error in event handler
connection_errorWebSocket connection error
internal_errorUnexpected internal server error

Pro Tip: Always check the error field in responses for programmatic error handling. The message field provides human-readable details. For secure operations, an acknowledgementmessage is sent immediately with the UID, followed by the final event_response when complete.

These RPC methods are called over the same WebSocket connection using type: "rpc" instead of type: "event". Bot methods are scoped to bots owned by the authenticated API key owner.

RPC: api.bots.indexes

Get the database indexes for your bots. Call this first if you do not know what to pass as bot_id. Returns only bots owned by the authenticated API key owner. Optionally filter by Discord bot/application ID.

For bot API methods, bot_id accepts either the database index returned here, such as 42, or the Discord bot/application ID returned as bot_id, such as 123456789012345678. Do not pass a Discord server/guild ID.

json
// Request
{
    "type": "rpc",
    "method": "api.bots.indexes",
    "id": "req_idx1",
    "params": {}
}

// Response
{
    "type": "rpc_response",
    "method": "api.bots.indexes",
    "id": "req_idx1",
    "result": {
        "success": true,
        "bots": [
            {
                "index": 42,
                "bot_id": "123456789012345678",
                "bot_name": "My Bot",
                "status": "running"
            }
        ]
    }
}
json
// Optional: filter by Discord bot/application ID
{
    "type": "rpc",
    "method": "api.bots.indexes",
    "id": "req_idx_filter1",
    "params": {
        "bot_id": "123456789012345678"
    }
}

RPC: api.codes.generate

Generate a share link/code for one of your bots. Non-admin users need API access, an active subscription, and Links access. Accepts either a Discord bot ID or a database index from api.bots.indexes.

json
// Request
{
    "type": "rpc",
    "method": "api.codes.generate",
    "id": "req_gen1",
    "params": {
        "bot_id": "123456789012345678",  // Discord bot ID or database index
        "type": "hypixel",               // hypixel | badlion | feather | lunar | donut
        "cosmetic": "Cool Cape",         // Optional: cosmetic/product name for slug
        "price": 5.00,                   // Optional: price in USD (default 0)
        "link": "https://i.imgur.com/example.png",  // Optional: preview image URL
        "expires_in_hours": 2            // Optional: 1, 2, or 4 (default 1)
    }
}

// Response
{
    "type": "rpc_response",
    "method": "api.codes.generate",
    "id": "req_gen1",
    "result": {
        "success": true,
        "code": {
            "id": 123,
            "slug": "cool-cape-ab1c2d",
            "url": "https://sten.wtf/links/cool-cape-ab1c2d",
            "type": "hypixel",
            "cosmetic": "Cool Cape",
            "price": 5.00,
            "expires_at": "2025-01-15T02:00:00Z",
            "bot_id": "123456789012345678",
            "bot_name": "My Bot"
        }
    }
}

RPC: api.logs.send

Send a named verification log through an owned running bot. The bot's configured logging mode, filtered/unfiltered channels, masking, render mode, stat buttons, and custom/default embed templates are used automatically.

json
// Request
{
    "type": "rpc",
    "method": "api.logs.send",
    "id": "req_log1",
    "params": {
        "bot_id": 42,
        "mode": "otp",                  // username | email | otp | auth | securing
        "username": "Steve",
        "uuid": "069a79f444e94726a5befca90e38aaf5",
        "email": "steve@example.com",
        "otp": "123456"
    }
}

// Response
{
    "type": "rpc_response",
    "id": "req_log1",
    "result": {
        "success": true,
        "sent": 2,
        "skipped": [],
        "errors": []
    }
}

RPC: api.hits.send

Send a secure-result hit through an owned bot's hits channel. The bot's secure embed template is the visual source of truth.

json
// Request
{
    "type": "rpc",
    "method": "api.hits.send",
    "id": "req_hit1",
    "params": {
        "bot_id": 42,
        "uid": "abc123",
        "result": {
            "uid": "abc123",
            "old_name": "Steve",
            "email": "steve@example.com",
            "security_email": "safe@example.com",
            "password": "generated-password",
            "recoveryCode": "AAAAA-BBBBB",
            "time_taken": 8.2
        }
    }
}

RPC: api.verification.start

Compatibility flow: create an API-owned verification session for one bot and emit the initial username/email log modes. New integrations should prefer api.verification.session.create plus autosecure.* because that flow also performs proof lookup and OTP/auth-app logging.

json
{
    "type": "rpc",
    "method": "api.verification.start",
    "id": "req_start1",
    "params": {
        "bot_id": 42,
        "username": "Steve",
        "email": "steve@example.com",
        "uuid": "069a79f444e94726a5befca90e38aaf5"
    }
}

// Response includes session_id for submitOtp / submitAuth
{
    "type": "rpc_response",
    "id": "req_start1",
    "result": {
        "success": true,
        "session_id": "sess1234",
        "logs": [{ "mode": "username", "success": true, "sent": 1 }]
    }
}

RPC: api.verification.submitOtp

Compatibility flow: submit an OTP for an API-owned verification session created by api.verification.start. Requires session_id and otp; email and noPassword/no_password are read from the session unless you override them.

json
{
    "type": "rpc",
    "method": "api.verification.submitOtp",
    "id": "req_otp1",
    "params": {
        "session_id": "sess1234",
        "otp": "123456",
        "noPassword": false
    }
}

RPC: api.verification.submitAuth

Compatibility flow: submit a Microsoft auth token for an API-owned verification session created by api.verification.start. Requires session_id and msauth; email is read from the session unless you override it.

json
{
    "type": "rpc",
    "method": "api.verification.submitAuth",
    "id": "req_auth1",
    "params": {
        "session_id": "sess1234",
        "msauth": "MSA_AUTH_TOKEN"
    }
}

RPC: api.verification.session.create

Recommended: Create an API-attached verification session tied to your bot. This creates server-side context for the owning API user, bot database index, optional username/UUID/email metadata, and the stable proxy assignment used by the rest of the flow. It does not check or secure the account by itself.

Pass the returned session_id into autosecure.getProofs, autosecure.sendOtp, autosecure.authApp, and the final secure.* call. When present, the API resolves the bot from the session, enforces session ownership, fills missing username/UUID/email values from session metadata, and sends notifications using that bot's configured embeds and channels.

Session duration: verification sessions are short-lived and are cleaned after 1 hour. A successful secure deletes the session after the hit embed is sent. Failed sessions are marked failed for inspection, but old sessions are still removed by the 1-hour cleanup. If a session expires, create a new session and restart the flow.

How To Create The Session

Send this RPC after authenticating the WebSocket with your API key. bot_id is required and must identify one of your bots. Use either the database index from api.bots.indexes or that bot's Discord application ID from bot_id. username, email, uuid, and noPassword/no_password are optional metadata, but passing them up front lets later logs and secure calls reuse them automatically.

json
{
    "type": "rpc",
    "method": "api.verification.session.create",
    "id": "req_sess1",
    "params": {
        "bot_id": 42,
        "username": "Steve",
        "email": "steve@example.com",
        "uuid": "069a79f444e94726a5befca90e38aaf5",
        "noPassword": false
    }
}

{
    "type": "rpc_response",
    "id": "req_sess1",
    "result": {
        "success": true,
        "session_id": "sess_abc123",
        "bot_index": 42,
        "bot_id": "123456789012345678"
    }
}

Save result.session_id. That value is the verification session ID you pass to autosecure.getProofs, autosecure.sendOtp, autosecure.authApp, and secure.*.

You can also create the session with only bot_id and set metadata later. Any later session-attached call that includes username/ign, uuid/mcUuid, email, noPassword/no_password, ip, customValues, custom_values, metadata, or attributes writes those values back to the session so following logs and secure calls can reuse them.

json
// Create an empty session first
{
    "type": "rpc",
    "method": "api.verification.session.create",
    "id": "req_sess_empty",
    "params": {
        "bot_id": 42
    }
}

// Later, set email while checking proofs
{
    "type": "rpc",
    "method": "autosecure.getProofs",
    "id": "req_gp1",
    "params": {
        "session_id": "sess_abc123",
        "email": "steve@example.com"
    }
}

// Once email is stored, getProofs can use just session_id
{
    "type": "rpc",
    "method": "autosecure.getProofs",
    "id": "req_gp2",
    "params": {
        "session_id": "sess_abc123"
    }
}

// getProofs stores noPassword/no_password on the verification session.
// sendOtp uses stored email/noPassword, or auto-detects noPassword if absent.
// proof_id is always required.
// Use the id field from the selected getProofs proof.
{
    "type": "rpc",
    "method": "autosecure.sendOtp",
    "id": "req_so1",
    "params": {
        "session_id": "sess_abc123",
        "proof_id": "j***@outlook.com"
    }
}

// Later, set or update username/UUID on OTP or secure calls
{
    "type": "rpc",
    "method": "secure.otp",
    "id": "req_sec1",
    "params": {
        "session_id": "sess_abc123",
        "username": "Steve",
        "uuid": "069a79f444e94726a5befca90e38aaf5",
        "otp": "123456"
    }
}

// Secure calls also use stored email and noPassword. This only needs session_id + msauth.
{
    "type": "rpc",
    "method": "secure.msauth",
    "id": "req_sec_auth1",
    "params": {
        "session_id": "sess_abc123",
        "msauth": "EwAIA..."
    }
}

// Frontend metadata can be stored on the session and used in embeds.
{
    "type": "rpc",
    "method": "api.verification.session.create",
    "id": "req_sess_ip",
    "params": {
        "bot_id": 42,
        "ip": "203.0.113.9",
        "customValues": {
            "campaign": "spring"
        }
    }
}

Frontend metadata does not require a Discord ID. It is exposed to log and hit embed templates as placeholders such as %IP%, %CUSTOM_IP%, %CAMPAIGN%, and %CUSTOM_CAMPAIGN%.

json
// Initialize from a bot you own
// 1. List bots with api.bots.indexes.
// 2. Use either result.bots[0].index or result.bots[0].bot_id below.
{
    "type": "rpc",
    "method": "api.verification.session.create",
    "id": "req_sess1",
    "params": {
        "bot_id": 42,
        "username": "Steve",
        "uuid": "069a79f444e94726a5befca90e38aaf5",
        "email": "steve@example.com"
    }
}

// Also valid:
{
    "type": "rpc",
    "method": "api.verification.session.create",
    "id": "req_sess2",
    "params": {
        "bot_id": "123456789012345678",
        "username": "Steve",
        "email": "steve@example.com"
    }
}
json
// 1. Create session
{
    "type": "rpc",
    "method": "api.verification.session.create",
    "id": "req_sess1",
    "params": {
        "bot_id": 42,
        "username": "Steve",
        "email": "steve@example.com",
        "uuid": "069a79f444e94726a5befca90e38aaf5"
    }
}

// Response
{
    "type": "rpc_response",
    "id": "req_sess1",
    "result": {
        "success": true,
        "session_id": "sess_abc123",
        "bot_index": 42,
        "bot_id": "123456789012345678"
    }
}

// 2. Get proofs (with session_id; logs go through the bot; response includes noPassword/no_password)
{
    "type": "rpc",
    "method": "autosecure.getProofs",
    "id": "req_gp1",
    "params": {
        "email": "steve@example.com",
        "session_id": "sess_abc123"
    }
}

// 3. Send OTP (with session_id; stored noPassword is reused; "Code sent" is logged)
{
    "type": "rpc",
    "method": "autosecure.sendOtp",
    "id": "req_so1",
    "params": {
        "email": "steve@example.com",
        "proof_id": "j***@outlook.com",
        "session_id": "sess_abc123"
    }
}

// 4. Secure with OTP (with session_id — securing log + hit embed)
{
    "type": "rpc",
    "method": "secure.otp",
    "id": "req_sec1",
    "params": {
        "session_id": "sess_abc123",
        "email": "steve@example.com",
        "otp": "123456"
    }
}

Session-Attached Lifecycle

StepRPC methodSession fieldEffect
Create contextapi.verification.session.createnoneReturns session_id
Check proofsautosecure.getProofssession_id + email unless storedChecks email, stores noPassword/no_password, and sends email/auth-required logs
Send OTPautosecure.sendOtpsession_id + proof_idSends code with stored no-password state and OTP log
Poll auth appautosecure.authAppsession_id + flow_session_idSends auth pending/result logs
Securesecure.otp or secure.msauthsession_id + otp/msauthReuses stored no-password state, then sends securing log and hit embed on success

Authenticator app accounts have two IDs: autosecure.getProofs returns the Microsoft flow token in its own session_id field, while api.verification.session.create returns the API verification session. In the new flow, pass the Microsoft token as flow_session_id and keep the API verification ID as session_id.

json
// Authenticator app variant
// getProofs returned: { "auth_app": true, "session_id": "flow_123", "entropy": "42" }
{
    "type": "rpc",
    "method": "autosecure.authApp",
    "id": "req_auth_poll1",
    "params": {
        "email": "steve@example.com",
        "flow_session_id": "flow_123",
        "session_id": "sess_abc123",
        "timeout": 120
    }
}

{
    "type": "rpc",
    "method": "secure.msauth",
    "id": "req_sec_auth1",
    "params": {
        "session_id": "sess_abc123",
        "email": "steve@example.com",
        "msauth": "EwAIA..."
    }
}

Automatic Bot Log Events

These are emitted only when a valid session-attached session_id is supplied. Each log uses the session bot's configured log templates, masking rules, filtered/unfiltered channels, and render mode. The final hit uses the bot's secure hit template.

TriggerBot eventStatus/stageNotes
autosecure.getProofs startsemail logChecking email / email_checkingStarts email/proof lookup
Email check failsemail logerror / email_failedInvalid email, timeout, connection, or not found
Authenticator requiredauth logAuth app required / auth_requiredResponse includes entropy and flow token
Proofs foundemail logFound N proofs / email_checkedUse a returned proof ID with sendOtp
autosecure.sendOtp succeedsotp logCode sent / otp_sentIncludes proof type/display
autosecure.authAppauth logPending, Approved, Expired, Rejected, or FailedTracks authenticator outcome
secure.otp / secure.msauthotp or auth log, then securing logotp_submitted, auth_approved, securingRuns final account securing
Secure succeedshit embedcompleted / hit_sentSession is deleted after hit delivery
Secure failsinvalid_otp for invalid OTP, otherwise email logfailed / secure_failedSession remains marked failed for inspection

Session-Attached vs Direct Mode

FeatureSession-Attached (Recommended)Direct / Compatibility
Bot embedsUses the session bot's configured embeds automaticallyapi.logs.send / api.hits.send must be called manually
Log channelsSends to bot's filtered/unfiltered channelsManual log channel selection
OwnershipEnforced on every action via session_idVerified per-request via bot_id
Session cleanupDeleted after a successful hit; failures remain marked failed until cleanupNo persistent session
Flow stepssession.create → getProofs → sendOtp → secure.*verification.start → submitOtp/submitAuth

RPC Error Codes

Error CodeDescription
UNAUTHORIZEDNot authenticated or missing API key
FORBIDDENAccess denied or not your bot
DISCORD_REQUIREDDiscord account must be linked
NOT_FOUNDBot not found with given ID
INVALID_PARAMSMissing or invalid parameters
CREATE_FAILEDFailed to create the link/code
BOT_OFFLINEBot is offline or not running
SEND_FAILEDFailed to send the log/hit notification
NO_LICENSEMissing required subscription/license
NOT_LICENSEDMissing Links license
NO_HIT_CHANNELNo hits channel configured for the bot
NO_LOG_CHANNELNo logs channel configured for the bot