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
- Open your dashboard and go to the API section.
- Create a key. Copy the secret - it is shown only once.
- Send the key with every request (see Authentication).
- 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_hereKeys 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":"..."}}.
| Status | Meaning |
|---|---|
| 400 | Invalid request parameters |
| 401 | Missing or invalid API key |
| 402 | Insufficient balance |
| 403 | API key is missing the required scope |
| 404 | Resource not found |
| 409 | Idempotency key already in progress |
| 429 | Rate limit exceeded |
| 500 / 502 | Temporary 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
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
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
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
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_IDGet an order’s 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
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
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
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)
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)
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/ordersTariff availability is stock-limited - always check stock before ordering. Mobile proxies also appear in GET /proxies?product=mobile.
Account
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
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.
| Method | Path | Purpose |
|---|---|---|
| GET | /reseller/stock | How much traffic is free to hand out |
| GET | /reseller/clients | Your clients with their limits and usage |
| POST | /reseller/clients | Create a client (name, optional email) |
| DELETE | /reseller/clients/{id} | Delete a client; unused traffic returns to your stock |
| POST | /reseller/clients/{id}/traffic | Give a client traffic. Idempotent, Idempotency-Key required |
| DELETE | /reseller/clients/{id}/traffic | Reclaim the unused remainder |
| POST | /reseller/clients/{id}/access | Issue proxy credentials for that client |
| GET | /reseller/clients/{id}/access | List the credentials a client holds |
| DELETE | /reseller/clients/{id}/access/{accessId} | Revoke one credential |
| GET | /reseller/usage | Usage across every client in one call, for billing |
| GET | /reseller/proxies | Your static proxies. ?filter=free, ?type=ipv4 |
| GET | /reseller/clients/{id}/proxies | The proxies pinned to one client, with credentials |
| POST | /reseller/clients/{id}/proxies | Pin static proxies to a client |
| DELETE | /reseller/clients/{id}/proxies | Unpin 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/usageStatic 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>/proxiesNotes 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 carriesreadyInSecondsso you can delay showing them to your user. - ·`rotation`:
-1holds a sticky session,0gives 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.
- ·
assignedreports 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 againstrequestedif you need to react.
MCP server - buy proxies from Claude & AI agents
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)
- Open app.sotaproxy.com/api (the API item in the dashboard sidebar).
- Under Create new key, select both scopes -
readandtrade- and click Create key. - 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.
- In Claude, open Settings → Connectors.
- Click Add custom connector.
- Name:
SotaProxy. URL - paste this (with your key inside):
https://api.sotaproxy.com/mcp?key=sk_live_YOUR_KEY- Click Add. In a new chat, open the tools menu (the sliders icon) and make sure SotaProxy is enabled.
- 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.
- 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"- Start (or restart)
claudeand ask: “What’s my SotaProxy balance?” - To remove later:
claude mcp remove sotaproxy.
Option C - Cursor and other MCP clients
- In Cursor: Settings → MCP → Add new global MCP server (this opens
~/.cursor/mcp.json). - Paste this block (or merge it into the existing
mcpServersobject):
{
"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.