autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
# Kamatera Free Trial — Registration & Billing API
|
||||
|
||||
## Overview
|
||||
|
||||
Kamatera offers a 30-day free trial ($100 cloud credit) with payment card required. The registration and billing flow is entirely API-driven through a WordPress-based backend.
|
||||
|
||||
## Registration
|
||||
|
||||
### Endpoint (WordPress AJAX)
|
||||
```
|
||||
POST https://www.kamatera.com/wp-admin/admin-ajax.php
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
```
|
||||
|
||||
### jQuery Serialization Format
|
||||
The form uses jQuery's `$.ajax` with nested objects. Key format: `data_options[field]=value`
|
||||
|
||||
```
|
||||
action=cwm_api_action
|
||||
data_options[cases]=cwml
|
||||
data_options[email]=...@domain.com
|
||||
data_options[password]=...
|
||||
data_options[orgUrl]=https://www.kamatera.com/free-trial/
|
||||
data_options[formButtonText]=Create free account
|
||||
data_options[submitText]=Create free account
|
||||
data_options[headerText]=
|
||||
```
|
||||
|
||||
### Email Validation
|
||||
- Client-side regex: `/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/`
|
||||
- **`+` aliases NOT allowed** (Gmail `+suffix` fails `\w` check)
|
||||
- Use plain emails or disposable email domains
|
||||
|
||||
### Password Requirements
|
||||
- At least 1 lowercase
|
||||
- At least 1 uppercase
|
||||
- At least 1 number
|
||||
- At least 8 characters
|
||||
- Less than 28 characters
|
||||
|
||||
### Response
|
||||
```json
|
||||
{
|
||||
"status": 0, // 0 = success, 13 = blocked/captcha fail
|
||||
"token": "...",
|
||||
"existing": false, // true if account already exists
|
||||
"url": "https://console.kamatera.com/al.php?t=...",
|
||||
"validationToken": "...",
|
||||
"impactid": "kt-..."
|
||||
}
|
||||
```
|
||||
|
||||
Status 13 with `url: null` = blocked (likely reCAPTCHA v3 score too low, or IP flagged).
|
||||
|
||||
## Email Verification
|
||||
|
||||
Verification email comes from `support@kamatera.com` with subject "Confirm your Kamatera cloud account". Contains a link:
|
||||
```
|
||||
https://console.kamatera.com/rd.php?t=...&e=...&p=emailValidation&h=...
|
||||
```
|
||||
Click the link → redirects to `validateSuccessful?email=...` → account verified.
|
||||
|
||||
## Disposable Email
|
||||
|
||||
**mail.tm** works reliably:
|
||||
```python
|
||||
# 1. Get domain
|
||||
r = requests.get("https://api.mail.tm/domains")
|
||||
domain = r.json()["hydra:member"][0]["domain"]
|
||||
|
||||
# 2. Create account
|
||||
r = requests.post("https://api.mail.tm/accounts", json={
|
||||
"address": f"{username}@{domain}",
|
||||
"password": "password"
|
||||
})
|
||||
|
||||
# 3. Get token
|
||||
r = requests.post("https://api.mail.tm/token", json={
|
||||
"address": email, "password": "password"
|
||||
})
|
||||
token = [REDACTED])["token"]
|
||||
|
||||
# 4. Read messages
|
||||
r = requests.get("https://api.mail.tm/messages",
|
||||
headers={"Authorization": f"Bearer {token}"})
|
||||
```
|
||||
|
||||
**GuerrillaMail** works but Kamatera emails may not arrive to `.guerrillamailblock.com` — use mail.tm instead.
|
||||
|
||||
## Console API
|
||||
|
||||
### Base URL & Auth
|
||||
```
|
||||
Base: https://console.kamatera.com/svc/
|
||||
Headers:
|
||||
Content-Type: application/json
|
||||
Accept: application/json
|
||||
api-version: latest
|
||||
token: <CSRF_TOKEN>
|
||||
```
|
||||
|
||||
### CSRF Token
|
||||
Get from `/csrf` endpoint:
|
||||
```python
|
||||
r = requests.get("https://console.kamatera.com/csrf")
|
||||
csrf = re.search(r'CSRF_TOKEN",\s*"([^"]+)"', r.text).group(1)
|
||||
```
|
||||
|
||||
The `/csrf` page returns HTML that sets `sessionStorage.setItem("CSRF_TOKEN", "...")`. The token is embedded in the HTML as a script tag.
|
||||
|
||||
### Login Flow (with 2FA)
|
||||
```
|
||||
1. POST /svc/login {"email", "password"}
|
||||
→ {"email": "...", "mediateToken": "..."}
|
||||
|
||||
2. POST /svc/sendtfa {"email", "mediateToken"} (header: token=<csrf>)
|
||||
→ triggers email with 6-digit code
|
||||
|
||||
3. Check mail.tm for code in subject "Kamatera Cloud Platform: 2-Step Verification"
|
||||
|
||||
4. POST /svc/logintfa {"email", "code", "rememberBrowser": true, "mediateToken"}
|
||||
→ 200 = logged in, session cookie set
|
||||
→ 400 + code 51 = "Invalid code" (code expired or wrong)
|
||||
```
|
||||
|
||||
### TFA Code Pitfalls
|
||||
- Codes expire quickly (~2-5 minutes)
|
||||
- `sendtfa` may return 200 but NOT send a new email if one was already sent recently
|
||||
- Delete old emails from mail.tm before calling `sendtfa` to avoid picking up stale codes
|
||||
- The 2FA email body contains the code in format: `Your access code ... is: XXXXXX`
|
||||
- Filter out false positives: `1999` and `2026` are in the email footer, not the code
|
||||
|
||||
### Billing Profile API
|
||||
```
|
||||
PUT /svc/billing/profile (header: token=<csrf>)
|
||||
```
|
||||
|
||||
### Billing Profile Fields (Discovered via Progressive 400 Errors)
|
||||
The API validates fields in sequence. Each fix reveals the next missing field:
|
||||
|
||||
| Error Code | Message | Required Fix |
|
||||
|-----------|---------|-------------|
|
||||
| 122 | invalid invoice name | Add `invoiceName` |
|
||||
| 105 | invalid first name | Add `firstName` |
|
||||
| 107 | invalid country | Fix `country` format |
|
||||
| 110 | invalid city | Add `city` |
|
||||
| 112 | invalid zip code | Use `postalCode` (NOT `zipCode` or `zip`) |
|
||||
| 109 | invalid phone | Add `phone` |
|
||||
| 21 | generic error | Card rejected by payment processor |
|
||||
|
||||
### Working Billing Payload (Passes All Validation)
|
||||
```json
|
||||
{
|
||||
"firstName": "Alex",
|
||||
"lastName": "Morgan",
|
||||
"country": "US",
|
||||
"city": "New York",
|
||||
"address": "123 Broadway",
|
||||
"state": "NY",
|
||||
"postalCode": "10001",
|
||||
"phone": "2125550100",
|
||||
"invoiceName": "Alex Morgan",
|
||||
"paymentType": 0,
|
||||
"cardNumber": "4874100085748500",
|
||||
"cardExpiry": "05/2030",
|
||||
"cardCvv": "617"
|
||||
}
|
||||
```
|
||||
|
||||
### Error Code 21 (Card Rejected)
|
||||
After all field validation passes, error 21 means the payment processor rejected the card. This is NOT a field format issue. Possible causes:
|
||||
- Card blocked/stolen
|
||||
- Insufficient funds for $1 authorization hold
|
||||
- 3D Secure required but not supported
|
||||
- Region mismatch (card issuing country ≠ billing country)
|
||||
- Card expired (check BIN + expiry date format)
|
||||
|
||||
### Card Expiry Formats Tried
|
||||
- `cardExpiry: "05/2030"` — works (passes to processor)
|
||||
- `cardExpiry: "05/30"` — works (passes to processor)
|
||||
- Separate `expMonth`/`expYear` fields — also pass validation
|
||||
|
||||
All formats pass field validation — the rejection is at the payment processor level.
|
||||
|
||||
## Browser-Based API Calls
|
||||
|
||||
When the React SPA is unresponsive (clicks don't navigate), use `fetch()` from browser console with the session's CSRF token:
|
||||
|
||||
[REDACTED]
|
||||
fetch('/svc/billing/profile', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'api-version': 'latest',
|
||||
'token': sessionStorage.getItem('CSRF_TOKEN')
|
||||
},
|
||||
body: JSON.stringify({...})
|
||||
}).then(r => r.json()).then(d => console.log(JSON.stringify(d)))
|
||||
```
|
||||
|
||||
This bypasses the broken React navigation and uses the browser's authenticated session directly.
|
||||
|
||||
## Key Pitfalls
|
||||
|
||||
1. **Email `+` aliases fail client-side validation** — use plain email or disposable domain
|
||||
2. **`sendtfa` doesn't always send** — delete old emails before calling, codes may have cooldown
|
||||
3. **React SPA navigation broken in headless** — use direct `fetch()` from console
|
||||
4. **Field names are specific**: `postalCode` not `zipCode`, `invoiceName` required, `firstName`/`lastName` not `name`
|
||||
5. **Country format**: `"US"` (2-letter ISO) works, `"USA"` fails
|
||||
6. **Card validation is sequential** — fix errors one at a time, each reveals the next
|
||||
Reference in New Issue
Block a user