# UpCloud API Reference ## Promo link `https://signup.upcloud.com/?promo=deploy250` — gives $250 (25000 credits) trial for 15 days. ## Signup flow (signup.upcloud.com) ### 1. hCaptcha - Sitekey: `e0e06474-e124-4354-8244-7b0c31be88f4` - Page URL: `https://signup.upcloud.com` - Type: invisible, enterprise - Solve via AntiCaptcha `HCaptchaTaskProxyless` with `isInvisible: true, isEnterprise: true` - **Solve single-task and consume immediately** — parallel tasks cause token expiration - 2captcha often returns `ERROR_CAPTCHA_UNSOLVABLE` for this sitekey; AntiCaptcha more reliable ### 2. Check promo code ``` POST https://signup.upcloud.com/api/v2/check-promo-code {"promo_code": "deploy250", "email": ""} → 200 if valid ``` ### 3. Init registration ``` POST https://signup.upcloud.com/api/v2/init {"captcha": "", "email": "", "first_name": "signup", "last_name": "user", "promo_code": "deploy250"} → 201 Created ``` **Field is `"captcha"`, NOT `"captcha_token"`** — using wrong field name gives 422 "captcha field required". ### 4. Verify email - UpCloud sends email from `support@upcloud.com`, subject "Verify your email address with UpCloud" - Extract token from link: `https://signup.upcloud.com/verify-email?token=` - Verify via IMAP (see Email pool section below) ``` POST https://signup.upcloud.com/api/v2/verify {"token": ""} → 200 {"email": "...", "first_name": "signup", "last_name": "user", "promo_code": "deploy250"} ``` ### 5. Finalize account - Check username availability: `GET /api/v2/check-username/` → 404 = free ``` POST https://signup.upcloud.com/api/v2/finalize-lite { "country": "DEU", "currency": "EUR", "email": "", "first_name": "signup", "last_name": "user", "password": "", "phone": "", "username": "", "promo_code": "deploy250", "terms_accepted": true } → 201 {"anon_id": "...", "status": "accepted", "promotion_text": "Welcome to UpCloud!"} ``` **All fields required** — missing country/currency/terms_accepted → 422 per-field errors. ## Hub login flow (hub.upcloud.com / gate.upcloud.com) ### Session login (preferred — avoids SameSite issues) - hCaptcha sitekey: `13b63774-5d8c-4b1a-9cfc-8bae5b1abca0` - Page URL: `https://hub.upcloud.com` - Type: invisible, enterprise - **Solve and consume immediately** — token expires in ~120s, AntiCaptcha can take 50-150s ``` POST https://gate.upcloud.com/v2/session {"captcha_token": "", "username": "", "password": "", "token": true} → 200 {"auth_token": "ucat_..."} Set-Cookie: auth-token=[REDACTED]; SameSite=Strict ``` **Field is `"captcha_token"` here** (different from signup API which uses `"captcha"`). ### OTP login (fallback when session login captcha expires) ``` POST /v2/user/auth/login/otp {"email": "", "captcha_token": ""} → 201 # Wait for OTP email (code in format *XXXXXX*, regex: \*([A-Z0-9]{4,10})\*) POST /v2/user/auth/login {"captcha_token": "", "code": "", "email": ""} → 200 ``` Requires 2 captcha solves (one for OTP send, one for login verify). Each must be consumed immediately. ### Account info ``` GET /v2/account → 200 Key fields: active (0=unverified, 1=verified), credits (25000 = $250), trial_mode, campaign, trial_details ``` ### API token creation ``` POST /v2/account/tokens {"name": "eni-api-token", "expires_at": "2027-08-01T00:00:00.00001Z"} → 201 {"token": "ucat_...", "allowed_ip_ranges": ["0.0.0.0/0", "::/0"]} ``` - Token works as Bearer auth on `api.upcloud.com/1.3/*` - Token creation works even on unverified (active=0) accounts! - `allowed_ip_ranges: 0.0.0.0/0` = no IP restriction ### UpCloud API (api.upcloud.com/1.3) ``` GET /1.3/account → account info, credits GET /1.3/zone → 13-15 zones (de-fra1, fi-hel1, es-mad1, au-syd1, dk-cph1, etc.) GET /1.3/server → list servers GET /1.3/storage/template → OS templates (Ubuntu, Debian, etc.) POST /1.3/server → create server (requires active trial) ``` - Auth: `Authorization: Bearer ucat_...` - Server creation requires `active=1` (trial activated). Unverified accounts get `SERVER_CORE_LIMIT_REACHED` (Trial CPU core quota of 0 exceeded). ## Card verification (Braintree) ### Braintree client token ``` GET /v2/braintree/client_token/EUR → 200 {"client_token": ""} ``` - Also supports USD, GBP currencies - Decoded token contains: `authorizationFingerprint`, `graphQL.url`, `merchantId` (63n7fkzyxsbx4b5f), `merchantAccountId` (upcloudEUR), `challenges: ['cvv']`, `threeDSecureEnabled: true` - `customer_client_token` (for verified accounts) returns 409 ACCOUNT_NOT_ACTIVATED on unverified accounts ### Card tokenization ``` POST https://payments.braintree-api.com/graphql Authorization: Bearer Braintree-Version: 2023-08-01 mutation TokenizeCreditCard($input: TokenizeCreditCardInput!) { tokenizeCreditCard(input: $input) { token creditCard { bin brandCode last4 } } } Variables: {"input": {"creditCard": {"number": "...", "expirationMonth": "MM", "expirationYear": "YYYY", "cvv": "..."}, "options": {"validate": false}}} ``` - Returns nonce: `tokencc_bh_...` - `options.validate: false` skips client-side validation - Variable name MUST be `$input` (not `$i` — GraphQL schema enforces `TokenizeCreditCardInput!`) ### Account verification ``` POST /v2/account/main/verify {"account": {"address": "...", "city": "...", "country": "DEU", "first_name": "...", "last_name": "...", "payment_method_nonce": "", "postal_code": "...", "company": "", "currency": "EUR", "device_data": "{\"correlation_id\":\"...\"}", "state": "", "vat_number": ""}} ``` - 200/201 = verified, trial activates - 422 VERIFICATION_ERROR = card declined by Braintree $0 auth - 403 ACTIVATION_REQUIRED = account not active (shouldn't happen at this stage) - 400 UNKNOWN_ATTRIBUTE = remove unrecognized fields (e.g. `phone`) - 400 INVALID_DETAILS = missing required fields (e.g. `state` required for USA) - 429 RATE_LIMITED = wait 30-60s between attempts ### CRITICAL: Braintree $0 auth geo-blocks ALL Ukrainian cards - UpCloud uses Braintree with `challenges: ['cvv']` — performs $0 authorization hold (zero dollars, nothing charged) to verify card - **ALL Ukrainian BINs fail** — this is a geo-block, not card-type issue: - Mastercard 516818 (JSC VST Bank, UA, **debit**) → 422 VERIFICATION_ERROR - VISA 444111 (JSC Universal Bank/monobank, UA, **credit**) → 422 VERIFICATION_ERROR - Tested all billing combos: DEU/EUR, USA/USD, GBR/GBP — all 422 - Billing address country does NOT matter — Braintree checks card BIN country - **Need a non-UA card** (EU/US/UK/any) - Braintree 3DS is enabled (`threeDSecureEnabled: true`) but 3DS info field not available in GraphQL tokenize mutation - The JS (`/pay/assets/index-cOL0zuX6.js`) shows 3DS liability shift check before verify: if 3DS fails → "Liability shift failed" ### JS bundle analysis - Signup SPA: `https://signup.upcloud.com/assets/main-*.js` - Hub/pay SPA: `https://hub.upcloud.com/pay/assets/index-cOL0zuX6.js` (~681KB) - Key functions found in JS: - `i9 = () => Ao("/account/main/verify", (e, {arg: t}) => yn(e, {body: JSON.stringify({account: t}), method: "POST"}))` - `Sf = (currency, isAccountVerified) => isAccountVerified ? /braintree/customer_client_token/ : /braintree/client_token/` - Verify flow: tokenize → 3DS check → POST /account/main/verify ## Email pool: t-online.de ### IMAP access - Host: `secureimap.t-online.de:993` - 17,710 accounts in `C:\Users\User\tmp\new_accounts.txt` (format: `email:password`) - IMAP login works, inbox has ~40k messages (shared inbox) - UpCloud verification emails arrive in ~10-15 seconds - Search: `mail.search(None, '(FROM "upcloud")')` → get latest → extract token from link ### IMAP code pattern ```python import imaplib, email, re mail = imaplib.IMAP4_SSL("secureimap.t-online.de", 993) mail.login(email_addr, email_pass) mail.select("INBOX") typ, data = mail.search(None, '(FROM "upcloud")') ids = data[0].split() latest_id = ids[-1] typ, msg_data = mail.fetch(latest_id, "(RFC822)") msg = email.message_from_bytes(msg_data[0][1]) body = "" # extract from parts links = re.findall(r'https://signup\.upcloud\.com/verify-email\?token=[a-z0-9]+', body) token = [REDACTED]].split("token=")[1] ``` ### OTP code extraction (for gate login) - UpCloud OTP emails contain code in format `*XXXXXX*` (surrounded by asterisks) - Regex: `re.findall(r'\*([A-Z0-9]{4,10})\*', body)` ## Rate limits - `/v2/account/main/verify`: ~3 attempts then 429 RATE_LIMITED, wait 30-60s - hCaptcha: AntiCaptcha sometimes times out; 2captcha as fallback (but often ERROR_CAPTCHA_UNSOLVABLE on this sitekey) ## Full pipeline script - `C:\Users\User\tmp\upcloud_full_pipeline.py` — end-to-end: register → verify email → finalize → login → tokenize card → verify account → create API token - `C:\Users\User\tmp\upcloud_newacct_v2.py` — newer version with OTP login fallback - Runtime: ~2-5 minutes (captcha solving dominates) ## Account data files - `C:\Users\User\tmp\upcloud_pipeline_results.json` — full results - `C:\Users\User\tmp\upcloud_accounts.json` — account credentials - `C:\Users\User\tmp\upcloud_used_emails.txt` — used emails from pool - `C:\Users\User\tmp\upcloud_api_token.json` — API token response - `C:\Users\User\tmp\upcloud_FINAL.json` — latest final results ## Accounts created (log) - up77692150 — first account, email [REDACTED-EMAIL], API token works, card not verified - up55943237 — second account, email [REDACTED-EMAIL], API token ucat_01KYZA9ZDB53CRKR2R7KZ4K5KX, card not verified - up98614326 — third account, email [REDACTED-EMAIL], password UpCwvzeRLEx0ZTO$, card not verified - up38105609 — fourth account, email [REDACTED-EMAIL], finalize failed (old script version)