All systems operational · View status →
On this page

API reference

Generate proxies and manage your account programmatically over a simple REST API. Base URL https://resifactory.net/api/v1.

Overview

The ResiFactory REST API lets you generate proxy credentials, inspect account balances, and review recent usage — all from your own code, scripts, or CI pipelines.

Base URL

https://resifactory.net/api/v1

All endpoints are served under this path. /api/v1 is the current stable version — it will not receive breaking changes.

HTTPS only

All requests must be made over HTTPS. Plaintext HTTP connections are rejected. Your API key is transmitted in every request header; never send it over an unencrypted channel.

Machine-readable spec

The OpenAPI 3.1 spec is served at:

/api/v1/openapi.json

Import it into Postman, Insomnia, or any OpenAPI-compatible tool.

All request and response bodies are JSON (Content-Type: application/json). Responses always include a top-level key — either the resource payload or an error object. See Errors for the full error shape.

Authentication

Every request is authenticated with a bearer token. Keys are created in the Developer tab of your dashboard. The full secret is displayed exactly once at creation time — copy it immediately.

Sending the key

Authorization: Bearer rf_live_xxxxxxxxxxxxxxxxxxxx

API keys start with rf_live_. Never share or commit your secret key.

Best practices

One key per application

Create a separate key for each integration so you can revoke one without disrupting others. You can hold up to 10 keys at once.

Minimal scopes

Grant only the scopes the application actually needs. A scraper that only generates proxies does not need usage:read or pools:read.

Rotate & revoke promptly

Rotate keys periodically. If a key is leaked, revoke it immediately from the Developer tab of your dashboard. A revoked key returns 401 unauthorized instantly.

Never commit your API key to source control. Use environment variables or a secret manager (e.g. process.env.RF_API_KEY). If you accidentally push a key, revoke it immediately — git history is public.

Scopes

Each API key carries a set of scopes that control which endpoints it can call. Scopes are set at key creation and cannot be changed afterwards — create a new key if you need different permissions. Keys are created and revoked in the dashboard Developer tab; the API itself cannot mint or revoke keys (a leaked key can never create more). Pick the scopes a key needs at creation time — every key gets proxies:generate, usage:read, and pools:read by default.

Scope What it unlocks Default?
proxies:generate Call POST /proxies to generate proxy credentials. Yes
usage:read Call GET /balance and GET /usage to read account balances and domain-level usage. Yes
pools:read Call GET /pools to list accessible pools and valid targeting options. Yes

GET /me is accessible with any valid key regardless of scopes — it is a lightweight identity check.

Quickstart

Generate your first proxy list in under two minutes.

1

Create an API key

Log in → Dashboard → Developer. Click New key, give it a name, leave the default scopes, and copy the secret that appears. It will not be shown again.

2

Generate 10 US proxies

curl -X POST https://resifactory.net/api/v1/proxies \
  -H "Authorization: Bearer rf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country":"us","quantity":10}'
3

Read the response

The default format (list) returns a JSON object where proxies is a newline-delimited string of host:port:user:pass lines:

{
  "proxies": "proxy.resifactory.net:8000:user-country-us:pass\n...",
  "count": 10,
  "country": "us",
  "is_demo": false,
  "pool": "walmart_premium",
  "format": "list"
}
4

Paste into your tool

Split the string on \n and use each line as a proxy. Each entry is host:port:username:password. Most HTTP clients accept this format directly. Switch to "format":"json" if you prefer a structured array.

Endpoints

All endpoints are relative to https://resifactory.net/api/v1.

POST /proxies proxies:generate

Generate a list of proxy credentials. Accounts with zero balance receive non-working demo credentials and is_demo: true in the response.

Request body (JSON)

Field Type Required Notes
poolstringNoPool ID (e.g. walmart_premium). Omit to use your default pool. Call GET /pools for valid IDs.
countrystringNoISO 3166-1 alpha-2 country code in lowercase (e.g. us, gb, de).
quantityintegerNoNumber of proxy lines to return. Range: 1–250,000. Default: 5,000.
proxyTypestringNorotating | sticky | mobile_rotating | mobile_sticky. Default: rotating.
sessionDurationintegerNoSticky session lifetime in minutes. Range: 1–1,440 (24 h). Ignored for rotating types.
statestringNoUS state targeting (US only). Use the state abbreviation (e.g. CA, TX). Call GET /pools for valid values.
formatstringNolist | json | userpass. Default: list. See Output Formats.

Example request

curl -X POST https://resifactory.net/api/v1/proxies \
  -H "Authorization: Bearer rf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country":"us","quantity":100,"proxyType":"sticky","sessionDuration":30,"format":"json"}'

Success response (200)

{
  "proxies": [
    { "host": "proxy.resifactory.net", "port": 8000, "username": "user-country-us-session-abc123", "password": "secret" },
    ...
  ],
  "count": 100,
  "country": "us",
  "is_demo": false,
  "pool": "walmart_premium",
  "format": "json"
}

Relevant errors: unauthorized (401), insufficient_scope (403), account_disabled (403), pool_not_available (404), invalid_request (400), rate_limited (429).

GET /balance usage:read

Returns the remaining GB balance for each pool the caller can access. Balances are floats rounded to four decimal places.

Example request

curl -X GET https://resifactory.net/api/v1/balance \
  -H "Authorization: Bearer rf_live_YOUR_KEY"

Success response (200)

{
  "balances": {
    "walmart_premium": 12.5342,
    "retail_select": 6.0000
  }
}

Relevant errors: unauthorized (401), insufficient_scope (403), rate_limited (429).

GET /usage usage:read

Returns top domains by bandwidth usage for this account. Useful for auditing traffic distribution across targets.

Query parameters

Parameter Type Notes
limitintegerNumber of domains to return. Range: 1–100. Default: 25.

Example request

curl -X GET https://resifactory.net/api/v1/usage?limit=5 \
  -H "Authorization: Bearer rf_live_YOUR_KEY"

Success response (200)

{
  "top_domains": [
    { "domain": "walmart.com", "bytes": 1073741824, "requests": 45023 },
    { "domain": "target.com",  "bytes":  536870912, "requests": 22100 }
  ]
}

bytes is a raw integer (not formatted). Divide by 1,073,741,824 to convert to GB.

GET /pools pools:read

Returns all pools accessible by this API key, plus valid targeting values (countries, US states, session duration range, carriers). Always call this endpoint at startup to discover valid pool IDs and targeting options — do not hardcode them.

Example request

curl -X GET https://resifactory.net/api/v1/pools \
  -H "Authorization: Bearer rf_live_YOUR_KEY"

Success response (200)

{
  "pools": [
    {
      "id": "walmart_premium",
      "label": "Premium",
      "host": "proxy.resifactory.net",
      "proxy_types": ["rotating", "sticky"]
    }
  ],
  "targeting": {
    "countries": ["us", "gb", "de", "ca", "jp", "au"],
    "us_states": ["CA", "TX", "NY", "FL", "WA"],
    "session_minutes": { "min": 1, "max": 1440 },
    "carriers": []
  }
}
GET /me any valid key

Returns account identity and a summary of the current key. Use this as a lightweight health check to verify that a key is valid and to inspect its scopes at runtime.

Example request

curl -X GET https://resifactory.net/api/v1/me \
  -H "Authorization: Bearer rf_live_YOUR_KEY"

Success response (200)

{
  "id": 42,
  "username": "jane_doe",
  "scopes": ["proxies:generate", "usage:read", "pools:read"],
  "balances": { "walmart_premium": 12.5342 },
  "key": {
    "name": "My scraper",
    "prefix": "rf_live_",
    "last4": "x7kQ"
  }
}

Pools & Targeting

ResiFactory operates multiple proxy pools. Each pool has its own host, balance, and set of supported proxy types. Call GET /pools at startup to discover what is currently accessible — never hardcode pool IDs or targeting values.

Proxy types

  • rotating — New IP on every request. Ideal for large-scale scraping.
  • sticky — Same IP for a configurable session window (1–1,440 min).
  • mobile_rotating — Mobile carrier IPs, rotates per request.
  • mobile_sticky — Mobile carrier IPs with a session window.

Session duration

Applies only to sticky and mobile_sticky types. Value is in minutes.

  • Minimum: 1 minute
  • Maximum: 1,440 minutes (24 hours)
  • Default (if omitted): pool default

Rotating types silently ignore this field.

Geographic targeting

  • country — ISO 3166-1 alpha-2 (e.g. us, gb)
  • state — US only; pass two-letter abbreviation (e.g. CA, NY)

Valid values are returned dynamically by GET /pools.

Tip: State targeting (state) is only valid when country is us. Attempting invalid combinations returns 400 invalid_request.

Output Formats

The format field on POST /proxies controls how credentials are serialized in the response. Choose the format that best matches your tool's import requirements.

list (default)

proxies is a single newline-delimited string. Each line is host:port:username:password. Split on \n and filter empty strings.

"proxies": "proxy.resifactory.net:8000:user-s-abc:pass\nproxy.resifactory.net:8000:user-s-xyz:pass"

json

proxies is a JSON array of objects. Easiest to work with programmatically — each entry has host, port, username, and password fields.

"proxies": [
  {
    "host": "proxy.resifactory.net",
    "port": 8000,
    "username": "user-s-abc",
    "password": "pass"
  }
]

userpass

proxies is a newline-delimited string in user:pass@host:port format. Useful for tools that expect credentials before the host.

"proxies": "user-s-abc:[email protected]:8000\nuser-s-xyz:[email protected]:8000"

Rate Limits

Rate limits are enforced per API key over a rolling 60-second window. Different endpoint groups have separate limits so heavy proxy generation does not starve read endpoints.

Endpoint group Endpoints Limit
Generate POST /proxies 20 / min
Reads GET /balance, GET /usage, GET /pools, GET /me 120 / min

Response headers

Every response includes rate-limit headers so you can track consumption without hitting the limit:

Header Description
RateLimit-LimitMaximum requests allowed in the current window.
RateLimit-RemainingRequests remaining before you hit the limit.
RateLimit-ResetUnix timestamp at which the window resets.
Retry-AfterSeconds to wait before retrying. Present only on 429 responses.

Handling 429

When you receive a 429 rate_limited response, read the Retry-After header and wait that many seconds before retrying. Use exponential backoff with jitter for burst scenarios:

// Pseudo-code: exponential backoff with jitter
async function callWithBackoff(fn, maxAttempts = 5) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const result = await fn();
    if (result.status !== 429) return result;
    const retryAfter = parseInt(result.headers['retry-after'] || '1', 10);
    const jitter = Math.random() * 1000;
    await sleep((retryAfter * 1000 + jitter) * Math.pow(2, attempt));
  }
  throw new Error('Max retry attempts exceeded');
}

Errors

All error responses share a common envelope:

{
  "error": {
    "code": "insufficient_scope",
    "message": "This key does not have the proxies:generate scope."
  }
}
Error code HTTP status Meaning How to resolve
unauthorized 401 Missing, malformed, or revoked API key. Verify the Authorization header is present and starts with Bearer rf_live_. Regenerate the key if it was revoked.
account_disabled 403 Your account has been suspended. Contact support via Discord to investigate.
insufficient_scope 403 The key lacks the required scope for this endpoint. Create a new key with the required scope (scopes cannot be changed after creation).
pool_not_available 404 The specified pool ID does not exist or is not accessible by this key. Call GET /pools to get the current list of accessible pool IDs.
invalid_request 400 A request parameter is missing, out of range, or an invalid combination was provided. Read the message field for the specific issue. Check parameter types, ranges, and targeting constraints.
rate_limited 429 You have exceeded the rate limit for this endpoint group. Wait the number of seconds in the Retry-After header, then retry with exponential backoff.
internal_error 500 An unexpected server-side error occurred. Retry after a short delay. If the error persists, report it in our Discord support channel.

Code Examples

The two most common operations — generating proxies and reading balance. Switch the language tab to match your stack.

Generate proxies

curl -X POST https://resifactory.net/api/v1/proxies \
  -H "Authorization: Bearer rf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country":"us","quantity":50,"proxyType":"rotating","format":"json"}'

Read balance

curl -X GET https://resifactory.net/api/v1/balance \
  -H "Authorization: Bearer rf_live_YOUR_KEY"

Versioning & Changelog

The current API version is v1, served at /api/v1/. This path is frozen — no breaking changes will ever be made under /api/v1. A breaking change (removed field, changed semantics, altered authentication) will always ship under a new version path (e.g. /api/v2) with advance notice and a deprecation period.

What counts as breaking

  • Removing or renaming a response field
  • Changing a field's type
  • Changing an error code or HTTP status
  • Removing an endpoint
  • Requiring a new mandatory parameter

What is not breaking

  • Adding new optional response fields
  • Adding new optional request parameters
  • Adding new endpoints
  • Adding new error codes for new conditions

Spec

The OpenAPI 3.1 machine-readable spec is always up-to-date at:

/api/v1/openapi.json

Changelog

v1.0

Initial release · June 17, 2026

Five endpoints — POST /proxies (generation), GET /balance + GET /usage (usage reads), GET /pools (pool discovery), and GET /me (identity) — across three scopes: proxies:generate, usage:read, pools:read. API keys are created and revoked only from the dashboard Developer tab — the API never manages keys, so a leaked key can never mint another. Request examples ship in cURL, Python, JavaScript, and Go, alongside a machine-readable OpenAPI 3.1 spec.

FAQ

I called POST /proxies but got demo credentials back. What happened?

Your account balance is zero for the requested pool. The API returns non-working demo credentials and sets is_demo: true in the response rather than returning an error. Check the balance with GET /balance and top up from the dashboard. Once you have balance, subsequent calls return live credentials.

I'm getting 401 unauthorized even though I copied the key correctly.

The most common causes are: (1) the key was revoked from the dashboard; (2) there is whitespace or a newline appended to the key string; (3) the Authorization header value is missing the Bearer prefix (note the trailing space). Call GET /me as a quick sanity check — if it returns 401, the key is definitively invalid.

I'm getting 403 insufficient_scope. How do I fix it?

Scopes are baked into a key at creation time and cannot be changed. Create a new key with the required scope in the dashboard Developer tab. Check what scopes a key has using GET /me.

How do I handle 429 rate limit errors in production?

Read the Retry-After header from the 429 response — it tells you the exact number of seconds to wait. Implement exponential backoff with jitter: after the first 429, wait Retry-After seconds; after the second, wait double; and so on. For the proxy-generation endpoint (20/min limit), batching all required proxies into a single large POST /proxies call (up to 250,000 lines) is more efficient than many small calls.

My balance dropped unexpectedly. Can I see where the GB went?

Call GET /usage?limit=100 to see the top domains by byte consumption for your account. This gives a per-domain breakdown of traffic. If usage looks unexpected, check whether your proxy credentials have been shared or leaked — if so, revoke the affected key immediately and generate fresh credentials.

Do sticky sessions actually hold the same IP for the full duration?

Yes, for the duration you specify (1–1,440 minutes). Each unique username in the returned credential list corresponds to a pinned session. Requests made with the same username:password pair will exit from the same IP until the session expires. Once a session expires, the next request on that credential rotates to a new IP automatically.

Can I have more than 10 API keys?

No — the limit is 10 keys per account. If you hit the limit, delete unused keys from the dashboard Developer tab to free slots. If you have a legitimate need for more keys (e.g. many separate services), contact support via Discord.

Questions? Reach us on Discord, or grab the machine-readable OpenAPI spec.

Sign up — start in 60 seconds →