Referral Program
Developers

API Documentation

A simple REST API to buy and manage proxies programmatically. Top up your balance, then create orders, list and export proxies, and renew them - all with a single API key.

Version v1 · Base URL https://api.sotaproxy.com/api/v1

Getting started

  1. Open your dashboard and go to the API section.
  2. Create a key. Copy the secret - it is shown only once.
  3. Send the key with every request (see Authentication).
  4. Your account balance is prepaid. Orders draw from it, so top up in the dashboard before buying.

All request and response bodies are JSON. All prices are in USD.

Authentication

Send your key in the Authorization header as a bearer token, or in the X-API-Key header. Never put the key in the URL.

Authorization: Bearer sk_live_your_key_here
# or
X-API-Key: sk_live_your_key_here

Keys can carry scopes: read (read-only) and trade (create and renew orders). A key with no scopes has full access.

curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/ping
# → {"ok":true,"service":"sotaproxy","version":"v1"}

Rate limits

Limits are applied per API key (per minute):

  • Reads (balance, orders, proxies): 120 / min
  • Catalog and quotes: 60 / min
  • Orders and renewals: 20 / min

Exceeding a limit returns HTTP 429.

Idempotency

Money-moving requests (creating an order, renewing a proxy) require an Idempotency-Key header - any unique string per attempt (max 128 chars). If a request is retried with the same key, the original result is returned instead of charging twice. The replayed response includes "idempotentReplay": true.

Errors

Errors return the matching HTTP status and a JSON body: {"error":{"code":"...","message":"..."}}.

StatusMeaning
400Invalid request parameters
401Missing or invalid API key
402Insufficient balance
403API key is missing the required scope
404Resource not found
409Idempotency key already in progress
429Rate limit exceeded
500 / 502Temporary server or upstream error - retry shortly

Endpoints

Products are ipv4, ipv6 and isp. Each product has its own list of country IDs and rental periods - always fetch them from /products first. IPv6 has a minimum quantity of 10 and serves ONE protocol chosen at order time via the protocol field (HTTPS by default, or SOCKS5) - the issued proxy exposes only the matching port (portHttp or portSocks; the other is null).

List products

GET/products

Returns sellable products with their available countries and rental periods. Prices are per account - use /quote for the price.

curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/products
{
  "products": [
    {
      "product": "ipv4",
      "unit": "proxy",
      "countries": [ { "id": 565, "name": "US", "alpha3": null }, ... ],
      "periods": [
        { "id": "1m", "name": "1 month",  "days": 30 },
        { "id": "2m", "name": "2 months", "days": 60 }, ...
      ]
    }
  ]
}

Price a prospective order

POST/quote

Returns the exact price for a given product, country, period and quantity without buying.

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"product":"ipv4","countryId":565,"periodId":"1m","quantity":5}' \
  https://api.sotaproxy.com/api/v1/quote
{
  "product": "ipv4", "countryId": 565, "periodId": "1m", "quantity": 5,
  "unitPrice": 1.8, "total": 9, "currency": "USD",
  "balance": 42.5, "sufficientBalance": true
}

Create an order

POST/orders

Buys and provisions proxies, charging your balance. Requires the trade scope and an Idempotency-Key header. Optional body fields: purpose (usage note) and protocol (HTTPS or SOCKS5).

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: your-unique-id" \
  -d '{"product":"ipv4","countryId":565,"periodId":"1m","quantity":5}' \
  https://api.sotaproxy.com/api/v1/orders
{
  "order": {
    "id": "31307ef6-6ee4-4ec7-8a78-e5bd6ee52b9b",
    "product": "ipv4", "country": "US", "periodId": "1m",
    "quantity": 5, "total": 9, "currency": "USD",
    "status": "completed", "createdAt": "2026-07-24T23:11:03.617Z"
  },
  "idempotentReplay": false
}

Note: proxies for a new order may take a few minutes to appear (especially IPv6). Poll /orders/{id}/proxies until they are returned.

List and read orders

GET/orders · /orders/{id}

List your orders (paginated: ?page, ?limit) or read a single order by id.

curl -H "Authorization: Bearer $KEY" "https://api.sotaproxy.com/api/v1/orders?limit=20"
curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/orders/ORDER_ID

Get an order’s proxies

GET/orders/{id}/proxies

Returns the issued proxies for an order. Add ?format=txt for plain ip:port:login:password lines.

curl -H "Authorization: Bearer $KEY" \
  "https://api.sotaproxy.com/api/v1/orders/ORDER_ID/proxies?format=txt"
{
  "proxies": [
    {
      "id": "e8c2...", "product": "ipv4", "ip": "23.165.240.2",
      "portHttp": 11565, "portSocks": null,
      "login": "user", "password": "pass",
      "country": "US", "status": "active",
      "expiresAt": "2026-07-31T00:00:00.000Z"
    }
  ]
}

List all proxies

GET/proxies

Returns every active proxy on your account. Filter by product with ?product=ipv4.

curl -H "Authorization: Bearer $KEY" "https://api.sotaproxy.com/api/v1/proxies?product=ipv4"

Price a renewal

GET/proxies/{id}/renew-quote

Returns the exact price to renew a proxy’s order for a given period without charging - use it to show the cost before confirming. Like the renewal itself, this is order-level: proxiesRenewed is the whole order and price covers all of them. Query periodId is one of 1m, 3m, 6m, 12m (defaults to 1m). No Idempotency-Key needed.

curl -H "Authorization: Bearer $KEY" \
  "https://api.sotaproxy.com/api/v1/proxies/PROXY_ID/renew-quote?periodId=1m"
{
  "proxyId": "2364b03b-...", "periodId": "1m",
  "proxiesRenewed": 10, "price": 2, "currency": "USD",
  "newExpiresAt": "2026-10-01T00:00:00.000Z"
}

Renew an order’s proxies

POST/proxies/{id}/renew

Extends a proxy - renewal is order-level: renewing one proxy renews every proxy bought in the same order, and the charge covers all of them. Requires the trade scope and an Idempotency-Key. Body periodId is one of 1m, 3m, 6m, 12m.

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: renew-unique-id" \
  -d '{"periodId":"1m"}' \
  https://api.sotaproxy.com/api/v1/proxies/PROXY_ID/renew
{
  "proxyId": "2364b03b-...", "newExpiresAt": "2026-10-01T00:00:00.000Z",
  "amountCharged": 2, "proxiesRenewed": 10, "currency": "USD",
  "idempotentReplay": false
}

Residential proxies (traffic-based)

POST/residential/*

Residential works differently from period products: you buy a GB traffic package, then create one or more endpoints inside it. Each endpoint pins optional geo targeting (country / region / city / ISP) and rotation, and returns ready-to-use gateway credentials. Traffic is drawn from the package as endpoints are used.

1. Plans - GET /residential/plans lists GB packages with your account’s pricing (contract per-GB price applies automatically).

2. Geo catalog - GET /residential/locations returns countries; add ?country=AT for regions, cities and ISPs.

3. Buy a package - requires the trade scope and an Idempotency-Key:

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: res-unique-id" \
  -d '{"planId":"ind_3gb"}' \
  https://api.sotaproxy.com/api/v1/residential/orders
{
  "package": { "id": "81cdc5d0-...", "plan": "3 GB", "trafficGb": 3,
    "pricePerGb": 2, "totalPrice": 6, "trafficLeftGb": 3,
    "active": true, "expiresAt": "2026-08-22T23:59:59.000Z" },
  "amountCharged": 6, "currency": "USD", "idempotentReplay": false
}

4. Create an endpoint (geo is pinned here) - the response carries credentials you can plug straight into any client:

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"packageId":"81cdc5d0-...","name":"Austria sticky","country":"AT","rotation":-1}' \
  https://api.sotaproxy.com/api/v1/residential/lists
{
  "list": { "id": "d7e8cbf4-...", "country": "AT", "rotation": -1, ... },
  "proxy": {
    "host": "proxy.sotaproxy.com", "portHttp": 10000, "portSocks": 10000,
    "login": "3c4d8398...", "password": "fTYRr2CH...",
    "httpUrl": "http://login:password@proxy.sotaproxy.com:10000",
    "socksUrl": "socks5://login:password@proxy.sotaproxy.com:10000"
  }
}

rotation: 0 = new IP per request, -1 = sticky session, 1–3600 = seconds between rotations. Manage endpoints with GET /residential/lists, DELETE /residential/lists/{id}; track usage via GET /residential/packages.

Mobile proxies (tariff-based)

POST/mobile/*

Mobile proxies are sold per modem from a fixed tariff catalog (country + carrier + rental period). Pick a tariff, buy N units - the order then behaves like any other: GET /orders/{id}/proxies returns the credentials.

curl -H "Authorization: Bearer $KEY" "https://api.sotaproxy.com/api/v1/mobile/tariffs?country=DE"
{
  "tariffs": [
    { "id": "mt_f1098dbc7be7a1b0", "country": "DE", "carrier": "Vodafone Germany",
      "periodId": "day", "period": "1 day", "unitPrice": 8.64,
      "dedicated": true, "stock": 16 }
  ],
  "currency": "USD"
}

Buy - requires the trade scope and an Idempotency-Key:

curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: mob-unique-id" \
  -d '{"tariffId":"mt_f1098dbc7be7a1b0","quantity":1}' \
  https://api.sotaproxy.com/api/v1/mobile/orders

Tariff availability is stock-limited - always check stock before ordering. Mobile proxies also appear in GET /proxies?product=mobile.

Account

GET/balance · /me

Read your prepaid balance, or the account and scopes a key belongs to.

curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/balance
# → {"balance":42.5,"currency":"USD"}

curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/me
# → {"accountId":"...","scopes":["read","trade"]}

Reseller subaccounts

GET/reseller/*

A partner running their own platform keeps their users, signups and balances on their side. What they need from us is the ability to slice the stock they already bought: create a client, give it an amount, issue credentials and read usage for their own billing.

Requires is_reseller on the account. Writes require the trade scope. The same operations exist in the dashboard, and both surfaces call the same service.

MethodPathPurpose
GET/reseller/stockHow much traffic is free to hand out
GET/reseller/clientsYour clients with their limits and usage
POST/reseller/clientsCreate a client (name, optional email)
DELETE/reseller/clients/{id}Delete a client; unused traffic returns to your stock
POST/reseller/clients/{id}/trafficGive a client traffic. Idempotent, Idempotency-Key required
DELETE/reseller/clients/{id}/trafficReclaim the unused remainder
POST/reseller/clients/{id}/accessIssue proxy credentials for that client
GET/reseller/clients/{id}/accessList the credentials a client holds
DELETE/reseller/clients/{id}/access/{accessId}Revoke one credential
GET/reseller/usageUsage across every client in one call, for billing
GET/reseller/proxiesYour static proxies. ?filter=free, ?type=ipv4
GET/reseller/clients/{id}/proxiesThe proxies pinned to one client, with credentials
POST/reseller/clients/{id}/proxiesPin static proxies to a client
DELETE/reseller/clients/{id}/proxiesUnpin them again

The flow, end to end

Five calls cover a client from signup to invoice. Traffic is returned as both units throughout: {"mb": 1024, "gb": 1}.

# 1. how much can I hand out right now
curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/reseller/stock

# 2. a new client signed up on your platform
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"name":"acme-corp"}' https://api.sotaproxy.com/api/v1/reseller/clients
# → {"client":{"id":"<clientId>", ...}}

# 3. they paid you for 10 GB
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-8412" \
  -d '{"trafficGb":10}' https://api.sotaproxy.com/api/v1/reseller/clients/<clientId>/traffic

# 4. issue their credentials
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"name":"main","ports":5,"rotation":-1,"country":"US"}' \
  https://api.sotaproxy.com/api/v1/reseller/clients/<clientId>/access
# → login/password + host + portFrom..portTo + readyInSeconds

# 5. bill them: poll usage on your schedule
curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/reseller/usage

Static proxies work differently

Traffic divides, an address does not. IPv4, IPv6 and ISP can only be pinned to a client, never split. You stay the owner and the payer, so renewals and auto-renew keep running off your balance and the customer relationship never touches us. Unpinning returns the proxy to your free pool untouched.

# what is free to hand out right now
curl -H "Authorization: Bearer $KEY" "https://api.sotaproxy.com/api/v1/reseller/proxies?filter=free&type=ipv4"

# pin two of them to a client
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"proxyIds":["<id1>","<id2>"]}' https://api.sotaproxy.com/api/v1/reseller/clients/<clientId>/proxies
# → {"requested":2,"assigned":2}

# what that client holds, with credentials to hand over
curl -H "Authorization: Bearer $KEY" https://api.sotaproxy.com/api/v1/reseller/clients/<clientId>/proxies

Notes that save a support ticket

  • ·Credentials need about 90 seconds before they authenticate, because the upstream network registers them asynchronously. Until then connections answer 407. The issue response carries readyInSeconds so you can delay showing them to your user.
  • ·`rotation`: -1 holds a sticky session, 0 gives a new IP per request, any other value is the number of seconds before the IP changes.
  • ·Ports: one credential spans portFrom..portTo, and each port is an independent session with its own IP. A single port serves both HTTP and SOCKS5.
  • ·Allocation is capped by real headroom, not by the raw remainder: traffic already handed to other clients is subtracted first.
  • ·Hierarchy is one level. A client cannot have clients of its own, and your clients get no login to our dashboard. Your users live on your platform, which is the point of this API.
  • ·assigned reports what actually happened when pinning proxies. Ids that are not yours, or already gone, are skipped rather than failing the whole call, so compare it against requested if you need to react.

MCP server - buy proxies from Claude & AI agents

POSThttps://api.sotaproxy.com/mcp

Connect SotaProxy to Claude (or any AI assistant that supports MCP) and manage proxies by simply chatting: “buy me 5 US ISP proxies for a month”, “get 3 GB of residential traffic with Austria geo”, “what’s my balance?”. The assistant always shows you the exact price and asks for confirmation before spending anything. Full MCP guide with all 18 tools →

Before you start: get your API key (once)

  1. Open app.sotaproxy.com/api (the API item in the dashboard sidebar).
  2. Under Create new key, select both scopes - read and trade - and click Create key.
  3. Copy the key that appears (it starts with sk_live_). It is shown only once - save it somewhere safe.

In every snippet below, replace sk_live_YOUR_KEY with this key.

Option A - Claude.ai website or Claude Desktop app

Easiest if you chat with Claude in the browser or the desktop app.

  1. In Claude, open Settings → Connectors.
  2. Click Add custom connector.
  3. Name: SotaProxy. URL - paste this (with your key inside):
https://api.sotaproxy.com/mcp?key=sk_live_YOUR_KEY
  1. Click Add. In a new chat, open the tools menu (the sliders icon) and make sure SotaProxy is enabled.
  2. Ask: “What’s my SotaProxy balance?” - if it answers with your balance, you’re connected.

Option B - Claude Code (terminal)

If you use the claude CLI.

  1. Open your terminal and paste this one command (key replaced):
claude mcp add --transport http sotaproxy https://api.sotaproxy.com/mcp \
  --header "Authorization: Bearer sk_live_YOUR_KEY"
  1. Start (or restart) claude and ask: “What’s my SotaProxy balance?”
  2. To remove later: claude mcp remove sotaproxy.

Option C - Cursor and other MCP clients

  1. In Cursor: Settings → MCP → Add new global MCP server (this opens ~/.cursor/mcp.json).
  2. Paste this block (or merge it into the existing mcpServers object):
{
  "mcpServers": {
    "sotaproxy": {
      "url": "https://api.sotaproxy.com/mcp",
      "headers": { "Authorization": "Bearer sk_live_YOUR_KEY" }
    }
  }
}

Save the file - the SotaProxy tools appear after a reload. Any other MCP-compatible client works the same way: URL https://api.sotaproxy.com/mcp + your key as a Bearer header (or ?key= in the URL if headers aren’t supported).

Things to try once connected

  • “What’s my balance?”
  • “How much would 10 US IPv6 proxies for a week cost?”
  • “Buy 5 US ISP proxies for a month” (it quotes first, then asks you to confirm)
  • “Buy 3 GB of residential and create an endpoint with Austria geo, sticky sessions”
  • “List my proxies and export them as ip:port:login:password”
  • “Renew my expiring order for another month” (shows the order-level price before charging)

Troubleshooting: an authentication error means the key is wrong or was revoked - create a fresh one in the dashboard. If buying fails with a scope error, the key is missing the trade scope. Purchases draw from your prepaid balance - top up in the dashboard first. Keys in URLs are sensitive: prefer the header form where supported, and revoke keys you no longer use.

Need help integrating, or higher limits and contract pricing? Contact us.