# Rotating sessions — PapaProxy.net API reference

Page: https://papaproxy.net/developers/reference/rotating-sessions.php
Last updated: November 9, 2026
Base URL: `https://papaproxy.net/account_new`. Authentication and conventions: https://papaproxy.net/developers/reference/

### Get rotating gateway settings

`GET /api/v1/customer/services/{service_id}/proxy/config`

- Access: API key required · scope `services:read`

Gateway hostnames and ports (HTTP, HTTPS, SOCKS5) of a rotating proxy service.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request examples:

cURL:

```bash
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/config" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/config",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/config", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/config');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/config", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Connection settings of a rotating proxy service.

Example response:

```json
{
  "endpoint": "papaproxy.pro",
  "endpoints": [
    "papaproxy.pro"
  ],
  "https_endpoints": [
    "eu01.gateway.example.com",
    "us01.gateway.example.com"
  ],
  "port": 3081,
  "http_ports": [
    3081,
    3082,
    3083,
    3084,
    3085,
    3086,
    3087,
    3088,
    3089,
    3090,
    3091,
    3092,
    3093,
    3094
  ],
  "socks_ports": [
    2081,
    2082,
    2083,
    2084,
    2085,
    2086,
    2087,
    2088,
    2089,
    2090,
    2091,
    2092,
    2093,
    2094
  ],
  "sticky_http": 5080,
  "sticky_socks5": 4080,
  "sticky_https": 4443,
  "session_format": "ip:port:username:password",
  "mode": "sticky",
  "sample_connection_string": "papaproxy.pro:3081:pp_user_3fa85f64:Xk9mQ2vL7pRt",
  "sample_connection_strings": [
    "papaproxy.pro:3081:pp_user_3fa85f64:Xk9mQ2vL7pRt"
  ]
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `endpoint` | string | yes |  |
| `endpoints` | array of string | no |  |
| `https_endpoints` | array of string | no |  |
| `port` | integer | yes |  |
| `http_ports` | array of integer | no | HTTP ports. |
| `socks_ports` | array of integer | no | SOCKS5 ports. |
| `sticky_http` | integer, nullable | no |  |
| `sticky_socks5` | integer, nullable | no |  |
| `sticky_https` | integer, nullable | no |  |
| `session_format` | string | no | Default: `"ip:port:username:password"` |
| `mode` | string | no | Default: `"rotating"` |
| `sample_connection_string` | string, nullable | no |  |
| `sample_connection_strings` | array of string | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:read`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:read"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### List sticky sessions

`GET /api/v1/customer/services/{service_id}/proxy/sticky/sessions`

- Access: API key required · scope `services:read`

List sticky sessions for a rotating proxy service.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request examples:

cURL:

```bash
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Active sticky sessions for a rotating service.

Example response:

```json
{
  "service_id": "3bd2e419-2dc6-52bb-9d74-0a4560d55f53",
  "username": "pp_user_3fa85f64",
  "sessions": []
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id` | string (uuid) | yes | ID of the service. |
| `username` | string | yes | Proxy username. |
| `sessions` | array of object | yes |  |
| `sessions[].sid` | string | yes | Sticky session ID. |
| `sessions[].session_id` | string | yes |  |
| `sessions[].server` | string | yes |  |
| `sessions[].exit` | string | yes | Exit IP of the session. |
| `sessions[].exit_addr` | string | yes | Exit IP and port of the session. |
| `sessions[].is_default` | boolean | no | Default: `false` |
| `sessions[].created` | string, nullable | no |  |
| `sessions[].last_used` | string, nullable | no |  |
| `sessions[].ttl_seconds` | integer, nullable | no | Sticky session duration, in seconds. |
| `sessions[].expires_at` | string, nullable | no | When the current term ends (ISO 8601, UTC). |
| `sessions[].mode` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:read`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:read"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Rotate a sticky session

`POST /api/v1/customer/services/{service_id}/proxy/sticky/sessions/{sid}/rotate`

- Access: API key required · scope `services:write`

Force a new exit IP for one sticky session. Free; this is not an IP list refresh.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |
| `sid (path)` | string | yes | ID of the sticky session. |

Request examples:

cURL:

```bash
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string/rotate" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string/rotate",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string/rotate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string/rotate');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string/rotate", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Result of moving one sticky session to a new exit IP.

| Field | Type | Required | Description |
|---|---|---|---|
| `sid` | string | yes | Sticky session ID. |
| `exit` | string | yes | Exit IP of the session. |
| `exit_addr` | string | yes | Exit IP and port of the session. |
| `status` | string | no | Default: `"rotated"` |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:write"}
  ```

- `404` — Sticky session not found, or it doesn't belong to your account.
- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### End a sticky session

`DELETE /api/v1/customer/services/{service_id}/proxy/sticky/sessions/{sid}`

- Access: API key required · scope `services:write`

End one sticky session; its next request gets a new exit IP.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |
| `sid (path)` | string | yes | ID of the sticky session. |

Request examples:

cURL:

```bash
curl -X DELETE "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.delete(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/sessions/string", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `204` — The session ended. No response body.
- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:write"}
  ```

- `404` — Sticky session not found, or it doesn't belong to your account.
- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### End all sticky sessions

`POST /api/v1/customer/services/{service_id}/proxy/sticky/purge`

- Access: API key required · scope `services:write`

End all sticky sessions of a rotating service.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request examples:

cURL:

```bash
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/purge" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/purge",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/purge", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/purge');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/purge", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Result of ending all sticky sessions.

Example response:

```json
{
  "deleted": 0
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `deleted` | integer | yes |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:write"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Get session mode

`GET /api/v1/customer/services/{service_id}/proxy/sticky/mode`

- Access: API key required · scope `services:read`

Current session mode of a rotating service: `rotating` (new exit IP per request), `sticky`, or `pinned`.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request examples:

cURL:

```bash
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Session mode: `rotating`, `sticky`, or `pinned`.

Example response:

```json
{
  "mode": "sticky"
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `mode` | string | yes |  |
| `pin` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:read`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:read"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Set session mode

`PUT /api/v1/customer/services/{service_id}/proxy/sticky/mode`

- Access: API key required · scope `services:write`

Switch between `rotating`, `sticky`, and `pinned` modes. `pin` is required for `pinned`. If your rotating service doesn't support switching the mode, the response is `501`; use the sticky session duration endpoints instead.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request body (JSON):

| Field | Type | Required | Description |
|---|---|---|---|
| `mode` | string | yes | sticky \| rotating \| pinned · One of: `sticky`, `rotating`, `pinned` |
| `pin` | string, nullable | no | Exit IP:port to keep when `mode` is `pinned`. |

Request examples:

cURL:

```bash
curl -X PUT "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mode": "sticky"}'
```

Python:

```python
import os

import requests

resp = requests.put(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    json={
        "mode": "sticky"
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "mode": "sticky"
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'mode' => 'sticky'
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("PUT", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/mode", strings.NewReader(`{"mode": "sticky"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Session mode: `rotating`, `sticky`, or `pinned`.

Example response:

```json
{
  "mode": "sticky"
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `mode` | string | yes |  |
| `pin` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:write"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```

- `501` — Switching the session mode isn't supported for this service.

  Example:

  ```json
  {"detail": "Sticky mode is not supported by the configured upstream."}
  ```


### Get sticky session duration

`GET /api/v1/customer/services/{service_id}/proxy/sticky/ttl`

- Access: API key required · scope `services:read`

How long a sticky session keeps the same exit IP, in seconds.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request examples:

cURL:

```bash
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Sticky session duration, in seconds.

Example response:

```json
{
  "ttl_seconds": 900,
  "is_custom": false,
  "global_default_ttl": 900,
  "ttl_human": "15m"
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `ttl_seconds` | integer, nullable | no | Sticky session duration, in seconds. |
| `is_custom` | boolean | no | Default: `false` |
| `global_default_ttl` | integer, nullable | no |  |
| `ttl_human` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:read`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:read"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Set sticky session duration

`PUT /api/v1/customer/services/{service_id}/proxy/sticky/ttl`

- Access: API key required · scope `services:write`

Set how long a sticky session keeps the same exit IP, in seconds (minimum 30).

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request body (JSON):

| Field | Type | Required | Description |
|---|---|---|---|
| `seconds` | integer | yes | TTL override in seconds (minimum 30) · Minimum: 30 |

Request examples:

cURL:

```bash
curl -X PUT "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"seconds": 600}'
```

Python:

```python
import os

import requests

resp = requests.put(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    json={
        "seconds": 600
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "seconds": 600
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'seconds' => 600
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("PUT", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl", strings.NewReader(`{"seconds": 600}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Sticky session duration, in seconds.

Example response:

```json
{
  "ttl_seconds": 600,
  "is_custom": true,
  "global_default_ttl": 900,
  "ttl_human": "10m"
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `ttl_seconds` | integer, nullable | no | Sticky session duration, in seconds. |
| `is_custom` | boolean | no | Default: `false` |
| `global_default_ttl` | integer, nullable | no |  |
| `ttl_human` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:write"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```


### Reset sticky session duration

`DELETE /api/v1/customer/services/{service_id}/proxy/sticky/ttl`

- Access: API key required · scope `services:write`

Return the sticky session duration to the default.

Parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `service_id (path)` | string (uuid) | yes | ID of the service. |

Request examples:

cURL:

```bash
curl -X DELETE "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
```

Python:

```python
import os

import requests

resp = requests.delete(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
```

Node.js:

```javascript
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
  },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
```

PHP:

```php
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
    ],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
```

Go:

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/proxy/sticky/ttl", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPAPROXY_API_KEY"))
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}
```

Responses:

- `200` — Sticky session duration, in seconds.

Example response:

```json
{
  "ttl_seconds": 900,
  "is_custom": false,
  "global_default_ttl": 900,
  "ttl_human": "15m"
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `ttl_seconds` | integer, nullable | no | Sticky session duration, in seconds. |
| `is_custom` | boolean | no | Default: `false` |
| `global_default_ttl` | integer, nullable | no |  |
| `ttl_human` | string, nullable | no |  |

- `401` — The API key is missing, malformed, revoked, or expired, or the account is inactive.

  Example:

  ```json
  {"detail": "Invalid or revoked API key."}
  ```

- `403` — The API key lacks scope `services:write`.

  Example:

  ```json
  {"detail": "API key is missing required scope: services:write"}
  ```

- `404` — Service not found, or it doesn't belong to your account.

  Example:

  ```json
  {"detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found."}
  ```

- `422` — Validation error: a field is missing or has the wrong type or value.

  Example:

  ```json
  {"detail": "Validation error"}
  ```

- `429` — Too many requests: the per-account limit is 60 requests per minute, shared by all keys and the MCP server. Retry with exponential backoff.

  Example:

  ```json
  {"detail": "Too Many Requests"}
  ```

