{"openapi":"3.0.3","info":{"title":"Proxy4U Customer Proxy API","version":"1.0.0","description":"Use this API to manage wallet, packages, IPs, configuration, and usage.\n\nThere are **two credentials**. They are not interchangeable.\n\n---\n\n## Before you start \u2014 Get an API key\n\nThis is dashboard setup, not an API call.\n\n1. Open the **API Access** page.\n2. Generate an API key there.\n3. Copy it immediately. It is shown **once**.\n\nThis key looks like `p4u_...`. Keep it secret. It is **not** a Bearer token.\n\nYou can optionally lock the key to specific IPs. If you do, token requests and API calls from other IPs return `403`.\n\n---\n\n## Step 1 \u2014 Get a Bearer token\n\nAfter you have an API key, this is the first API call.\n\nCall **Authentication \u2192 Issue a Bearer access token** (`POST \/auth\/token`).\n\nSend JSON (no Authorization header):\n\n```json\n{\n  \"email\": \"you@example.com\",\n  \"api_key\": \"p4u_...\"\n}\n```\n\nThe response includes `data.access_token` (starts with `p4u_tok_`). **That value is the Bearer token.**\n\nThen click **Authorize** in this page and paste the access token, or send:\n\n```\nAuthorization: Bearer p4u_tok_...\n```\n\n## Step 2 \u2014 Call the proxy APIs\n\nUse this Bearer token on every authenticated endpoint.\n\n- The token lasts **12 hours**.\n- Requesting a new token **revokes** the previous one for the same API key.\n- Never send the API key (`p4u_...`) as Bearer. Only `\/auth\/token` accepts the API key.\n- `{proxy_user_id}` is `proxy_user_id` from package responses, not your account id.\n- Package responses include only customer-facing fields needed for API usage.\n\n## Errors\n\n```json\n{ \"message\": \"Human-readable reason.\" }\n```\n\n| Code | Meaning |\n| --- | --- |\n| `401` | Missing, invalid, or expired token (or bad email\/API key on `\/auth\/token`) |\n| `403` | IP not allowed or IP banned |\n| `422` | Invalid input or purchase rejected |\n| `429` | Rate limit exceeded |\n| `500` | Unexpected failure |\n\nRate limits (after a valid Bearer token): 60 requests\/minute per key, 1,000\/hour per key, 120\/minute per IP, 20 writes\/minute per key."},"servers":[{"url":"https:\/\/api.proxy4u.com\/api\/v1","description":"Proxy4U API v1"}],"tags":[{"name":"Authentication","description":"Step 1 after you have an API key: issue a 12-hour Bearer token. All other tags need that token."},{"name":"Wallet","description":"Read the USD wallet used by the purchase and top-up endpoints. Requires Bearer token."},{"name":"Purchases","description":"Buy a new package or top up an existing package. Requires Bearer token."},{"name":"Packages","description":"List and inspect packages. Requires Bearer token."},{"name":"Access control","description":"Allowed IPs and password reset for a package. Requires Bearer token."},{"name":"Locations","description":"Look up countries, states, cities, zipcodes, and ASNs for a pool type. Requires Bearer token."},{"name":"Configuration","description":"Default targeting, rotation, and threads. Requires Bearer token."},{"name":"Reports","description":"Plan statistics, plan history, error statistics, and usage statistics for a package. Requires Bearer token."}],"security":[{"BearerAuth":[]}],"paths":{"\/auth\/token":{"post":{"tags":["Authentication"],"operationId":"issueAccessToken","summary":"Issue a Bearer access token","description":"**This is Step 1** after you already have an API key. It returns the Bearer token used by every authenticated endpoint.\n\n### How to call it\n\n1. You already created an API key on the **API Access** page.\n2. Send this request **without** an Authorization header.\n3. Body: your account `email` and the plaintext `api_key` (`p4u_...`).\n4. Read `data.access_token` from the response (`p4u_tok_...`).\n5. Click **Authorize** and paste that access token. That is the Bearer token.\n\n### Notes\n\n- Token lifetime is **12 hours** (`expires_at` \/ `expires_in_seconds`).\n- A new token **revokes** the previous token for this API key.\n- If the key has an IP allowlist, this request must come from an allowed IP.\n- Do not put the API key in the Authorization header. The API key belongs only in this JSON body.","security":[],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TokenRequestPayload"},"example":{"email":"user@example.com","api_key":"p4u_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}}},"responses":{"200":{"description":"Token issued. Use `data.access_token` as the Bearer token.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TokenResponse"},"example":{"message":"success","data":{"token_type":"Bearer","access_token":"p4u_tok_xxxxxxxx","expires_at":"2026-08-22T07:00:00.000000Z","expires_in_seconds":43200,"user_api_key_id":12,"token_prefix":"p4u_tok_xxxxxxxx"}}}}},"401":{"description":"Email and API key do not match, or the key does not belong to that user.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Invalid credentials."}}}},"403":{"description":"This IP is not on the key allowlist, or it is banned.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"This IP is not allowed for the API key."}}}},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/wallet\/balance":{"get":{"tags":["Wallet"],"operationId":"getWalletBalance","summary":"Get wallet balance","description":"Returns the USD balance used to pay for `POST \/buy`.\n\nA missing wallet is treated as `0`.","responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Current wallet balance in USD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WalletBalanceResponse"},"example":{"message":"success","data":{"balance":125.5,"currency":"USD"}}}}}]}},"\/countries":{"get":{"tags":["Locations"],"operationId":"getCountries","summary":"Get countries","description":"Returns available countries and IP counts for one package type.\n\nThis is the first location lookup. Use a `country_code` from this list as `countries` on **states**, **cities**, **zipcodes**, and **asns**.","parameters":[{"name":"package","in":"query","required":true,"description":"Package type to fetch countries for.","schema":{"type":"string","enum":["residential","datacenter","mobile"],"example":"residential"}}],"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Available countries for the requested package type.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ProxyLocationListResponse"},"example":{"message":"success","data":[{"country_code":"US","country_name":"United States","count":152340,"package":"residential"},{"country_code":"GB","country_name":"United Kingdom","count":45210,"package":"residential"}]}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/states":{"post":{"tags":["Locations"],"operationId":"getStates","summary":"Get states","description":"Returns states for the given countries.\n\nRequires `package` and `countries` (ISO country codes from `GET \/countries`).","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/StatesLookupPayload"},"example":{"package":"residential","countries":["US"]}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Matching states. Each item typically includes `name`, `code`, and `count`.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LocationOptionListResponse"},"example":{"message":"success","data":[{"name":"New York","code":"NY","count":12400}]}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/cities":{"post":{"tags":["Locations"],"operationId":"getCities","summary":"Get cities","description":"Returns cities for the given countries.\n\nRequires `package` and `countries`. Optionally pass `states` (codes from `POST \/states`) to narrow the list.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CitiesLookupPayload"},"example":{"package":"residential","countries":["US"],"states":["NY"]}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Matching cities. Each item typically includes `name`, `code`, and `count`.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LocationOptionListResponse"},"example":{"message":"success","data":[{"name":"New York","code":"NY","count":12400}]}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/zipcodes":{"post":{"tags":["Locations"],"operationId":"getZipcodes","summary":"Get zipcodes","description":"Returns zipcodes for the given countries.\n\nRequires `package` and `countries`. Optionally pass `states` and `cities` to narrow the list.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ZipcodesLookupPayload"},"example":{"package":"residential","countries":["US"],"states":["NY"],"cities":["newyork"]}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Matching zipcodes. Each item typically includes `name`, `code`, and `count`.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LocationOptionListResponse"},"example":{"message":"success","data":[{"name":"New York","code":"NY","count":12400}]}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/asns":{"post":{"tags":["Locations"],"operationId":"getAsns","summary":"Get ASNs","description":"Returns ASNs for the given countries.\n\nRequires `package` and `countries`. Optionally pass `states`, `cities`, and `zipcodes` to narrow the list.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AsnsLookupPayload"},"example":{"package":"residential","countries":["US"],"states":["NY"],"cities":["newyork"],"zipcodes":["10001"]}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Matching ASNs. Each item typically includes `name`, `code`, and `count`.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LocationOptionListResponse"},"example":{"message":"success","data":[{"name":"New York","code":"NY","count":12400}]}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/packages":{"get":{"tags":["Packages"],"operationId":"listPackages","summary":"List proxy packages","description":"Lists packages owned by the authenticated account.\n\nUse `proxy_user_id` from this list in later path parameters. This response does not include package passwords.","responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Owned packages.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PackageListResponse"}}}}]}},"\/buy":{"post":{"tags":["Purchases"],"operationId":"buyNewPackage","summary":"Buy a new package","description":"Requires a Bearer token from `POST \/auth\/token`.\n\nCharges the USD wallet and provisions traffic in **GB**.\n\nSend only `package` and `quantity`. A new package is created and attached to your account.\n\n```json\n{ \"package\": \"residential\", \"quantity\": 25 }\n```\n\n`quantity` is whole GB. Minimum purchase:\n\n| Package | Minimum |\n| --- | --- |\n| `residential` | 10 GB |\n| `mobile` | 5 GB |\n| `datacenter` | 10 GB |\n\nBelow the minimum returns `422`. Price is `unit_price \u00d7 quantity`, using this volume table:\n\n| Package | 1\u201399 GB | 100\u2013499 GB | 500+ GB |\n| --- | --- | --- | --- |\n| `residential` | $0.99 \/ GB | $0.85 \/ GB | $0.60 \/ GB |\n| `mobile` | $1.98 \/ GB | $1.70 \/ GB | $1.20 \/ GB |\n| `datacenter` | $0.49 \/ GB | $0.42 \/ GB | $0.30 \/ GB |\n\nOn success the wallet is already deducted. If provisioning fails, the debit is refunded and the API returns `422`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PurchasePayload"},"examples":{"buy_new_package":{"summary":"Buy a new residential package","value":{"package":"residential","quantity":25}}}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"New package purchased successfully.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PurchaseResponse"},"example":{"message":"success","data":{"session_id":"API-ABCDEF123","package":"residential","quantity":25,"unit_price":0.99,"total_price":24.75,"wallet_balance":{"balance":100.75,"currency":"USD"}}}}}},{"description":"Validation failed, quantity below the package minimum, insufficient wallet balance, or purchase could not be completed.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"examples":{"below_minimum":{"summary":"Quantity below package minimum","value":{"message":"Minimum purchase for residential is 10 GB.","errors":{"quantity":["Minimum purchase for residential is 10 GB."]},"data":{"package":"residential","quantity":3,"min_purchase":10,"unit":"GB"}}},"insufficient_balance":{"summary":"Wallet balance too low","value":{"message":"Insufficient wallet balance."}}}}}}]}},"\/packages\/{proxy_user_id}":{"get":{"tags":["Packages"],"operationId":"getPackage","summary":"Get package details and credentials","description":"Returns one owned package with current traffic and settings.\n\nThis response **includes `password`**. Treat it as a secret.","parameters":[{"$ref":"#\/components\/parameters\/ProxyUserId"}],"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Package details, including the current proxy password.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PackageDetailResponse"}}}},{"description":"Package not found for this user.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Package not found for this user."}}}},{"$ref":"#\/components\/responses\/ValidationError"}]},"post":{"tags":["Purchases"],"operationId":"topupPackage","summary":"Top up an existing package","description":"Requires a Bearer token from `POST \/auth\/token`.\n\nCharges the USD wallet and adds more traffic in **GB** to the package identified by `proxy_user_id`.\nThe `proxy_user_id` must belong to the authenticated user.\n\nSend `package` and `quantity` in the request body. The path parameter identifies which package to top up.\n\n```json\n{ \"package\": \"residential\", \"quantity\": 25 }\n```\n\n`quantity` is whole GB. Minimum purchase:\n\n| Package | Minimum |\n| --- | --- |\n| `residential` | 10 GB |\n| `mobile` | 5 GB |\n| `datacenter` | 10 GB |\n\nBelow the minimum returns `422`. Price is `unit_price \u00c3\u2014 quantity`, using this volume table:\n\n| Package | 1\u00e2\u20ac\u201c99 GB | 100\u00e2\u20ac\u201c499 GB | 500+ GB |\n| --- | --- | --- | --- |\n| `residential` | $0.99 \/ GB | $0.85 \/ GB | $0.60 \/ GB |\n| `mobile` | $1.98 \/ GB | $1.70 \/ GB | $1.20 \/ GB |\n| `datacenter` | $0.49 \/ GB | $0.42 \/ GB | $0.30 \/ GB |","parameters":[{"$ref":"#\/components\/parameters\/ProxyUserId"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TopupPayload"},"example":{"package":"residential","quantity":25}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Package top-up completed successfully.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PurchaseResponse"},"example":{"message":"success","data":{"session_id":"API-ABCDEF123","package":"residential","quantity":25,"unit_price":0.99,"total_price":24.75,"wallet_balance":{"balance":100.75,"currency":"USD"}}}}}},{"description":"Package not found for this user.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Package not found for this user."}}}},{"description":"Validation failed, quantity below the package minimum, package type mismatch, insufficient wallet balance, or top-up could not be completed.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"}}}}]},"delete":{"tags":["Packages"],"operationId":"hidePackage","summary":"Delete package","description":"Deletes the package from your package list.\n\nAfter success, the package is no longer returned by package list or package detail API calls.","parameters":[{"$ref":"#\/components\/parameters\/ProxyUserId"}],"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Package deleted successfully.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/HidePackageResponse"},"example":{"message":"success","data":{"proxy_user_id":12345,"hidden":true,"message":"Package deleted successfully."}}}}},{"description":"Package not found for this user.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Package not found for this user."}}}},{"description":"Password rotation failed before the package could be archived.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Failed to reset package password."}}}}]}},"\/packages\/allowed-ips":{"post":{"tags":["Access control"],"operationId":"addAllowedIp","summary":"Allow an IP on a package","description":"Adds an IPv4 or IPv6 address to the package allowlist. Clients connecting through this package may need to come from an allowed IP, depending on how the proxy is used.\n\n`ip` must be a valid IP address. Returns the updated package **without** password.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AllowedIpPayload"},"example":{"proxy_user_id":1382924,"ip":"203.0.113.10"}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"IP added. Updated package details are returned without the password.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PackageSummaryResponse"}}}},{"$ref":"#\/components\/responses\/ValidationError"},{"$ref":"#\/components\/responses\/ServerError"}]},"delete":{"tags":["Access control"],"operationId":"removeAllowedIp","summary":"Remove an allowed IP from a package","description":"Removes an IP from the package allowlist. Send the same JSON body as the add call (`{ \"proxy_user_id\": 1382924, \"ip\": \"...\" }`).\n\nSwagger\u2019s Try it out for DELETE still needs a request body with `ip`.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AllowedIpPayload"},"example":{"proxy_user_id":1382924,"ip":"203.0.113.10"}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"IP removed. Updated package details are returned without the password.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PackageSummaryResponse"}}}},{"$ref":"#\/components\/responses\/ValidationError"},{"$ref":"#\/components\/responses\/ServerError"}]}},"\/packages\/password\/reset":{"post":{"tags":["Access control"],"operationId":"resetPackagePassword","summary":"Reset package proxy password","description":"Rotates the proxy login password for this package.\n\nThe new password is returned in `data.password`. Update any clients that still use the old password.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PackageIdPayload"},"example":{"proxy_user_id":1382924}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Password reset completed. Updated package details include the new password.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PackageDetailResponse"}}}},{"$ref":"#\/components\/responses\/ServerError"}]}},"\/packages\/configuration":{"put":{"tags":["Configuration"],"operationId":"updatePackageConfiguration","summary":"Update targeting, rotation, and threads","description":"Sets default pool parameters for the package (geo targeting, ASN filters, rotation) and optionally `threads`.\n\nUse the same endpoint for both simple and detailed targeting.\n\n### Simple example\n\nCountry only:\n\n```json\n{\n  \"countries\": [\"US\"]\n}\n```\n\n### Detailed example\n\nCountry + state + city + zipcode + ASN:\n\n```json\n{\n  \"countries\": [\"US\"],\n  \"states\": [\"California\"],\n  \"cities\": [\"Los Angeles\"],\n  \"zipcodes\": [\"90001\"],\n  \"asns\": [\"AS15169\"],\n  \"anonymous_filter\": true,\n  \"rotation_interval\": 10,\n  \"threads\": 200\n}\n```\n\nCountry codes are short ISO-style strings such as `US`.\n`states`, `cities`, `zipcodes`, and `asns` are arrays. Send them only when you want more specific targeting.\n`threads` is a concurrent connection cap from `1` to `2000`. `rotation_interval` is in seconds (`0` or omit for sticky \/ default).\n\nReturns the updated package **without** password.\nYou can also set `custom_label` here to rename the package inside Proxy4U.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ConfigPayload"},"examples":{"country_only":{"summary":"Country only","value":{"proxy_user_id":1382924,"countries":["US"]}},"state_city_zip_asn":{"summary":"Country, state, city, zipcode, and ASN","value":{"proxy_user_id":1382924,"countries":["US"],"states":["California"],"cities":["Los Angeles"],"zipcodes":["90001"],"asns":["AS15169"],"anonymous_filter":true,"rotation_interval":10,"threads":200}}}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Configuration saved.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PackageSummaryResponse"}}}},{"$ref":"#\/components\/responses\/ValidationError"},{"$ref":"#\/components\/responses\/ServerError"}]}},"\/packages\/plan-stats":{"post":{"tags":["Reports"],"operationId":"getPlanStats","summary":"Get current plan statistics","description":"Returns current plan statistics for the package.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PlanStatsPayload"},"example":{"proxy_user_id":1382924}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Current plan statistics with package details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ReportResponse"}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/packages\/plan-stats-history":{"post":{"tags":["Reports"],"operationId":"getPlanStatsHistory","summary":"Get plan statistics history","description":"Returns plan statistics history for the package.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PlanStatsHistoryPayload"},"example":{"proxy_user_id":1382924,"group_type":"day"}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Plan history with package details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ReportResponse"}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/packages\/errors-stats":{"post":{"tags":["Reports"],"operationId":"getErrorsStats","summary":"Get error statistics","description":"Returns error statistics for the package.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorsStatsPayload"},"example":{"proxy_user_id":1382924,"groupby":"datetime,host","datetime_interval":"hour","limit":1000}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Error statistics with package details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ReportResponse"}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}},"\/packages\/usage-stats":{"post":{"tags":["Reports"],"operationId":"getUsageStats","summary":"Get usage statistics","description":"Returns usage statistics for the package.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UsageStatsPayload"},"example":{"proxy_user_id":1382924,"groupby":"domain","limit":1000}}}},"responses":[{"$ref":"#\/components\/responses\/Unauthorized"},{"$ref":"#\/components\/responses\/Forbidden"},{"$ref":"#\/components\/responses\/RateLimited"},{"description":"Usage statistics with package details.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ReportResponse"}}}},{"$ref":"#\/components\/responses\/ValidationError"}]}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Token","description":"Use the **access token** from Step 1 (`POST \/auth\/token`), not your API key.\n\n1. You already have an API key from the **API Access** page.\n2. Call `POST \/auth\/token` with `email` + `api_key`.\n3. Paste `data.access_token` here.\n\n```\nAuthorization: Bearer p4u_tok_xxxxxxxx\n```\n\nThe API key (`p4u_...`) is only for `\/auth\/token`. All other API calls use this Bearer token (`p4u_tok_...`)."}},"parameters":{"ProxyUserId":{"name":"proxy_user_id","in":"path","required":true,"description":"Package id (`proxy_user_id` from package responses). This is not your account id.","schema":{"type":"integer","example":12345}}},"schemas":{"ErrorMessage":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable error.","example":"Invalid credentials."},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Present on some 422 validation responses. Keys are field names."}}},"TokenRequestPayload":{"type":"object","required":["email","api_key"],"properties":{"email":{"type":"string","format":"email","description":"Proxy4U account email (case-insensitive).","example":"user@example.com"},"api_key":{"type":"string","description":"Plaintext API key from the API Access page. Shown only once at create\/regenerate time.","example":"p4u_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}},"TokenResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"type":"object","properties":{"token_type":{"type":"string","example":"Bearer"},"access_token":{"type":"string","description":"Send as `Authorization: Bearer <access_token>`."},"expires_at":{"type":"string","format":"date-time"},"expires_in_seconds":{"type":"integer","example":43200},"user_api_key_id":{"type":"integer"},"token_prefix":{"type":"string","description":"First characters of the token, for support\/debug."}}}}},"WalletBalance":{"type":"object","properties":{"balance":{"type":"number","format":"float","example":125.5},"currency":{"type":"string","example":"USD"}}},"WalletBalanceResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"$ref":"#\/components\/schemas\/WalletBalance"}}},"ProxyLocation":{"type":"object","properties":{"country_code":{"type":"string","example":"US"},"country_name":{"type":"string","example":"United States"},"count":{"type":"integer","example":152340},"package":{"type":"string","enum":["residential","datacenter","mobile"]}}},"ProxyLocationListResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/ProxyLocation"}}}},"LocationOption":{"type":"object","description":"A state, city, zipcode, or ASN returned by this lookup.","properties":{"name":{"type":"string","example":"New York"},"code":{"type":"string","example":"NY"},"count":{"type":"integer","example":12400}}},"LocationOptionListResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/LocationOption"}}}},"StatesLookupPayload":{"type":"object","required":["package","countries"],"properties":{"package":{"type":"string","enum":["residential","mobile","datacenter"]},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes from `GET \/countries`. Always send an array, even for one country: `[\"US\"]`. A single string such as `\"US\"` is also accepted.","example":["US"]}}},"CitiesLookupPayload":{"type":"object","required":["package","countries"],"properties":{"package":{"type":"string","enum":["residential","mobile","datacenter"]},"countries":{"type":"array","items":{"type":"string"},"example":["US"]},"states":{"type":"array","items":{"type":"string"},"description":"Optional state codes from `POST \/states`.","example":["NY"]}}},"ZipcodesLookupPayload":{"type":"object","required":["package","countries"],"properties":{"package":{"type":"string","enum":["residential","mobile","datacenter"]},"countries":{"type":"array","items":{"type":"string"},"example":["US"]},"states":{"type":"array","items":{"type":"string"},"example":["NY"]},"cities":{"type":"array","items":{"type":"string"},"example":["newyork"]}}},"AsnsLookupPayload":{"type":"object","required":["package","countries"],"properties":{"package":{"type":"string","enum":["residential","mobile","datacenter"]},"countries":{"type":"array","items":{"type":"string"},"example":["US"]},"states":{"type":"array","items":{"type":"string"},"example":["NY"]},"cities":{"type":"array","items":{"type":"string"},"example":["newyork"]},"zipcodes":{"type":"array","items":{"type":"string"},"description":"Optional zipcodes from `POST \/zipcodes`. `zip` is accepted as an alias.","example":["10001"]}}},"AllowedIpPayload":{"type":"object","required":["proxy_user_id","ip"],"properties":{"proxy_user_id":{"type":"integer","description":"Package id from the package list.","example":1382924},"ip":{"type":"string","description":"IPv4 or IPv6 address to add or remove.","example":"203.0.113.10"}}},"PackageIdPayload":{"type":"object","required":["proxy_user_id"],"properties":{"proxy_user_id":{"type":"integer","description":"Package id from the package list.","example":1382924}}},"PlanStatsPayload":{"type":"object","required":["proxy_user_id"],"properties":{"proxy_user_id":{"type":"integer","description":"Package id from the package list.","example":1382924}}},"PlanStatsHistoryPayload":{"type":"object","required":["proxy_user_id"],"properties":{"proxy_user_id":{"type":"integer","description":"Package id from the package list.","example":1382924},"from":{"type":"string","nullable":true,"description":"Optional range start.","example":"2026-08-01T00:00"},"to":{"type":"string","nullable":true,"description":"Optional range end.","example":"2026-08-27T23:59"},"group_type":{"type":"string","nullable":true,"enum":["minute","hour","day","month"],"description":"Grouping bucket.","example":"day"}}},"ErrorsStatsPayload":{"type":"object","required":["proxy_user_id"],"properties":{"proxy_user_id":{"type":"integer","description":"Package id from the package list.","example":1382924},"from":{"type":"string","nullable":true,"description":"Optional range start."},"to":{"type":"string","nullable":true,"description":"Optional range end."},"groupby":{"type":"string","nullable":true,"description":"Grouping fields such as `datetime,host`.","example":"datetime,host"},"datetime_interval":{"type":"string","nullable":true,"enum":["minute","hour","day","month"],"description":"Datetime bucket size.","example":"hour"},"limit":{"type":"integer","nullable":true,"minimum":1,"maximum":1000,"example":1000},"offset":{"type":"integer","nullable":true,"minimum":0,"example":0}}},"UsageStatsPayload":{"type":"object","required":["proxy_user_id"],"properties":{"proxy_user_id":{"type":"integer","description":"Package id from the package list.","example":1382924},"groupby":{"type":"string","nullable":true,"enum":["domain","session"],"description":"Group rows by `domain` or `session`.","example":"domain"},"from":{"type":"string","nullable":true,"description":"Optional range start."},"to":{"type":"string","nullable":true,"description":"Optional range end."},"limit":{"type":"integer","nullable":true,"minimum":1,"maximum":1000,"example":1000},"offset":{"type":"integer","nullable":true,"minimum":0,"example":0}}},"PurchasePayload":{"type":"object","required":["package","quantity"],"properties":{"package":{"type":"string","enum":["residential","mobile","datacenter"],"description":"Proxy pool type to purchase."},"quantity":{"type":"integer","minimum":5,"description":"Traffic in whole GB. Minimum 10 for residential and datacenter, 5 for mobile.","example":25}}},"TopupPayload":{"type":"object","required":["package","quantity"],"properties":{"package":{"type":"string","enum":["residential","mobile","datacenter"],"description":"Proxy pool type of the existing package."},"quantity":{"type":"integer","minimum":5,"description":"Traffic in whole GB. Minimum 10 for residential and datacenter, 5 for mobile.","example":25}}},"PurchaseResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"type":"object","properties":{"session_id":{"type":"string","description":"Internal purchase reference."},"package":{"type":"string"},"quantity":{"type":"integer"},"unit_price":{"type":"number","description":"USD per GB for this quantity tier."},"total_price":{"type":"number","description":"USD deducted from the wallet."},"wallet_balance":{"$ref":"#\/components\/schemas\/WalletBalance"}}}}},"ConfigPayload":{"type":"object","description":"Default pool targeting and package display settings. Use only `countries` for simple setup, or add `states`, `cities`, `zipcodes`, and `asns` for more specific targeting.","properties":{"proxy_user_id":{"type":"integer","description":"Package id from the package list.","example":1382924},"countries":{"type":"array","items":{"type":"string","maxLength":8},"description":"Country codes to include, e.g. `US`.","example":["US"]},"exclude_countries":{"type":"array","items":{"type":"string","maxLength":8},"description":"Country codes to exclude."},"custom_label":{"type":"string","nullable":true,"maxLength":255,"description":"Your own package name shown by Proxy4U.","example":"US residential pool"},"anonymous_filter":{"type":"boolean","description":"Prefer anonymous \/ low-detect IPs when true.","example":true},"exclude_asn":{"type":"array","items":{"type":"string","maxLength":50},"description":"ASNs to exclude."},"rotation_interval":{"type":"integer","minimum":0,"description":"IP rotation interval in seconds. `0` uses sticky \/ default.","example":10},"cities":{"type":"array","items":{"type":"string","maxLength":50},"description":"City names to include inside the selected countries or states."},"states":{"type":"array","items":{"type":"string","maxLength":50},"description":"State or region names to include inside the selected countries."},"zipcodes":{"type":"array","items":{"type":"string","maxLength":50},"description":"Zip or postal codes to include."},"asns":{"type":"array","items":{"type":"string","maxLength":50},"description":"ASNs to include, for example `AS15169`."},"threads":{"type":"integer","minimum":1,"maximum":10000,"description":"Max concurrent threads for the package.","example":2000}}},"Package":{"type":"object","description":"Package details exposed through the customer API.","properties":{"proxy_user_id":{"type":"integer","description":"Package id. Use this in path parameters.","example":12345},"custom_label":{"type":"string","nullable":true},"login":{"type":"string","description":"Proxy username."},"pool_type":{"type":"string","enum":["residential","mobile","datacenter"]},"balance":{"type":"integer","format":"int64","description":"Remaining traffic in bytes."},"balance_format":{"type":"string","description":"Human-readable remaining traffic, e.g. `25 GB`."},"threads":{"type":"integer"},"allowed_ips":{"type":"array","items":{"type":"string"}},"blocked_hosts":{"type":"array","items":{"type":"string"}},"default_pool_parameters":{"type":"object","additionalProperties":true,"description":"Current targeting \/ rotation defaults."}}},"PackageDetail":{"allOf":[{"$ref":"#\/components\/schemas\/Package"},{"type":"object","properties":{"password":{"type":"string","description":"Proxy password. Only on detail and password reset."}}}]},"PackageListResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Package"}}}},"PackageSummaryResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"$ref":"#\/components\/schemas\/Package"}}},"PackageDetailResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"$ref":"#\/components\/schemas\/PackageDetail"}}},"HidePackageResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"type":"object","properties":{"proxy_user_id":{"type":"integer","example":12345},"hidden":{"type":"boolean","example":true},"message":{"type":"string","example":"Package deleted successfully."}}}}},"ReportResponse":{"type":"object","properties":{"message":{"type":"string","example":"success"},"data":{"type":"object","properties":{"package":{"$ref":"#\/components\/schemas\/Package"},"data":{"description":"Report payload for this endpoint."}}}}}},"responses":{"Unauthorized":{"description":"Missing, invalid, or expired credentials.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Invalid or expired bearer token."}}}},"Forbidden":{"description":"The request IP is not on the API key allowlist, or the IP is banned.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"This IP is not allowed for the API key."}}}},"ValidationError":{"description":"Request body or query parameters failed validation.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"The given data was invalid."}}}},"RateLimited":{"description":"Too many requests. Back off and retry.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Rate limit exceeded."}}}},"ServerError":{"description":"Package lookup failed, or unexpected failure.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ErrorMessage"},"example":{"message":"Failed to fetch usage details."}}}}}}}