Files
autoreg-skills-max/skills/cloud-trial-registration/references/upcloud-api.md

9.7 KiB

UpCloud API Reference

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": "<email>"}
→ 200 if valid

3. Init registration

POST https://signup.upcloud.com/api/v2/init
{"captcha": "<hCaptcha token>", "email": "<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=<token>
  • Verify via IMAP (see Email pool section below)
POST https://signup.upcloud.com/api/v2/verify
{"token": "<verify token>"}
→ 200 {"email": "...", "first_name": "signup", "last_name": "user", "promo_code": "deploy250"}

5. Finalize account

  • Check username availability: GET /api/v2/check-username/<username> → 404 = free
POST https://signup.upcloud.com/api/v2/finalize-lite
{
  "country": "DEU", "currency": "EUR", "email": "<email>",
  "first_name": "signup", "last_name": "user",
  "password": "<password>", "phone": "<phone>",
  "username": "<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": "<hCaptcha token>", "username": "<username>", "password": "<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": "<email>", "captcha_token": "<token>"} → 201
# Wait for OTP email (code in format *XXXXXX*, regex: \*([A-Z0-9]{4,10})\*)
POST /v2/user/auth/login {"captcha_token": "<new token>", "code": "<OTP>", "email": "<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": "<base64 JWT>"}
  • 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 <authorizationFingerprint>
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": "<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

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)