autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
113
skills/apodex-batch-reg/references/apodex-otp-rate-limits.md
Normal file
113
skills/apodex-batch-reg/references/apodex-otp-rate-limits.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Apodex OTP: Rate Limits & IMAP Extraction
|
||||
|
||||
## CRITICAL: NO-OTP Registration (discovered 2026-06-26)
|
||||
|
||||
Apodex creates accounts **without OTP verification**. Simply entering a new email on the sign-in page and clicking "Continue with email" creates the account server-side — the OTP dialog that appears is a frontend artefact. The account already exists.
|
||||
|
||||
**This changes everything:**
|
||||
- No IMAP OTP extraction needed for account creation
|
||||
- No rate limit (`PASSWORDLESS_SEND_RATE_LIMITED`) — it only applies to OTP endpoint, not account creation
|
||||
- 12+ accounts in ~4 minutes: navigate → click Sign in → type email → click Continue → clear cookies → repeat
|
||||
- NO wait between accounts
|
||||
|
||||
**ONLY use OTP flow when you need to LOG IN** to an existing account (e.g., to extract API key from the dashboard).
|
||||
|
||||
## Auth Endpoint
|
||||
|
||||
```
|
||||
POST https://www.apodex.ai/api/auth/passwordless/send-code
|
||||
Content-Type: application/json
|
||||
{"email": "[REDACTED-EMAIL]"}
|
||||
```
|
||||
|
||||
Returns:
|
||||
- `200` — OTP sent (browser transitions to OTP input)
|
||||
- `429` — `{"code":"PASSWORDLESS_SEND_RATE_LIMITED","message":"Operation too frequent, please try again later"}`
|
||||
- `404` on `/api/auth/magic-link` — wrong endpoint, use `passwordless/send-code`
|
||||
|
||||
## Verify Endpoint
|
||||
|
||||
```
|
||||
POST https://www.apodex.ai/api/auth/passwordless/verify-login
|
||||
Content-Type: application/json
|
||||
{"email": "[REDACTED-EMAIL]", "code": "123456"}
|
||||
```
|
||||
|
||||
Returns:
|
||||
- `200` — `{"success":true,"data":{"access_token":"<JWT>","user":{...}}}`
|
||||
- The `access_token` is an Apodex JWT (`{user_id, session_id}`). Works for `www.apodex.ai/api/auth/*`, NOT for `api.apodex.ai/v1/api-keys` (returns 401 `invalid token`).
|
||||
- The Supabase JWT format needed for `/v1/api-keys` is `{iss, ref, role, sub}` — but the Supabase project is DEAD.
|
||||
- `400` — OTP expired or already used
|
||||
|
||||
## Rate Limit
|
||||
|
||||
- ~8-10 OTP triggers per short window before 429
|
||||
- Reset: ~5-10 minutes
|
||||
- Per-IP (not per-email)
|
||||
- **Does NOT apply to account creation via email-only signup**
|
||||
- Symptoms: email form re-renders without OTP page appearing
|
||||
|
||||
## IMAP OTP Extraction (Python One-Liner)
|
||||
|
||||
ONLY needed for key extraction from existing accounts:
|
||||
|
||||
```python
|
||||
python -c "
|
||||
import imaplib, ssl, re, email
|
||||
imap = imaplib.IMAP4_SSL('secureimap.t-online.de', 993, timeout=15)
|
||||
imap.login('[REDACTED-EMAIL]', 'PASSWORD')
|
||||
imap.select('INBOX')
|
||||
status, msgs = imap.search(None, 'FROM', 'apodex')
|
||||
msg_ids = msgs[0].split()
|
||||
status, data = imap.fetch(msg_ids[-1], '(RFC822)')
|
||||
raw = data[0][1].decode('utf-8', errors='ignore')
|
||||
msg = email.message_from_string(raw)
|
||||
if msg.is_multipart():
|
||||
for part in msg.walk():
|
||||
if part.get_content_type() == 'text/plain':
|
||||
body = part.get_payload(decode=True).decode('utf-8', errors='ignore')
|
||||
codes = re.findall(r'\b\d{6}\b', body)
|
||||
if codes: print(codes[0])
|
||||
else:
|
||||
body = msg.get_payload(decode=True).decode('utf-8', errors='ignore')
|
||||
codes = re.findall(r'\b\d{6}\b', body)
|
||||
if codes: print(codes[0])
|
||||
imap.logout()
|
||||
"
|
||||
```
|
||||
|
||||
## Registration Flow
|
||||
|
||||
### PRIMARY: NO-OTP (account creation only, ~20s per account)
|
||||
|
||||
1. `browser_navigate('https://www.apodex.ai')` — signed-out state
|
||||
2. `browser_click('Sign in')` — opens auth dialog (ref `@e9`)
|
||||
3. `browser_type(email)` + `browser_click('Continue with email')` — single type, single click
|
||||
4. Account created server-side immediately. OTP dialog is cosmetic — ignore it.
|
||||
5. `browser_console('localStorage.clear(); sessionStorage.clear();')`
|
||||
6. Repeat from step 1 — NO wait, NO rate limit
|
||||
|
||||
### FALLBACK: OTP (login for key extraction)
|
||||
|
||||
⚠️ **BLOCKED** — Supabase project is dead, so `/v1/api-keys` can't issue new keys. Only use to log into dashboard.
|
||||
|
||||
1. `browser_navigate('https://www.apodex.ai')`
|
||||
2. `browser_click('Sign in')`
|
||||
3. `browser_type(email)` + `browser_click('Continue with email')` — FIRST attempt
|
||||
4. Dialog re-renders, email cleared → `browser_type(email)` + `browser_click('Continue with email')` — SECOND attempt
|
||||
5. OTP page appears → `browser_snapshot()` to get refs
|
||||
6. Run IMAP one-liner → get 6-digit code
|
||||
7. `browser_type(otp_code)` + wait for auto-verify
|
||||
8. "Free Beta" alertdialog = SUCCESS
|
||||
9. Sign out: `browser_click(user_menu)` → `browser_click('Sign Out')`
|
||||
10. Clear storage
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **NO-OTP is PRIMARY** — DO NOT fetch OTP for account creation
|
||||
- **Rate limit 429 only applies to OTP flow** — after ~8 accounts. Ignore for NO-OTP
|
||||
- **Double-type required ONLY for OTP flow** — email input gets cleared on first dialog render
|
||||
- **Click, not Enter**: Enter closes the dialog instead of submitting
|
||||
- **Password format**: t-online.de passwords may contain `@` (e.g., `@cottage`)
|
||||
- **IMAP server**: `secureimap.t-online.de:993` (SSL), not `imap.t-online.de`
|
||||
- **access_token from verify-login = Apodex JWT**, NOT Supabase JWT. Won't work for `/v1/api-keys`.
|
||||
Reference in New Issue
Block a user