Skip to content
API reference · v1.0.0

NUVEXIQ Cloud Phone API

Rent and control real Android cloud phones with scoped API tokens.

Base URL https://nuvexiq.com/api/v1
OpenAPI 3.1 spec (YAML) Create an account

Authentication

Create a token on the Developers page and send it as a bearer token. Tokens start with nvx_, are shown once, and expire after 90 days (you get an email a week before). Each token has scopes; a request outside its scopes returns 403 forbidden.

Authorization: Bearer nvx_your_token
wallet:readphones:readphones:createphones:powerphones:remote-sessionbilling:read

Tokens created inside an organization workspace charge that organization's wallet.

Idempotency

Send an Idempotency-Key header (a UUID) with POST /cloud-phone-orders, POST /cloud-phones and POST /cloud-phones/{phoneId}/renew. Retrying with the same key returns the original response (with X-Idempotent-Replay: true) and never charges twice. Reusing a key with a different body returns 422; a retry while the first request is still running returns 409.

Errors & rate limits

Errors are JSON with a machine-readable error code and a human-readable message. Validation errors use 422 with an errors object per field.

{ "error": "ENTITLEMENT_REQUIRED", "message": "No unused cloud phone entitlement. Create an order first." }
StatusMeaning
401unauthorized, invalid_token or token_expired
403forbidden (missing scope or role) or account_inactive
404not_found: the resource doesn't exist or isn't yours
422Validation failed, or a business rule (e.g. insufficient balance)
429Rate limited: 60 requests/minute overall, 10 purchase requests/minute. Respect Retry-After.

Cloud phones

GET /cloud-phone-plans

List cloud phone plans and per-phone prices

Prices are per cloud phone for the chosen rental period (7, 30 or 90 days). There is no per-minute billing.

No token required.

curl "https://nuvexiq.com/api/v1/cloud-phone-plans"
200 Plans on sale, each with its active prices
POST /cloud-phone-orders

Rent cloud phones

Charges price per phone × quantity − coupon discount + tax (if configured) from your wallet (prices come from the server, never the client) and creates one entitlement per phone. With create_phones (default true) each phone starts provisioning immediately; the rental period starts only when the phone is ready. Refused when capacity is not available. Use an Idempotency-Key so a retry is charged once.

Scope: phones:create

NameInType
Idempotency-Key header string (uuid)
plan_id* body string
rental_period_days* body integer: 7 | 30 | 90
quantity* body integer
create_phones body boolean
coupon_code body string
curl -X POST "https://nuvexiq.com/api/v1/cloud-phone-orders" \
  -H "Authorization: Bearer nvx_your_token" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"plan_id":"essential","rental_period_days":30,"quantity":1,"create_phones":true,"coupon_code":"LAUNCH10"}'
201 Order with its entitlements, and the phones being created
403 INSUFFICIENT_SCOPE (the token lacks phones:create, or the plan does not include API access; buy it from the dashboard), or BETA_ACCESS_REQUIRED (cloud phones are in private beta and this account has not been let in yet)
409 CAPACITY_UNAVAILABLE, INSUFFICIENT_FUNDS, COUPON_INVALID or ORDER_REJECTED
503 SERVICE_TEMPORARILY_UNAVAILABLE (cloud phones not on sale)
GET /cloud-phone-orders/{orderId}

Fetch a cloud phone order

Scope: billing:read

NameInType
orderId* path string (uuid)
curl "https://nuvexiq.com/api/v1/cloud-phone-orders/{orderId}" \
  -H "Authorization: Bearer nvx_your_token"
200 Order totals, status and entitlements
404 ORDER_NOT_FOUND
GET /cloud-phone-entitlements

List paid cloud phone entitlements

One entitlement per paid phone; status available (not created yet), consumed or refunded.

Scope: billing:read

curl "https://nuvexiq.com/api/v1/cloud-phone-entitlements" \
  -H "Authorization: Bearer nvx_your_token"
200 Entitlements, newest first
GET /cloud-phones

List your cloud phones

Returns cloud phones owned by the authenticated account.

Scope: phones:read

NameInType
per_page query integer, default 25
curl "https://nuvexiq.com/api/v1/cloud-phones?per_page=…" \
  -H "Authorization: Bearer nvx_your_token"
200 Phones (id, display_name, status, power_state, plan, expires_at, remaining_days, pending_operation)
POST /cloud-phones

Create a cloud phone from an unused entitlement

Creates a cloud phone using an unused entitlement when infrastructure capacity is available. Asynchronous; poll the phone.

Scope: phones:create

NameInType
Idempotency-Key header string (uuid)
entitlement_id body string
display_name body string
curl -X POST "https://nuvexiq.com/api/v1/cloud-phones" \
  -H "Authorization: Bearer nvx_your_token" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"entitlement_id":"ent_01j\u2026","display_name":"Marketing Phone 01"}'
202 Phone accepted with status provisioning
402 ENTITLEMENT_REQUIRED
GET /cloud-phones/{phoneId}

Get phone status

Scope: phones:read

NameInType
phoneId* path string
curl "https://nuvexiq.com/api/v1/cloud-phones/{phoneId}" \
  -H "Authorization: Bearer nvx_your_token"
200 Phone details
404 PHONE_NOT_FOUND
DELETE /cloud-phones/{phoneId}

Request deletion of a phone

Records a deletion request. Deletion is confirmed by NUVEXIQ staff and removes the phone and its data permanently.

Scope: phones:create

NameInType
phoneId* path string
curl -X DELETE "https://nuvexiq.com/api/v1/cloud-phones/{phoneId}" \
  -H "Authorization: Bearer nvx_your_token"
202 Deletion requested
POST /cloud-phones/{phoneId}/start

Start my phone

Requests startup of a cloud phone owned by the authenticated account. Asynchronous; use the phone-status endpoint to monitor progress.

Scope: phones:power

NameInType
phoneId* path string
curl -X POST "https://nuvexiq.com/api/v1/cloud-phones/{phoneId}/start" \
  -H "Authorization: Bearer nvx_your_token"
202 Accepted (operation_id, status)
409 PHONE_ALREADY_RUNNING, PHONE_NOT_READY or PROVISIONING_IN_PROGRESS
POST /cloud-phones/{phoneId}/stop

Stop my phone

Requests a controlled stop. Stopping does not pause the rental period.

Scope: phones:power

NameInType
phoneId* path string
curl -X POST "https://nuvexiq.com/api/v1/cloud-phones/{phoneId}/stop" \
  -H "Authorization: Bearer nvx_your_token"
202 Accepted
409 PHONE_ALREADY_STOPPED or PHONE_NOT_READY
POST /cloud-phones/{phoneId}/reboot

Restart my phone

Scope: phones:power

NameInType
phoneId* path string
curl -X POST "https://nuvexiq.com/api/v1/cloud-phones/{phoneId}/reboot" \
  -H "Authorization: Bearer nvx_your_token"
202 Accepted
409 PHONE_NOT_READY
POST /cloud-phones/{phoneId}/renew

Renew a phone

Charges the plan's price for the period from your wallet. Active phones extend from their current expiry; expired or suspended phones extend from now and are restarted.

Scope: phones:create

NameInType
Idempotency-Key header string (uuid)
rental_period_days* body integer: 7 | 30 | 90
coupon_code body string
curl -X POST "https://nuvexiq.com/api/v1/cloud-phones/{phoneId}/renew" \
  -H "Authorization: Bearer nvx_your_token" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"rental_period_days":30,"coupon_code":"RENEW20"}'
201 Renewal order and updated phone
409 INSUFFICIENT_FUNDS, COUPON_INVALID or PHONE_NOT_READY
POST /cloud-phones/{phoneId}/remote-sessions

Open a remote-access session

Creates a short-lived authorized remote-access session for an eligible running cloud phone. Single controller; expires if not used within two minutes. Returns REMOTE_SESSION_UNAVAILABLE while remote access is not enabled.

Scope: phones:remote-session

NameInType
phoneId* path string
curl -X POST "https://nuvexiq.com/api/v1/cloud-phones/{phoneId}/remote-sessions" \
  -H "Authorization: Bearer nvx_your_token"
201 session_id, expires_at, stream_host, ports, and urls (video/touch WebSocket URLs, wss://stream_host:port; with path routing one hostname on 443)
409 REMOTE_SESSION_UNAVAILABLE

Wallet

GET /wallet/balance

Query wallet balance

Scope: wallet:read

curl "https://nuvexiq.com/api/v1/wallet/balance" \
  -H "Authorization: Bearer nvx_your_token"
200 Available and reserved hold balances (decimal strings, 2 places)
GET /wallet/transactions

List wallet ledger entries

Scope: wallet:read

NameInType
per_page query integer, default 20
curl "https://nuvexiq.com/api/v1/wallet/transactions?per_page=…" \
  -H "Authorization: Bearer nvx_your_token"
200 Paginated double-entry ledger lines (amounts as 4-decimal strings)

Inbound callbacks

Called by payment processors and suppliers, not by customers. Listed for partners and operators.

POST /payments/callback

Payment processor deposit callback

Called by the payment processor, not by customers. Authenticated only by X-Nuvexiq-Signature = hex HMAC-SHA256 of the raw body using NUVEXIQ_PAYMENT_WEBHOOK_SECRET. Confirmations are idempotent; the amount actually received minus fee is credited.

NameInType
X-Nuvexiq-Signature* header string
deposit_id* body string (uuid)
status* body string: confirmed | failed | pending
tx_id body string
amount_received body string
fee body string
200 Callback received (applied=false when the deposit can no longer change)
401 Invalid signature
404 Unknown deposit
422 Malformed payload