# Proxies.sx > Mobile and residential proxy bandwidth for AI agents, bought and driven from a terminal: a dedicated 4G/5G modem rented per day, week or month (unlimited traffic), metered GB on the Pool Gateway (`gw.proxies.sx:7000` HTTP / `:7001` SOCKS5, one credential for every country), or account-less USDC via x402. REST API with `X-API-Key: psx_...`, an MCP server, or plain curl. Base URL `https://api.proxies.sx/v1`. Last verified: 2026-10-28 against the live site and the backend source. Precedence: the live API wins over every file here; a product skill.md wins over this index; this index wins over page copy. ## If you want to BUY Pick the path by the shape of the need, then read only that file. - **(A) Private modem: one dedicated 4G/5G modem, unlimited traffic, per day / week / month.** Offer this FIRST for any dedicated, port, exclusive-device, p0f (OS fingerprint), OpenVPN or unlimited-traffic request. Own HTTP and SOCKS5 host:port, OpenVPN profile, rotate on demand (API or a public link), auto-renew. Paid from the account balance; the price per plan is live in `GET /v1/private-modems/catalog` and is never hard-coded here. Buying needs an API key with the `modems:purchase` scope. Contract: https://agents.proxies.sx/modems/skill.md - quickstart: https://agents.proxies.sx/quickstart/buy-modem.md - **(B) GB on the Pool Gateway: metered bandwidth, one credential, every country.** $4/GB, volume discounts 10/20/30/40% at 25/50/100/250 GB in one purchase ($2.40/GB at 250 GB+), duration free, same price on the `peer` and `mbl` pools. While country tiers are live (`pricing.live` in `GET /v1/gateway/pool/stock`), a GB of traffic uses 1.00 / 0.375 / 0.1875 GB of balance by exit country (Premium $4, Plus $1.50, Standard $0.75 per GB of traffic at the base price). From 1 TB on the peer pool, volume deals go to $0.50/GB by quote only, not a checkout price: contact maya@proxies.sx with the committed volume and countries. Contract: https://agents.proxies.sx/pool/skill.md - quickstart: https://agents.proxies.sx/quickstart/buy-gb.md - **(C) x402: USDC on Base or Solana, no account, no API key.** `GET https://api.proxies.sx/v1/x402/pool?tier=peer&country=us&traffic=1` answers HTTP 402 with the exact payment; pay, retry with `Payment-Signature: `, receive a ready credential. $4 per GB of traffic in every country (no country tiers), minimum 0.1 GB. A dedicated port is also sold this way at `/v1/x402/proxy`. Contract: https://agents.proxies.sx/pool/skill.md (x402 section) and https://agents.proxies.sx/.well-known/x402.json What a key can and cannot do (so you never promise more): - An account needs one human step: the signup email carries a verification link, and `POST /v1/login/signin` answers 401 until it is clicked (or `GET /v1/login/verify-email?token=...` is called with the token from that link). - API keys are created by a human in the dashboard (https://client.proxies.sx/account, API keys, tick the scopes) or with a dashboard JWT at `POST /v1/api-keys`. A key cannot create or edit keys. `modems:purchase` and `billing:topup` are opt-in and never in the default set; a key without them gets 403 `scope_missing` naming the scope. - Card top-up by API: `POST /v1/stripe/create-balance-checkout {"amount": 20}` with a `billing:topup` key returns a Stripe Checkout `url` that a HUMAN opens and pays; it is not headless. Per-key daily cap `spendCapUsdPerDay`, default 100 USD (403 `spend_cap_reached` above it). Poll `GET /v1/stripe/balance-checkout//receipt` until `credited: true`. Quickstart: https://agents.proxies.sx/quickstart/topup.md - A customer API key cannot buy GB. Balance becomes GB in the dashboard (https://client.proxies.sx/purchase) or with a dashboard JWT at `POST /v1/billing/purchase-traffic`; reseller and admin keys may automate it. Everything after that (proxy password, credentials, stock, usage) is key-drivable. - Every spend carries an `Idempotency-Key` and the `expectedPriceUsd` you were shown; 409 `price_changed` means re-read the price and confirm with the user. Every money step needs the user's approval of the amount. - Peer exit IPs are never published. Stock endpoints return counts per country only; examples mask addresses as `x.x`. ## Prices and errors (machine-readable) - [pricing.json](https://agents.proxies.sx/pricing.json): the GB price table generated from the backend source (base price, volume tiers, country tiers, the 1 TB quote line, payment routes), in the shape of the live `GET https://api.proxies.sx/v1/pricing`, which wins when they disagree - [Live pool stock and country tiers](https://api.proxies.sx/v1/gateway/pool/stock): counts per pool and country plus the `pricing` block (`live`, `basePricePerGB`, `volumeDiscounts`, `tiers[]` with `burnRate`, `pricePerGB`, `countries`), no auth, never an IP - [Live x402 pricing](https://api.proxies.sx/v1/x402/pricing): the $4/GB base and volume discounts for wallet purchases, no auth - [Error table](https://agents.proxies.sx/errors.md): every gateway `E_*` code, purchase-API code and the x402 402 body with HTTP status, meaning, exact fix and whether a retry helps ## Quickstarts (curl first, every step verified) - [Buy GB and connect](https://agents.proxies.sx/quickstart/buy-gb.md): sign up, verify the email, key, top up, buy GB in the dashboard, proxy password, connect through `gw.proxies.sx:7000` - [Rent a private modem](https://agents.proxies.sx/quickstart/buy-modem.md): catalog, quote, buy with `Idempotency-Key` and `expectedPriceUsd`, poll, connect, rotate, renew - [Top up the balance by API](https://agents.proxies.sx/quickstart/topup.md): checkout link, human pays, poll the receipt, balance credited - [Pool quickstart (HTML)](https://agents.proxies.sx/pool-quickstart.html): the shortest path to a working pool credential - [Rotation cookbook](https://agents.proxies.sx/pool/rotation-cookbook.md): copy-paste IP rotation in curl/python/node and the footguns that trip LLMs; read before writing rotation code ## Product contracts (one skill.md per product) - [Private modems](https://agents.proxies.sx/modems/skill.md): catalog, quote, buy, poll, credentials (HTTP, SOCKS5, OpenVPN), rotate, auto-rotate, renew, auto-renew, OS fingerprint, replace; page https://agents.proxies.sx/modems/ - [Pool Gateway](https://agents.proxies.sx/pool/skill.md): API-key path, deposited GB, country tiers, username DSL, stock, sessions, errors, the x402 alternative; page https://agents.proxies.sx/pool/ - [Dedicated port (legacy)](https://agents.proxies.sx/marketplace/skill.md): the older per-port modem pool (`POST /v1/ports`, `/v1/x402/proxy`) in US, GB, FR, NL, PL, GE (Georgia); nearly full, so start at https://agents.proxies.sx/modems/ - [Private Pool](https://agents.proxies.sx/private-pool/skill.md): named country-scoped credentials and Reserved IPs held exclusively for you - [Task market](https://agents.proxies.sx/tasks/skill.md): wallet-only x402 catalog of bounded egress tasks; the 402 response is the quote - [Master skill file](https://agents.proxies.sx/skill.md): the whole machine contract in one file (buy steps, x402 402 shape, username DSL, MCP catalog, peer protocol, compute, reseller keys) - [Agent research index](https://agents.proxies.sx/index.md): one screen, every page and which question it answers ## Use it from a tool - [MCP server](https://agents.proxies.sx/mcp/): `npx -y @proxies-sx/mcp-server` with `PROXIES_API_KEY=psx_...`. Version 3.1.0 (release pending; npm currently 3.0.1) exposes a default toolset of 20 tools: buy (`proxies_modem_catalog`, `proxies_modem_quote`, `proxies_modem_buy`, `proxies_modem_renew`, `proxies_topup_checkout`, `proxies_topup_status`, `get_pricing`), use (`pool_get_stock`, `pool_get_my_credentials`, `pool_build_proxy_url`, `pool_explain_error`, `proxies_modem_mine`, `proxies_modem_rotate`) and manage (account, usage, proxy password, status, tickets). The full set (96 API-key tools plus 16 wallet tools) loads with `--toolset=full` or `PROXIES_TOOLSET=full`. Wallet-only x402 mode with `AGENT_WALLET_KEY`. Call `tools/list` for the authoritative catalog. npm: https://www.npmjs.com/package/@proxies-sx/mcp-server - source: https://github.com/bolivian-peru/proxies-sx-mcp-server - [Integrations](https://agents.proxies.sx/integrations/skill.md): Playwright, browser-use, LangChain, CrewAI, n8n, Make/Zapier, OpenAI Agents SDK, Vercel AI SDK, Stagehand, CloakBrowser (https://agents.proxies.sx/integrations/cloakbrowser/) - [Pool Gateway Swagger](https://api.proxies.sx/docs/gateway): public OpenAPI for the gateway surface; the reseller API is at https://api.proxies.sx/v1/reseller/docs/openapi ## Gateway username (the thing agents get wrong) `psx_--[-rot-][-sid-]`, password = your proxy password (set once with `PATCH /v1/account/proxy-password`; the account login password is never accepted). `pool` is `peer` (flagship: residential and mobile, every country with stock), `mbl` (carrier modems in US, GB, FR, NL, PL, GE = Georgia; `mbl-de` always fails, use `peer-de`), `any` or `best`. `sticky` and `hard` pin the modem, not the IP; `sticky`/`auto*` need a `-sid-` to persist; unknown tokens are dropped silently (there is no `-session-` token). Limits: 500 concurrent connections and 250 sessions per account. ## Build and resell - [Build & resell](https://agents.proxies.sx/build/skill.md): mint per-customer `pak_` keys, set your own retail price, embed a dashboard or ship a storefront; kit https://github.com/bolivian-peru/proxy-reseller-kit, npm `@proxies-sx/pool-sdk` and `@proxies-sx/pool-portal-react` ## Bundles (one fetch) - [llms-full.txt](https://agents.proxies.sx/llms-full.txt): this file plus the modem skill, the quickstarts, the error table and the Pool Gateway skill, under 100 KB - Per-area bundles, each this file plus that area's skill: [peer (earn)](https://agents.proxies.sx/peer/llms-full.txt), [compute](https://agents.proxies.sx/compute/llms-full.txt), [build](https://agents.proxies.sx/build/llms-full.txt), [integrations](https://agents.proxies.sx/integrations/llms-full.txt), [dedicated port](https://agents.proxies.sx/marketplace/llms-full.txt), [private pool](https://agents.proxies.sx/private-pool/llms-full.txt), [tasks](https://agents.proxies.sx/tasks/llms-full.txt) ## Machine discovery - [x402 discovery](https://agents.proxies.sx/.well-known/x402.json): x402 services, wallets, pricing and management endpoints - [Agent card (A2A)](https://agents.proxies.sx/.well-known/agent-card.json): discovery-only card; act through the HTTP endpoints - [ERC-8004 registration](https://agents.proxies.sx/.well-known/erc8004-registration.json): on-chain agent registration record - [docs-manifest.json](https://agents.proxies.sx/docs-manifest.json): the numbers behind the docs - [Live status](https://api.proxies.sx/v1/x402/status): component health as JSON; human page https://agents.proxies.sx/status/ - [Sign up](https://client.proxies.sx/signup), [API keys](https://client.proxies.sx/account), [Buy GB](https://client.proxies.sx/purchase), [Private modems in the dashboard](https://client.proxies.sx/private-modems) ## Company - [About](https://agents.proxies.sx/about/), [Where our IPs come from](https://www.proxies.sx/where-our-ips-come-from), [Terms](https://www.proxies.sx/terms), [Privacy](https://www.proxies.sx/privacy) - [Contact](https://www.proxies.sx/contact): support and sales, maya@proxies.sx; [Telegram](https://t.me/proxies_sx); [X](https://x.com/sxproxies); [GitHub](https://github.com/bolivian-peru) ## Optional - [Earn: peer network](https://agents.proxies.sx/peer/skill.md): share bandwidth from consenting devices and get paid per GB; the live rate is `earningsPerGB` in the register response, never a hard-coded number. Go SDK 1.6.8 https://agents.proxies.sx/peer/go/ (Linux amd64 and arm64; Chinese steps https://agents.proxies.sx/peer/go/linux-zh.md), Node reference 1.6.6 https://agents.proxies.sx/peer/reference-sdk.js?v=1.6.6, Windows https://agents.proxies.sx/peer/windows/, Android https://github.com/bolivian-peru/android-peer-sdk (JitPack 1.3.2). Sign Partner Agreement 2.0 at https://farmer.proxies.sx/agreement first; devices are admitted only after approval (relay close 1013 until then). Payouts: https://farmer.proxies.sx/payouts. Supplier introductions carry no automatic commission. - [Mac compute](https://agents.proxies.sx/compute/skill.md): rent one approved Apple Silicon Mac for 30 days of inference (Starter 24 GB, Pro 48 GB, Max 96 GB; Qwen3.8 27B), or supply one. Early access, no SLA, no x402 checkout; purchases need `compute:purchase`, an `Idempotency-Key`, `expectedPriceUsd` and `pricingVersion`. Live tiers https://api.proxies.sx/v1/peer/compute/tiers, marketplace https://api.proxies.sx/v1/peer/compute/marketplace - [$SX token](https://agents.proxies.sx/sx-token/ecosystem.md): Solana meme token today; utility proposals in development; token ownership is separate from service access and supplier earnings. Overview https://agents.proxies.sx/sx-token/ - [Ground Truth](https://agents.proxies.sx/news/feed.md): source-backed research posts for agents (Atom: https://agents.proxies.sx/news/feed.xml). Latest: https://agents.proxies.sx/news/context-is-capacity/ - [Thesis](https://agents.proxies.sx/thesis/), [System map](https://agents.proxies.sx/system-map/), [Bot detection scanner](https://www.proxies.sx/tools/bot-detection-scanner), [Username builder](https://www.proxies.sx/tools/proxy-username-builder), [x402 SDK](https://github.com/bolivian-peru/x402-sdk) (`@proxies-sx/x402-core`, `-hono`, `-solana` 1.0.1; do not use 1.0.0), [@proxies-sx/lucid-agents](https://www.npmjs.com/package/@proxies-sx/lucid-agents), [Customer portal](https://client.proxies.sx) --- # Source: https://agents.proxies.sx/private-pool/skill.md # /private-pool - Proxies.sx Private Pool API > Programmatic control of a **Private Pool**: a scoped, named slice of the proxy network with its own credential, its own country list, and optional **Reserved IPs** - specific exit devices held for you alone so nobody else routes through them. > **Hierarchy:** this file is the canonical Private Pool API contract. If any other file disagrees with it, this file wins. If this file disagrees with the live API, the live API wins. **Base URL:** `https://api.proxies.sx/v1` **Auth:** every endpoint below takes an account API key. Both forms work: ```bash -H "X-API-Key: psx_YOUR_KEY" # or -H "Authorization: ApiKey psx_YOUR_KEY" ``` A browser-session JWT (`Authorization: Bearer `) works on the same routes. Mint an API key at https://client.proxies.sx/account or `POST /v1/api-keys`. Every route is owner-scoped: you only ever see and mutate your own pools. A pool id you do not own returns `404`, never another tenant's data. --- ## Is this the product you want? | | Pool Gateway | **Private Pool** | Dedicated Port | |---|---|---|---| | What you get | one credential over the whole network | a **named, country-scoped** credential + optional held IPs | one real modem on its own host:port | | Exit devices | shared | shared, or **Reserved (exclusive)** | exclusively yours | | Countries | any, per-request | the list you scope the pool to | one, fixed at purchase | | Price | balance $4.00/GB; a GB of traffic uses 1.00 / 0.375 / 0.1875 GB by exit country | the same balance and country rates when built from balance; raw GB against the pool's own cap when purchase-funded | $4.00/GB (1 GB of traffic = 1 GB) | | Docs | [/pool/skill.md](https://agents.proxies.sx/pool/skill.md) | this file | [/marketplace/skill.md](https://agents.proxies.sx/marketplace/skill.md) | Private Pool is the right choice when you want **separate credentials per project/customer** with their own usage series, or when you need **one exit device reserved exclusively** (Reserved IPs). > **Before you scope a pool to a country, check that country has real depth.** > `curl -s https://api.proxies.sx/v1/gateway/pool/stock` returns live endpoint counts per country. A country with a handful of endpoints will be unreliable no matter what you configure. This is the single most common cause of "my private pool does not work". --- ## Funding models A pool is funded one of two ways. **Which one you have changes what the credential meters against**, so read this before integrating. | | `fundingSource: "balance"` | `fundingSource: "purchase"` | |---|---|---| | Created by | `POST /private-pool/build-from-balance` | `POST /private-pool/requests` then `POST /:id/activate` | | Budget | your account's global GB balance | GB from the specific purchase claimed by that pool | | `credit.allocatedGB` | a display-only earmark (`dedicatedGb`) | the pak's hard cap | | Runs out when | your **account** GB hits zero | the pool's own cap is reached | On a balance-funded pool, `credit.allocatedGB` is a guide, not a separate bucket - the real gate is `credit.accountAvailableGB`. Meter against that. **Country tiers.** A balance-funded pool draws on the account balance at the country rate: a GB of traffic uses 1.00 GB of balance in a Premium country, 0.375 in Plus and 0.1875 in Standard ($4.00 / $1.50 / $0.75 per GB of traffic at the base price). A purchase-funded pool counts raw GB against its own cap in every country. The tier of each country is in the `pricing` block of `GET /v1/gateway/pool/stock`; fields and an example are in [/pool/skill.md](https://agents.proxies.sx/pool/skill.md#country-tiers-what-a-gb-of-traffic-costs). --- ## Quickstart ```bash KEY="psx_YOUR_KEY" # 1. list your pools (each with a ready-to-use connection block) curl -s https://api.proxies.sx/v1/private-pool/pools -H "X-API-Key: $KEY" # 2. reveal the pool's secret (audit-logged) curl -s -X POST https://api.proxies.sx/v1/private-pool/POOL_ID/reveal -H "X-API-Key: $KEY" # 3. connect - substitute the revealed pak_ as the password curl -x "http://psx_ACCOUNT-best-us-sid-pool01-rot-sticky:pak_SECRET@gw.proxies.sx:7000" \ https://api.ipify.org ``` `GET /pools` already returns `connection.strings[]` with a ready username per country - build from those rather than assembling the DSL yourself. --- ## Endpoints ### Read #### `GET /private-pool/pools` Every non-deleted pool you own, each with its live connection block. **This is the endpoint to poll.** ```jsonc [{ "pool": { "id": "6a6708230f7bd445c7077a8c", "label": "eu-scrapers", // null until you set one "poolType": "mbl" | "peer" | "any", "deviceCount": 10, "countries": ["US","GB","FR"], "allowedCountries": ["US","GB","FR"], // effective scope; null = flexible "requestedCountries": [], // pending additions, if any "qualityTier": "standard" | "safe", // 'safe' = carrier modems only "failoverDefault": "samecountry", "termMonths": 1, "purchasedGB": 50, "dedicatedGb": 20, // display earmark on balance-funded pools "fundingSource": "balance" | "purchase", "status": "requested" | "active" | "suspended" | "expired" | "cancelled", "expiresAt": "2026-08-27T00:00:00.000Z", "createdAt": "2026-07-27T07:26:27.000Z" }, "connection": { // null while status is 'requested' "host": "gw.proxies.sx", "httpPort": 7000, "socksPort": 7001, "proxyUsername": "psx_...", // the account id to authenticate as "poolToken": "best" | "mbl" | "peer", "countries": ["US","GB","FR"], "failoverDefault": "samecountry", "usernameTemplate": "psx_...-best-{country}[-sid-{name}][-rot-...]", "strings": [ { "country": "US", "username": "psx_...-best-us-sid-pool01-rot-sticky", "http": "http://psx_...-best-us-sid-pool01-rot-sticky:pak_********@gw.proxies.sx:7000" } ], "credit": { "allocatedGB": 20, "usedGB": 1.597, "remainingGB": 18.403, "expiresAt": null, "enabled": true, "note": "Draws from your account GB", // balance-funded only "accountAvailableGB": 18.4 // balance-funded only - THE REAL GATE }, "stockUrl": "https://api.proxies.sx/v1/gateway/pool/stock", "notes": ["..."] } }] ``` The password in `strings[].http` is masked as `pak_********`. Call `reveal` to get the real secret. #### `GET /private-pool/mine` The single most recent pool, same shape wrapped as `{ pool, connection }`. Returns `{"pool": null}` when you have none. Prefer `/pools`. #### `GET /private-pool/:id/usage` · `GET /private-pool/mine/usage` Per-day MB series for the pool. Query: `?days=30` (1-365, default 30). ```jsonc { "series": [{ "date": "2026-07-27", "mb": 412.5 }], "totalMB": 1634.2 } ``` #### `GET /private-pool/:id/sessions` Live gateway sessions currently open on this pool's credential. ```jsonc { "count": 3 } ``` Returns `{"count": 0}` on any gateway hiccup - it is a live indicator, never a blocker. ### Credential #### `POST /private-pool/:id/reveal` · `POST /private-pool/mine/reveal` Returns the full secret. **Audit-logged every time.** ```jsonc { "key": "pak_a1b2c3..." } ``` #### `POST /private-pool/:id/regenerate` · `POST /private-pool/mine/regenerate` Issues a new secret and **immediately invalidates the old one**. The username does not change, so only the password in your config needs updating. In-flight connections are not torn down; new connections with the old secret get `407`. ```jsonc { "key": "pak_NEW..." } ``` ### Create #### `POST /private-pool/build-from-balance` Creates **and activates** a pool funded by your existing account GB. No purchase needed. Rate limit: **5/min**. ```bash curl -s -X POST https://api.proxies.sx/v1/private-pool/build-from-balance \ -H "X-API-Key: $KEY" -H "Content-Type: application/json" \ -d '{"deviceCount": 10, "countries": ["US","GB"], "dedicateGB": 20}' ``` | field | type | notes | |---|---|---| | `deviceCount` | int | how many devices to spread across | | `countries` | string[] | ISO-2 codes; check stock depth first | | `dedicateGB` | int ≥1 | display earmark, **not** a hard cap | Requires some GB still available on the account, or `400`; `dedicateGB` is reduced to the whole GB you have. Returns the pool object (`status: "active"`). > Gated by a server flag. If the feature is off you get `503 Balance-funded pools are not available yet.` - use the request+activate path instead. #### `POST /private-pool/requests` → `POST /private-pool/:id/activate` The purchase-funded path. `requests` files the configuration (status `requested`, opens a ticket); `activate` claims a paid GB purchase made in the last 30 minutes and mints the credential. ```bash curl -s -X POST https://api.proxies.sx/v1/private-pool/requests \ -H "X-API-Key: $KEY" -H "Content-Type: application/json" \ -d '{"poolType":"mbl","deviceCount":10,"countries":["US","GB"]}' ``` A given purchase can fund exactly one pool - a second `activate` against the same purchase returns `404 No recent paid traffic purchase found to apply` (`400 This purchase was already applied to a private pool` when two calls race). ### Modify #### `POST /private-pool/:id/request-countries` Adds countries to the pool scope **instantly and free**. Widen-only: nothing is ever removed. ```bash -d '{"countries":["DE","NL"]}' ``` `400` if every country you list is already in scope. Returns the updated pool. #### `PATCH /private-pool/:id/label` ```bash -d '{"label":"eu-scrapers"}' ``` Sanitised to `[\w\s-]`, max 60 chars. #### `POST /private-pool/mine/custom-request` Files a support ticket for a custom build. `-d '{"text":"..."}'`, minimum 5 characters. #### `DELETE /private-pool/:id` Deletes one of your pools (live since 2026-10-12). The pool's key is disabled, the pool leaves `GET /private-pool/pools`, and its Reserved IPs are released by the next lease clean-up pass rather than in the same call. ```bash curl -s -X DELETE https://api.proxies.sx/v1/private-pool/POOL_ID -H "X-API-Key: $KEY" # -> { "deleted": true } ``` | status | when | |---|---| | `200` | `{ "deleted": true }` | | `400` | `invalid poolId`, or the pool is purchase-funded and has a key: `This pool holds prepaid GB. Contact support to remove it so the remaining GB is handled correctly.` | | `404` | `Private pool not found` - unknown id, already deleted, or not yours | A balance-funded pool holds no GB of its own, so deleting it costs nothing: the balance stays on the account. There is no undelete; build a new pool to get a new key. --- ## Reserved IPs (leases) A lease **holds one specific exit device for you exclusively** - no other customer is routed through it while the hold is valid. > A reservation pins a device, not an unchanging address. A carrier or ISP may change the same device’s exit IP without advance notice. Residential addresses are usually more stable, but are not guaranteed fixed. The rotation and failure-recovery settings below control device replacement; they do not prevent carrier IP changes. **Idle release is a hard rule.** A lease that carries no traffic for **24 hours** is released automatically, regardless of the idle window requested — the server clamps longer windows to 24 h. Every request through the lease resets the clock. **A lease also removes that device from your own shared-pool routing.** While you hold it, traffic on your account proxy password or on another pool's key will not select it; this pool's own key can still be routed to it without the pin, and the lease username (`-pin-lease-`) always reaches it. Hold devices you are actually using, and release the rest — an idle hold in a thin country starves your own shared traffic first. #### `GET /private-pool/:id/leases` Returns an object containing the currently active leases: ```jsonc { "enabled": true, "maxLeases": 500, "held": 1, "leases": [{ "leaseId": "l0123456789", "country": "US", "carrier": "Example carrier", "ipType": "residential", "city": null, "region": null, "failover": "strict", "idleTtlSec": 86400, "rotationMode": "off", "rotateCount": 0, "lastRotatedAt": null, "nextRotationEligibleAt": null, "observedIp": null, "deviceOnline": true, "lastSeenActiveAt": "2026-09-26T00:00:00.000Z", "rotationToken": "ROTATION_TOKEN", "rotateUrl": "https://api.proxies.sx/v1/private-pool-rotate/ROTATION_TOKEN", "strings": { "username": "psx_ACCOUNT-peer-us-sid-hold_l0123456789-pin-lease-l0123456789-rot-sticky-failover-strict", "http": "http://psx_ACCOUNT-peer-us-sid-hold_l0123456789-pin-lease-l0123456789-rot-sticky-failover-strict:pak_********@gw.proxies.sx:7000", "socks5": "socks5://psx_ACCOUNT-peer-us-sid-hold_l0123456789-pin-lease-l0123456789-rot-sticky-failover-strict:pak_********@gw.proxies.sx:7001" } }] } ``` `observedIp` is the last reported exit address, returned only to the pool owner while this exact lease holds an online device with a valid fence. It is `null` when unavailable; it is not a fresh request-level IP check, a promise that the address remains unchanged, or an advance-change signal. Never publish these addresses or send them to analytics. `lastRotatedAt` is also used as the schedule baseline when auto-rotation is enabled. Do not treat it as an IP-change timestamp. `nextRotationEligibleAt` is the earliest scheduled eligibility, not an exact promise: rotation runs on a later check while traffic is active and a matching replacement is available. It is `null` when scheduled rotation is off. #### `POST /private-pool/:id/leases` Acquires a lease. To request a residential device with no scheduled rotation and no automatic device replacement: ```json {"country":"us","ipType":"residential","failover":"strict","idleTtlSec":86400} ``` Acquisition starts with `rotationMode: "off"`. If `failover` is omitted, the pool default applies (normally `samecountry`), which permits automatic device replacement. Country, carrier, source, city and state narrow the requested stock. Acquisition fails with `409` if no matching device is free. Do not silently retry by widening the customer's requested scope. New leases retain the requested carrier and source for subsequent rotation and recovery. An explicit carrier remains required even with `samecountry` or `any` failure recovery. The lease list returns `carrierWant` and `sourceWant`; older leases may have no saved original selection and continue to use their existing failure policy. Do not infer a historical customer choice from the current device's carrier. An initial `source: "any"` search can choose either source, but replacement keeps the selected device source encoded in the copied credentials. #### `POST /private-pool/leases/:leaseId/rotate` Requests a different matching device now. The lease id and reservation handle stay the same. Reconnect your proxy client after rotation to use the replacement. Existing TCP tunnels may remain open until they close. No matching free replacement is a `409`, and keeps the existing reservation unchanged. #### `POST /private-pool/leases/:leaseId/extend` · `DELETE /private-pool/leases/:leaseId` Change the idle window with `{"idleTtlSec":86400}`, or release the hold. Idle windows range from 10 minutes to 24 hours; longer values are clamped to 24 hours. A manual release does not restart automatically. #### `PATCH /private-pool/leases/:leaseId/rotation-mode` Set cadence and, optionally, failure recovery on the same lease: ```json {"mode":"off","failover":"strict"} ``` - `mode`: `off`, `auto5`, `auto10`, `auto20`, or `auto60`. - `off`: no scheduled device changes; manual button/API rotation remains available. - `failover` is optional. Omission preserves the lease's existing policy. `strict` stops automatic substitution when the held device is unavailable. `samecountry` and `samecarrier` permit replacements within that scope. The legacy `any` and `samenode` values remain accepted. - `off` alone does **not** turn off automatic replacement allowed by the failover policy. - These settings do not detect or stop the same device's carrier/ISP changing its IP. Response: `{ "leaseId": "…", "rotationMode": "off", "failover": "strict", "nextRotationEligibleAt": null }`. Read the lease list back to confirm saved settings and copy its current connection string after a policy change. #### `POST /private-pool/leases/:leaseId/rotation-token` · `DELETE …` Regenerates (or revokes) the link for unauthenticated on-demand rotation. A new reservation already has one; `DELETE` it if you do not want such a link: ```bash curl -s https://api.proxies.sx/v1/private-pool-rotate/ROTATION_TOKEN ``` The response indicates whether rotation succeeded; do not assume a successful HTTP request means a device was changed. This is the **only** unauthenticated Private Pool endpoint. Treat the token as a secret; anyone holding it can request rotation. Regenerating or deleting it invalidates the old link. Do not call it as a health check or insert it as a proxy address. ### Importing a reservation into your tool 1. Read `leases[].strings` from the owner-authenticated list above. 2. Reveal the pool's secret once through `POST /private-pool/:poolId/reveal`, and replace only the `pak_********` password placeholder. 3. Import the complete HTTP or SOCKS5 string. Keep the returned `-sid-hold_…`, `-pin-lease-…`, rotation and failover tokens intact. Use port `7000` for HTTP or `7001` for SOCKS5. 4. The dashboard can copy URL, `host:port:user:pass`, `user:pass@host:port`, or `host:port@user:pass` formats using the same canonical string. The rotation link is separate and is called only when you intend to change devices. Use the API-returned reservation string instead of constructing a generic pool username. A generic string does not import the reservation or its controls. Use `-pin-lease-`, never a raw device pin, for a lease. Do not replace the canonical session ID with a new one for every request. --- ## Routing (username DSL) The password is the pak secret; everything else is declared in the username. Full cheatsheet: [/pool/skill.md](https://agents.proxies.sx/pool/skill.md#routing-parameters-username-dsl---full-cheatsheet). ``` psx_--[-sid-][-rot-][-pin-lease-][-failover-] ``` | token | values | notes | |---|---|---| | `pool` | `mbl` \| `peer` \| `best` \| `any` | `best` = modem-preferred with peer failover | | `country` | ISO-2 or `any` | keep it within the pool's scope | | `sid` | 1-64 chars | **required for stickiness to survive across connections** | | `rot` | `sticky` \| `auto5/10/20/60` \| `ondemand` \| `hard` | default `auto10` | | `failover` | `any` \| `samecountry` \| `samecarrier` \| `samenode` \| `strict` | default `samecountry` | **Two footguns that account for most "it does not work" reports:** 1. `-sid-` alone is **not** sticky. Stickiness needs `-rot-sticky` **and** a `-sid-`. Without a `-sid-` every connection gets a fresh throwaway session. 2. `-session-` is **not** a real token. It is silently ignored. The token is `-sid-`. --- ## Errors | status | meaning | |---|---| | `400` | bad input, or the action is not applicable (already-claimed purchase, countries already in scope, insufficient account GB, deleting a purchase-funded pool) | | `401` | missing/invalid API key | | `404` | pool or lease not found **or not owned by you**; no recent unclaimed purchase to activate | | `409` | no free matching device, lease limit reached, rotation cooldown or hourly rotation limit; the existing reservation is unchanged | | `429` | rate limited | | `503` | feature flag off, or a dependency (balance check) is unavailable - fail-closed by design | Gateway-side errors (returned as `CODE: message (req: uuid)` on the proxy connection, not this REST API): | code | meaning | |---|---| | `E_AUTH_INVALID` | wrong secret, or the key is disabled | | `E_CAP_EXCEEDED` | the pool's GB cap (or the owner's account balance) is exhausted | | `E_NO_STOCK_COUNTRY` | no live endpoints for that country - check `/gateway/pool/stock` | | `E_RATE_LIMITED_AUTH` | too many failed auths; back off, do not retry in a loop | --- ## Operational notes - **Rate limits (per minute):** `build-from-balance` 5, `reveal` and `regenerate` 30, reserve a lease 20, rotate a lease 10, rotation-token 20, the public rotation link 30 per IP. A lease also has a 10-second rotation cooldown and 30 rotations per hour (`409`). Other routes follow the standard API limits. - **Metering:** every byte is metered against the pool's budget. There is no separate per-pool invoice - it draws on the same GB you bought. - **Reveal is audited:** each `reveal` writes an audit record. Cache the secret in your own secret store rather than calling it per request. - **Exit IPs are not published:** the only address any endpoint here returns is `leases[].observedIp`, to the pool owner for a device that pool currently holds. Published exit IPs get burned by anti-bot IP-reputation systems, which would degrade the network for everyone. ## See also - [Pool Gateway](https://agents.proxies.sx/pool/skill.md) - the one-credential product and the full DSL - [Rotation Cookbook](https://agents.proxies.sx/pool/rotation-cookbook.md) - copy-paste rotation in curl/python/node - [Dedicated Port](https://agents.proxies.sx/marketplace/skill.md) - one modem, its own host:port - Live stock: `https://api.proxies.sx/v1/gateway/pool/stock`