Workspaces

Four endpoints. Workspaces are the billed unit, so creating and removing them changes what you pay.

A workspace owns a set of proxy assignments and their credentials. Your plan defines how many IPs each workspace gets; the number of workspaces defines how many seats you pay for. Separating traffic by workspace is how you keep one project's IPs from mixing with another's.

List workspaces

GET /workspaces

Every workspace in your organization.

Returns all workspaces, including those still provisioning. Not paginated — the list is bounded by your plan, so everything comes back in one response.

Example request

cURL
curl https://api.proxycharm.com/api/v1/public/workspaces \
  -H "Authorization: Bearer $PROXYCHARM_API_KEY"

Example response

200 OK
{
  "success": true,
  "data": [
    {
      "id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c",
      "name": "Scraper US",
      "address": "500 W Madison St, Chicago, IL",
      "country": "US",
      "status": "active"
    },
    {
      "id": "5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e",
      "name": "Scraper EU",
      "address": null,
      "country": "DE",
      "status": "pending_provision"
    }
  ],
  "error": null,
  "context": {
    "affected_entities": [],
    "suggested_next_actions": [
      "get_organization",
      "list_proxies"
    ],
    "warnings": []
  },
  "request_id": null,
  "timestamp": "2026-02-18T09:31:04.512Z"
}

Response fields

Name Type Description
(array) array<object> data is the array itself, not an object wrapping it.
id string Workspace id. Use this wherever an endpoint takes {account_id}.
name string Display name you chose for the workspace.
address string | null Optional operating address recorded for the workspace.
country string | null Optional ISO 3166-1 alpha-2 country the workspace operates from.
status string Lifecycle state. pending_payment is awaiting checkout, pending_provision is paid but waiting for an IP, active has live proxies, removed is retired.

Errors

Code HTTP What it means
API_KEY_INVALID 401 The Authorization header is missing the key prefix, the key does not exist, or its organization has been deleted.
API_KEY_REVOKED 401 The key was revoked in the dashboard.
API_KEY_EXPIRED 401 The key passed the expiry date it was created with.
RATE_LIMIT_EXCEEDED 429 The key exceeded its request budget for the current window.

Get workspace

GET /workspaces/{account_id}

Read one workspace by id.

Returns a single workspace. Requesting a workspace from another organization returns HTTP 403 rather than 404, so a caller cannot use this endpoint to probe for ids that exist elsewhere.

Path parameters

Name Type Description
account_id Required string Workspace id, from GET /workspaces or GET /organization.

Example request

cURL
curl https://api.proxycharm.com/api/v1/public/workspaces/3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c \
  -H "Authorization: Bearer $PROXYCHARM_API_KEY"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c",
    "name": "Scraper US",
    "address": "500 W Madison St, Chicago, IL",
    "country": "US",
    "status": "active"
  },
  "error": null,
  "context": {
    "affected_entities": [],
    "suggested_next_actions": [
      "list_workspaces",
      "get_workspace_proxies"
    ],
    "warnings": []
  },
  "request_id": null,
  "timestamp": "2026-02-18T09:31:04.512Z"
}

Response fields

Name Type Description
id string Workspace id. Use this wherever an endpoint takes {account_id}.
name string Display name you chose for the workspace.
address string | null Optional operating address recorded for the workspace.
country string | null Optional ISO 3166-1 alpha-2 country the workspace operates from.
status string Lifecycle state. pending_payment is awaiting checkout, pending_provision is paid but waiting for an IP, active has live proxies, removed is retired.

Errors

Code HTTP What it means
ORGANIZATION_PERMISSION_DENIED 403 The workspace id in the path belongs to another organization, or the profile that created the key is not an owner. Invoices require owner-level access.
API_KEY_INVALID 401 The Authorization header is missing the key prefix, the key does not exist, or its organization has been deleted.
API_KEY_REVOKED 401 The key was revoked in the dashboard.
API_KEY_EXPIRED 401 The key passed the expiry date it was created with.
RATE_LIMIT_EXCEEDED 429 The key exceeded its request budget for the current window.

Add workspace

POST /workspaces

Create a workspace, taking an open seat or adding a paid one.

Adds a workspace to the organization. If your subscription has an open seat, the new workspace fills it at no extra cost. If not, a seat is added and charged pro rata. The workspace comes back as pending_provision and becomes active once its IPs are assigned, usually within a few minutes.

Request body

Name Type Description
name Required string Display name for the workspace.
slots Required array<object> One entry per IP the plan includes. Each entry is an object with a country key: an ISO 3166-1 alpha-2 code, or null for any country. Send exactly subscription.plan.ip_count entries or you get SLOT_COUNT_MISMATCH.
address Optional string | null Operating address to record against the workspace.
country Optional string | null ISO 3166-1 alpha-2 country the workspace operates from. Unrelated to the exit country, which comes from slots.
idempotency_key Optional string | null Unique value that makes retries safe. Retrying with the same key returns the original workspace instead of creating a second one.

Example request

cURL
curl https://api.proxycharm.com/api/v1/public/workspaces \
  -X POST \
  -H "Authorization: Bearer $PROXYCHARM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "name": "Scraper EU",
       "slots": [
         {
           "country": "DE"
         }
       ],
       "country": "DE",
       "idempotency_key": "6f9619ff-8b86-d011-b42d-00c04fc964ff"
     }'

Example response

200 OK
{
  "success": true,
  "data": {
    "account_id": "5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e",
    "subscription": {
      "id": "7a2e4c19-3d5b-4f8a-9e6c-1b0d2f4a6c8e",
      "status": "active",
      "plan": {
        "id": "1f3a5c79-2b4d-4e6f-8a0c-3d5e7f9a1b2c",
        "name": "Starter",
        "ip_count": 1,
        "interval": "month",
        "amount_cents": 1200,
        "currency": "usd",
        "amount_display": "12.00 USD",
        "active": true,
        "popular": true
      },
      "slots": [
        {
          "slot_index": 0,
          "country": "US",
          "status": "assigned",
          "assignment_id": "9c1f7a2e-4b5d-4c3a-8e11-2d7b6f0a91c4",
          "account_id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c"
        },
        {
          "slot_index": 1,
          "country": "DE",
          "status": "pending",
          "assignment_id": null,
          "account_id": "5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e"
        }
      ],
      "current_period_end": "2026-03-18T09:00:00Z",
      "cancel_at_period_end": false,
      "payment_action_required": false,
      "pending_change": null,
      "paid_seat_count": 2,
      "open_seats": 0,
      "accounts": [
        {
          "account_id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c",
          "name": "Scraper US",
          "status": "active",
          "slots": [
            {
              "slot_index": 0,
              "country": "US",
              "status": "assigned",
              "assignment_id": "9c1f7a2e-4b5d-4c3a-8e11-2d7b6f0a91c4",
              "account_id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c"
            }
          ]
        },
        {
          "account_id": "5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e",
          "name": "Scraper EU",
          "status": "pending_provision",
          "slots": [
            {
              "slot_index": 1,
              "country": "DE",
              "status": "pending",
              "assignment_id": null,
              "account_id": "5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e"
            }
          ]
        }
      ]
    }
  },
  "error": null,
  "context": {
    "affected_entities": [
      "account:5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e"
    ],
    "suggested_next_actions": [
      "list_workspaces",
      "get_subscription"
    ],
    "warnings": []
  },
  "request_id": null,
  "timestamp": "2026-02-18T09:31:04.512Z"
}

Response fields

Name Type Description
account_id string Id of the workspace that was created or reused.
subscription object The subscription after the change, so you can see the new seat count without a second call.
id string Subscription id.
status string One of incomplete, active, past_due, canceling, canceled, unpaid. Only active accepts workspace changes.
plan object The plan this subscription is on.
id string Plan id.
name string Plan name as shown on the pricing page.
ip_count integer IPs included per workspace. POST /workspaces must send exactly this many slots.
interval string Billing interval: month or year.
amount_cents integer Price per interval in minor units.
currency string Lowercase ISO 4217 currency code.
amount_display string Pre-formatted price, e.g. 12.00 USD.
active boolean False when the plan is archived from new checkouts.
popular boolean True for the featured plan at this interval.
slots array<object> Every IP slot across the subscription, flattened.
slot_index integer Zero-based index of the IP slot within the subscription.
country string | null Requested ISO 3166-1 alpha-2 country, or null for any country.
status string pending while awaiting an IP, assigned once filled, dropped when released.
assignment_id string | null Assignment holding this slot, once one is assigned.
account_id string | null Workspace this slot belongs to.
current_period_end string | null ISO timestamp when the current period ends.
cancel_at_period_end boolean True when cancellation is scheduled for the period boundary.
payment_action_required boolean True when the cardholder must complete an authentication step.
pending_change object | null A plan change awaiting payment. While this is non-null, POST /workspaces returns ADD_ACCOUNT_PENDING.
plan_id string Plan the subscription is moving to.
add_slots array<object> Slot countries being added.
drop_slot_indexes array<integer> Slot indexes being released.
accounts array<object> Per-workspace add and drop intent.
paid_seat_count integer Number of workspaces you are paying for.
open_seats integer Paid seats with no workspace attached. While this is above zero, POST /workspaces fills a seat you already pay for instead of charging you again.
accounts array<object> Billed workspaces on this subscription, each with its own slots.
account_id string Workspace id.
name string Workspace display name.
status string Workspace lifecycle state.
slots array<object> Slots belonging to this workspace.
slot_index integer Zero-based index of the IP slot within the subscription.
country string | null Requested ISO 3166-1 alpha-2 country, or null for any country.
status string pending while awaiting an IP, assigned once filled, dropped when released.
assignment_id string | null Assignment holding this slot, once one is assigned.
account_id string | null Workspace this slot belongs to.

Errors

Code HTTP What it means
ACCOUNT_NAME_INVALID 200 The workspace name is empty or longer than the allowed length.
ACCOUNT_ADDRESS_INVALID 200 The address exceeds the allowed length.
ACCOUNT_COUNTRY_INVALID 200 The workspace country is not a two-letter ISO code.
SLOT_INVALID_COUNTRY 200 A slot entry was not an object, or its country was not a two-letter ISO code.
SLOT_COUNT_MISMATCH 200 The number of slots you sent does not match the IPs per workspace on your plan.
SUBSCRIPTION_NOT_ACTIVE 200 There is no live subscription, or it has not finished checkout.
SUBSCRIPTION_PAST_DUE 200 A payment failed, so seat changes are blocked.
SUBSCRIPTION_CANCELING 200 The plan is set to end at the period boundary.
ADD_ACCOUNT_PENDING 200 A plan change is still confirming payment.
ADD_ACCOUNT_CONFLICT 200 Another seat change for the same organization was in flight, so this one lost the race.
ADD_ACCOUNT_FAILED 200 The workspace could not be created — commonly because the idempotency key you sent already belongs to another organization's workspace.
STRIPE_CUSTOMER_MISSING 200 The organization has no billing customer, so a paid seat cannot be charged.
PLAN_NOT_FOUND 200 The plan behind the live subscription could not be loaded.
API_KEY_INVALID 401 The Authorization header is missing the key prefix, the key does not exist, or its organization has been deleted.
API_KEY_REVOKED 401 The key was revoked in the dashboard.
API_KEY_EXPIRED 401 The key passed the expiry date it was created with.
RATE_LIMIT_EXCEEDED 429 The key exceeded its request budget for the current window.

Remove workspace

DELETE /workspaces/{account_id}

Retire a workspace and release its IPs.

Marks the workspace removed and releases the IPs held by its slots. Returns the subscription after the change. The seat stays paid for the rest of the period and shows up as an open seat, so you can attach a new workspace to it without paying twice.

Path parameters

Name Type Description
account_id Required string Workspace id to remove.

Example request

cURL
curl https://api.proxycharm.com/api/v1/public/workspaces/5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e \
  -X DELETE \
  -H "Authorization: Bearer $PROXYCHARM_API_KEY"

Example response

200 OK
{
  "success": true,
  "data": {
    "subscription": {
      "id": "7a2e4c19-3d5b-4f8a-9e6c-1b0d2f4a6c8e",
      "status": "active",
      "plan": {
        "id": "1f3a5c79-2b4d-4e6f-8a0c-3d5e7f9a1b2c",
        "name": "Starter",
        "ip_count": 1,
        "interval": "month",
        "amount_cents": 1200,
        "currency": "usd",
        "amount_display": "12.00 USD",
        "active": true,
        "popular": true
      },
      "slots": [
        {
          "slot_index": 0,
          "country": "US",
          "status": "assigned",
          "assignment_id": "9c1f7a2e-4b5d-4c3a-8e11-2d7b6f0a91c4",
          "account_id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c"
        }
      ],
      "current_period_end": "2026-03-18T09:00:00Z",
      "cancel_at_period_end": false,
      "payment_action_required": false,
      "pending_change": null,
      "paid_seat_count": 1,
      "open_seats": 0,
      "accounts": [
        {
          "account_id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c",
          "name": "Scraper US",
          "status": "active",
          "slots": [
            {
              "slot_index": 0,
              "country": "US",
              "status": "assigned",
              "assignment_id": "9c1f7a2e-4b5d-4c3a-8e11-2d7b6f0a91c4",
              "account_id": "3b7d2c48-6e19-4a5f-8b0c-9d1e2f3a4b5c"
            }
          ]
        }
      ]
    }
  },
  "error": null,
  "context": {
    "affected_entities": [
      "account:5d9f4e6a-8c2b-4713-9e5d-0f1a2b3c4d5e",
      "subscription:7a2e4c19-3d5b-4f8a-9e6c-1b0d2f4a6c8e"
    ],
    "suggested_next_actions": [],
    "warnings": []
  },
  "request_id": null,
  "timestamp": "2026-02-18T09:31:04.512Z"
}

Response fields

Name Type Description
subscription object | null The live subscription, or null when the organization has none.
id string Subscription id.
status string One of incomplete, active, past_due, canceling, canceled, unpaid. Only active accepts workspace changes.
plan object The plan this subscription is on.
id string Plan id.
name string Plan name as shown on the pricing page.
ip_count integer IPs included per workspace. POST /workspaces must send exactly this many slots.
interval string Billing interval: month or year.
amount_cents integer Price per interval in minor units.
currency string Lowercase ISO 4217 currency code.
amount_display string Pre-formatted price, e.g. 12.00 USD.
active boolean False when the plan is archived from new checkouts.
popular boolean True for the featured plan at this interval.
slots array<object> Every IP slot across the subscription, flattened.
slot_index integer Zero-based index of the IP slot within the subscription.
country string | null Requested ISO 3166-1 alpha-2 country, or null for any country.
status string pending while awaiting an IP, assigned once filled, dropped when released.
assignment_id string | null Assignment holding this slot, once one is assigned.
account_id string | null Workspace this slot belongs to.
current_period_end string | null ISO timestamp when the current period ends.
cancel_at_period_end boolean True when cancellation is scheduled for the period boundary.
payment_action_required boolean True when the cardholder must complete an authentication step.
pending_change object | null A plan change awaiting payment. While this is non-null, POST /workspaces returns ADD_ACCOUNT_PENDING.
plan_id string Plan the subscription is moving to.
add_slots array<object> Slot countries being added.
drop_slot_indexes array<integer> Slot indexes being released.
accounts array<object> Per-workspace add and drop intent.
paid_seat_count integer Number of workspaces you are paying for.
open_seats integer Paid seats with no workspace attached. While this is above zero, POST /workspaces fills a seat you already pay for instead of charging you again.
accounts array<object> Billed workspaces on this subscription, each with its own slots.
account_id string Workspace id.
name string Workspace display name.
status string Workspace lifecycle state.
slots array<object> Slots belonging to this workspace.
slot_index integer Zero-based index of the IP slot within the subscription.
country string | null Requested ISO 3166-1 alpha-2 country, or null for any country.
status string pending while awaiting an IP, assigned once filled, dropped when released.
assignment_id string | null Assignment holding this slot, once one is assigned.
account_id string | null Workspace this slot belongs to.

Errors

Code HTTP What it means
ORGANIZATION_PERMISSION_DENIED 403 The workspace id in the path belongs to another organization, or the profile that created the key is not an owner. Invoices require owner-level access.
ACCOUNT_NOT_FOUND 200 The workspace was deleted between your read and your write.
ACCOUNT_NOT_REMOVABLE 200 The workspace is already removed, or is still confirming payment, so it is not in a removable state.
LAST_ACCOUNT_CANCEL_ONLY 200 You tried to remove the only live workspace on the plan.
SUBSCRIPTION_NOT_ACTIVE 200 There is no live subscription, or it has not finished checkout.
API_KEY_INVALID 401 The Authorization header is missing the key prefix, the key does not exist, or its organization has been deleted.
API_KEY_REVOKED 401 The key was revoked in the dashboard.
API_KEY_EXPIRED 401 The key passed the expiry date it was created with.
RATE_LIMIT_EXCEEDED 429 The key exceeded its request budget for the current window.