Products
Datacenter proxies from $19/mo Rotating proxies from $25/mo ISP proxies from $33/mo Dedicated proxies from $3.50/mo UDP proxies from $5/mo Try proxies
Use cases
Data & scraping AI services Social media & messaging E-commerce & finance Media & entertainment Marketing & ads Automation & tools All use cases →
Pricing
Full pricing table All locations Money-back guarantee
Resources
Dashboard guide API reference API and MCP Setup guides FAQ Blog For business About us Affiliate program
New dashboard
English
English Русский

Services

6 endpoints · base URL https://papaproxy.net/account_new · authentication

List your services

GET/api/v1/customer/services
API key required scope services:read

List your services (paginated).

Parameters

FieldTypeDescription
offset (query)integerNumber of items to skip.Minimum: 0Default: 0
limit (query)integerPage size.Minimum: 1Maximum: 100Default: 50

Request example Try it in the Dashboard

cURL
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
Python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/services",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services", {
  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
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services');
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
package main

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

func main() {
	req, err := http.NewRequest("GET", "https://papaproxy.net/account_new/api/v1/customer/services", 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 Paginated service list. · 33 fields
    Example response · JSON
    {
      "services": [
        {
          "id": "3bd2e419-2dc6-52bb-9d74-0a4560d55f53",
          "owner_type": "customer",
          "owner_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
          "product_id": "5234db61-2f19-5aa0-8e64-faa72f7d4b76",
          "product_name": "Starter 2.5M",
          "product_kind": "proxy_rotating",
          "product_display_name": "Starter 2.5M",
          "display_name": "DC Rotating 2500k requests",
          "owner_email": null,
          "status": "active",
          "params": {
            "sticky": true,
            "username": "pp_user_3fa85f64",
            "pool_class": "datacenter",
            "quota_kind": "requests",
            "period_days": 30,
            "session_mode": "sticky"
          },
          "started_at": "2026-11-07T13:41:50.351104Z",
          "expires_at": "2027-01-06T13:41:50.369505Z",
          "grace_until": null,
          "cancelled_at": null,
          "usage_requests_cur": null,
          "usage_bytes_cur": null,
          "is_trial": false,
          "is_auto_renew": true,
          "customer_note": null,
          "created_at": "2026-11-07T13:41:50.327149Z",
          "price_cents": 4900,
          "price_unit": "period",
          "active_addon_types": [],
          "renewal_price_cents": 4900,
          "renewal_coverage": "not_covered",
          "suspend_reason": null,
          "next_quota_grant_at": "2026-12-07T13:41:50.369505Z",
          "renew_allowed": true
        },
        {
          "id": "cb532178-5b03-506a-84ea-0230ff28576b",
          "owner_type": "customer",
          "owner_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
          "product_id": "50ef87c9-6dd6-50ae-b2e5-bef6da689911",
          "product_name": "Datacenter Proxy US 500 IPs",
          "product_kind": "proxy_datacenter",
          "product_display_name": "Datacenter Proxy US 500 IPs",
          "display_name": "Datacenter Proxy US 500 IPs",
          "owner_email": null,
          "status": "active",
          "params": {
            "geo": [
              "US"
            ],
            "segments": [
              {
                "count": 500,
                "country": 197148
              }
            ],
            "total_ip": 500,
            "composite": true,
            "whitelist_ips": [
              "203.0.113.10"
            ]
          },
          "started_at": "2026-11-07T13:41:00.208626Z",
          "expires_at": "2027-01-06T13:41:02.315398Z",
          "grace_until": null,
          "cancelled_at": null,
          "usage_requests_cur": null,
          "usage_bytes_cur": null,
          "is_trial": false,
          "is_auto_renew": true,
          "customer_note": null,
          "created_at": "2026-11-07T13:40:54.881463Z",
          "price_cents": 9500,
          "price_unit": "period",
          "active_addon_types": [],
          "renewal_price_cents": 9500,
          "renewal_coverage": "not_covered",
          "suspend_reason": null,
          "next_quota_grant_at": "2026-12-07T13:41:02.315398Z",
          "renew_allowed": true
        }
      ],
      "total": 16,
      "offset": 0,
      "limit": 2
    }
    FieldTypeDescription
    services requiredarray of object
    services[].id requiredstring (uuid)Unique ID.
    services[].owner_type requiredstringOwner type (customer).
    services[].owner_id requiredstring (uuid)ID of your account.
    services[].product_id requiredstring (uuid)ID of the catalog product.
    services[].product_namestringCatalog product name.Default: ""
    services[].product_kindstringProduct type: proxy_datacenter, proxy_isp, or proxy_rotating. Dedicated proxies report the underlying type and have params.dedicated = true.Default: ""
    services[].product_display_namestringProduct name shown in the Dashboard.Default: ""
    services[].display_namestring, nullableName shown in the Dashboard.
    services[].owner_emailstring, nullableEmail of the owner, if set.
    services[].status requiredstringService status, for example active, pending (awaiting payment), or suspended.
    services[].params requiredobject, nullableService configuration: countries and IP counts for proxy packages; dedicated: true for dedicated proxies.
    services[].started_at requiredstring (date-time), nullableWhen the service started (ISO 8601, UTC).
    services[].expires_at requiredstring (date-time), nullableWhen the current term ends (ISO 8601, UTC).
    services[].grace_untilstring (date-time), nullableEnd of the grace period after expiration, if any.
    services[].cancelled_at requiredstring (date-time), nullableWhen the service was canceled, if it was.
    services[].usage_requests_cur requiredinteger, nullableRequests used in the current period (rotating proxies).
    services[].usage_bytes_cur requiredinteger, nullableBandwidth used in the current period, in bytes.
    services[].is_trialbooleanWhether this is a trial service.Default: false
    services[].is_auto_renew requiredbooleanWhether the service renews automatically.
    services[].customer_notestring, nullableYour note on the service, if any.
    services[].created_at requiredstring (date-time)When it was created (ISO 8601, UTC).
    services[].price_centsinteger, nullablePrice in cents.
    services[].price_unitstring, nullableBilling unit of price_cents.
    services[].active_addon_typesarray of stringTypes of the add-ons that are active on this service.
    services[].renewal_price_centsinteger, nullableForecast charge at the next auto-renewal (base price + active add-ons), same resolution as the real renewal charge. None when not applicable (see renewal_coverage).
    services[].renewal_coveragestringWhether the next renewal is covered: covered_by_balance, covered_by_card (an automatic top-up will charge the saved card), not_covered, or not_applicable.Default: "not_applicable"
    services[].suspend_reasonstring, nullableWhy the service is suspended: quota_exhausted, expired, or other. Null when it isn't suspended.
    services[].next_quota_grant_atstring (date-time), nullableWhen the next monthly request allowance is added (rotating services), if it falls within the paid term.
    services[].renew_allowedboolean, nullableWhether the service can be renewed right now.
    total requiredintegerTotal number of items across all pages.
    offsetintegerNumber of items skipped.Default: 0
    limitintegerPage size.Default: 50
  • 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"
    }
  • 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"
    }

Buy a service

POST/api/v1/customer/services
API key required scope services:write

Buy a catalog product (rotating proxies) and pay from your wallet balance. Idempotent: repeating the call with the same product and parameters returns the existing service without charging again. For proxy packages built from countries, use POST /api/v1/billing/composite/order; for dedicated proxies, use POST /api/v1/billing/dedicated/order.

Request body

FieldTypeDescription
product_id requiredstring (uuid)ID of the catalog product.
paramsobject, nullable
auto_renewbooleanDefault: true
expected_price_centsinteger, nullableThe total charge you showed the user, in cents. Required for some products; if it's missing or doesn't match the current price, the request fails with HTTP 409 and nothing is charged.

Request example Try it in the Dashboard

cURL
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/services" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"product_id": "5234db61-2f19-5aa0-8e64-faa72f7d4b76", "expected_price_cents": 4900}'
Python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/customer/services",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    json={
        "product_id": "5234db61-2f19-5aa0-8e64-faa72f7d4b76",
        "expected_price_cents": 4900
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "product_id": "5234db61-2f19-5aa0-8e64-faa72f7d4b76",
    "expected_price_cents": 4900
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
PHP
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'product_id' => '5234db61-2f19-5aa0-8e64-faa72f7d4b76',
        'expected_price_cents' => 4900
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
Go
package main

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

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/customer/services", strings.NewReader(`{"product_id": "5234db61-2f19-5aa0-8e64-faa72f7d4b76", "expected_price_cents": 4900}`))
	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

  • 201 Result of service creation. · 31 fields
    Example response · JSON
    {
      "service": {
        "id": "3bd2e419-2dc6-52bb-9d74-0a4560d55f53",
        "owner_type": "customer",
        "owner_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
        "product_id": "5234db61-2f19-5aa0-8e64-faa72f7d4b76",
        "product_name": "Starter 2.5M",
        "product_kind": "proxy_rotating",
        "product_display_name": "Starter 2.5M",
        "display_name": "DC Rotating 2500k requests",
        "owner_email": null,
        "status": "active",
        "params": {
          "sticky": true,
          "username": "pp_user_3fa85f64",
          "pool_class": "datacenter",
          "quota_kind": "requests",
          "period_days": 30,
          "session_mode": "sticky"
        },
        "started_at": "2026-11-07T13:41:50.351104Z",
        "expires_at": "2027-01-06T13:41:50.369505Z",
        "grace_until": null,
        "cancelled_at": null,
        "usage_requests_cur": null,
        "usage_bytes_cur": null,
        "is_trial": false,
        "is_auto_renew": true,
        "customer_note": null,
        "created_at": "2026-11-07T13:41:50.327149Z",
        "price_cents": 4900,
        "price_unit": "period",
        "active_addon_types": [],
        "renewal_price_cents": null,
        "renewal_coverage": "not_applicable",
        "suspend_reason": null,
        "next_quota_grant_at": "2026-12-07T13:41:50.369505Z",
        "renew_allowed": true
      },
      "invoice_url": null
    }
    FieldTypeDescription
    service requiredobjectA purchased service / subscription.
    service.id requiredstring (uuid)Unique ID.
    service.owner_type requiredstringOwner type (customer).
    service.owner_id requiredstring (uuid)ID of your account.
    service.product_id requiredstring (uuid)ID of the catalog product.
    service.product_namestringCatalog product name.Default: ""
    service.product_kindstringProduct type: proxy_datacenter, proxy_isp, or proxy_rotating. Dedicated proxies report the underlying type and have params.dedicated = true.Default: ""
    service.product_display_namestringProduct name shown in the Dashboard.Default: ""
    service.display_namestring, nullableName shown in the Dashboard.
    service.owner_emailstring, nullableEmail of the owner, if set.
    service.status requiredstringService status, for example active, pending (awaiting payment), or suspended.
    service.params requiredobject, nullableService configuration: countries and IP counts for proxy packages; dedicated: true for dedicated proxies.
    service.started_at requiredstring (date-time), nullableWhen the service started (ISO 8601, UTC).
    service.expires_at requiredstring (date-time), nullableWhen the current term ends (ISO 8601, UTC).
    service.grace_untilstring (date-time), nullableEnd of the grace period after expiration, if any.
    service.cancelled_at requiredstring (date-time), nullableWhen the service was canceled, if it was.
    service.usage_requests_cur requiredinteger, nullableRequests used in the current period (rotating proxies).
    service.usage_bytes_cur requiredinteger, nullableBandwidth used in the current period, in bytes.
    service.is_trialbooleanWhether this is a trial service.Default: false
    service.is_auto_renew requiredbooleanWhether the service renews automatically.
    service.customer_notestring, nullableYour note on the service, if any.
    service.created_at requiredstring (date-time)When it was created (ISO 8601, UTC).
    service.price_centsinteger, nullablePrice in cents.
    service.price_unitstring, nullableBilling unit of price_cents.
    service.active_addon_typesarray of stringTypes of the add-ons that are active on this service.
    service.renewal_price_centsinteger, nullableForecast charge at the next auto-renewal (base price + active add-ons), same resolution as the real renewal charge. None when not applicable (see renewal_coverage).
    service.renewal_coveragestringWhether the next renewal is covered: covered_by_balance, covered_by_card (an automatic top-up will charge the saved card), not_covered, or not_applicable.Default: "not_applicable"
    service.suspend_reasonstring, nullableWhy the service is suspended: quota_exhausted, expired, or other. Null when it isn't suspended.
    service.next_quota_grant_atstring (date-time), nullableWhen the next monthly request allowance is added (rotating services), if it falls within the paid term.
    service.renew_allowedboolean, nullableWhether the service can be renewed right now.
    invoice_urlstring, nullableLink to the invoice, if one was issued.
  • 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"
    }
  • 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 a service

GET/api/v1/customer/services/{service_id}
API key required scope services:read

Get details of one of your services.

Parameters

FieldTypeDescription
service_id (path) requiredstring (uuid)ID of the service.

Request example Try it in the Dashboard

cURL
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
Python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6", {
  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
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6');
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
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", 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 A purchased service / subscription. · 29 fields
    Example response · JSON
    {
      "id": "cb532178-5b03-506a-84ea-0230ff28576b",
      "owner_type": "customer",
      "owner_id": "8218fbc6-d67b-52fd-a639-cca399215d31",
      "product_id": "50ef87c9-6dd6-50ae-b2e5-bef6da689911",
      "product_name": "Datacenter Proxy US 500 IPs",
      "product_kind": "proxy_datacenter",
      "product_display_name": "Datacenter Proxy US 500 IPs",
      "display_name": "Datacenter Proxy US 500 IPs",
      "owner_email": null,
      "status": "active",
      "params": {
        "geo": [
          "US"
        ],
        "segments": [
          {
            "count": 500,
            "country": 197148
          }
        ],
        "total_ip": 500,
        "composite": true,
        "whitelist_ips": [
          "203.0.113.10"
        ]
      },
      "started_at": "2026-11-07T13:41:00.208626Z",
      "expires_at": "2027-01-06T13:41:02.315398Z",
      "grace_until": null,
      "cancelled_at": null,
      "usage_requests_cur": null,
      "usage_bytes_cur": null,
      "is_trial": false,
      "is_auto_renew": true,
      "customer_note": null,
      "created_at": "2026-11-07T13:40:54.881463Z",
      "price_cents": 9500,
      "price_unit": "period",
      "active_addon_types": [],
      "renewal_price_cents": 9500,
      "renewal_coverage": "not_covered",
      "suspend_reason": null,
      "next_quota_grant_at": "2026-12-07T13:41:02.315398Z",
      "renew_allowed": true
    }
    FieldTypeDescription
    id requiredstring (uuid)Unique ID.
    owner_type requiredstringOwner type (customer).
    owner_id requiredstring (uuid)ID of your account.
    product_id requiredstring (uuid)ID of the catalog product.
    product_namestringCatalog product name.Default: ""
    product_kindstringProduct type: proxy_datacenter, proxy_isp, or proxy_rotating. Dedicated proxies report the underlying type and have params.dedicated = true.Default: ""
    product_display_namestringProduct name shown in the Dashboard.Default: ""
    display_namestring, nullableName shown in the Dashboard.
    owner_emailstring, nullableEmail of the owner, if set.
    status requiredstringService status, for example active, pending (awaiting payment), or suspended.
    params requiredobject, nullableService configuration: countries and IP counts for proxy packages; dedicated: true for dedicated proxies.
    started_at requiredstring (date-time), nullableWhen the service started (ISO 8601, UTC).
    expires_at requiredstring (date-time), nullableWhen the current term ends (ISO 8601, UTC).
    grace_untilstring (date-time), nullableEnd of the grace period after expiration, if any.
    cancelled_at requiredstring (date-time), nullableWhen the service was canceled, if it was.
    usage_requests_cur requiredinteger, nullableRequests used in the current period (rotating proxies).
    usage_bytes_cur requiredinteger, nullableBandwidth used in the current period, in bytes.
    is_trialbooleanWhether this is a trial service.Default: false
    is_auto_renew requiredbooleanWhether the service renews automatically.
    customer_notestring, nullableYour note on the service, if any.
    created_at requiredstring (date-time)When it was created (ISO 8601, UTC).
    price_centsinteger, nullablePrice in cents.
    price_unitstring, nullableBilling unit of price_cents.
    active_addon_typesarray of stringTypes of the add-ons that are active on this service.
    renewal_price_centsinteger, nullableForecast charge at the next auto-renewal (base price + active add-ons), same resolution as the real renewal charge. None when not applicable (see renewal_coverage).
    renewal_coveragestringWhether the next renewal is covered: covered_by_balance, covered_by_card (an automatic top-up will charge the saved card), not_covered, or not_applicable.Default: "not_applicable"
    suspend_reasonstring, nullableWhy the service is suspended: quota_exhausted, expired, or other. Null when it isn't suspended.
    next_quota_grant_atstring (date-time), nullableWhen the next monthly request allowance is added (rotating services), if it falls within the paid term.
    renew_allowedboolean, nullableWhether the service can be renewed right now.
  • 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"
    }

Renew a service

POST/api/v1/customer/services/{service_id}/renew
API key required scope services:write

Renew a service for another term and pay from your wallet balance. Pass period_months (1, 3, 6, or 12) to apply the term discount. A retry with the same idempotency_key returns the original result and doesn't charge again. Insufficient balance returns 400 (Insufficient funds: need … cents); nothing is charged.

Parameters

FieldTypeDescription
service_id (path) requiredstring (uuid)ID of the service.

Request body

FieldTypeDescription
period_countintegerMinimum: 1Maximum: 12Default: 1
period_monthsinteger, nullableRenewal term in months (1, 3, 6, or 12). Overrides period_count and applies the term discount.
idempotency_keystring, nullableIdempotency key; retries with the same key never charge twice. Can also be sent in the Idempotency-Key header.Min length: 1Max length: 128

Request example Try it in the Dashboard

cURL
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/renew" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"period_months": 1, "idempotency_key": "renew-2026-001"}'
Python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/renew",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    json={
        "period_months": 1,
        "idempotency_key": "renew-2026-001"
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/renew", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "period_months": 1,
    "idempotency_key": "renew-2026-001"
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
PHP
<?php
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/renew');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('PAPAPROXY_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'period_months' => 1,
        'idempotency_key' => 'renew-2026-001'
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
var_dump($status, json_decode($response, true));
Go
package main

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

func main() {
	req, err := http.NewRequest("POST", "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/renew", strings.NewReader(`{"period_months": 1, "idempotency_key": "renew-2026-001"}`))
	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 Simple status update response. · 8 fields
    Example response · JSON
    {
      "service_id": "cb532178-5b03-506a-84ea-0230ff28576b",
      "status": "active",
      "message": "Service renewed for 1 month(s).",
      "refund_cents": null,
      "new_expires_at": "2027-01-06T13:41:02.315398Z",
      "charged_cents": 5700,
      "funding_source": null,
      "refund_base_cents": null
    }
    FieldTypeDescription
    service_id requiredstring (uuid)ID of the service.
    status requiredstring
    message requiredstring
    refund_centsinteger, nullable
    new_expires_atstring (date-time), nullable
    charged_centsinteger, nullableAmount charged to your wallet, in cents.
    funding_sourcestring, nullable
    refund_base_centsinteger, nullable
  • 400 Insufficient wallet balance. Nothing is charged.
    Example · JSON
    {
      "detail": "Insufficient funds: need 9500 cents"
    }
  • 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"
    }

Cancel a service

POST/api/v1/customer/services/{service_id}/cancel
API key required scope services:write

Cancel (terminate) a service. Unused paid time may be refunded to your wallet on a prorated basis.

Cancellations are limited per account. Shortly after a previous cancellation, the request fails with 409 and detail.error = "SERVICE_CANCEL_COOLDOWN"; detail.retry_at and detail.retry_after_seconds say when you can try again. To cancel sooner, contact support.

Parameters

FieldTypeDescription
service_id (path) requiredstring (uuid)ID of the service.

Request example Try it in the Dashboard

cURL
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/cancel" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
Python
import os

import requests

resp = requests.post(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/cancel",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/cancel", {
  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
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/cancel');
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
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/cancel", 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 Simple status update response. · 8 fields
    FieldTypeDescription
    service_id requiredstring (uuid)ID of the service.
    status requiredstring
    message requiredstring
    refund_centsinteger, nullable
    new_expires_atstring (date-time), nullable
    charged_centsinteger, nullableAmount charged to your wallet, in cents.
    funding_sourcestring, nullable
    refund_base_centsinteger, nullable
  • 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."
    }
  • 409 A cancellation cooldown is active for your account.
    Example · JSON
    {
      "detail": {
        "error": "SERVICE_CANCEL_COOLDOWN",
        "support_required": true,
        "retry_at": "2026-11-10T13:41:08Z",
        "retry_after_seconds": 252708
      }
    }
  • 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 usage statistics

GET/api/v1/customer/services/{service_id}/usage
API key required scope usage:read

Request and connection statistics for a service over a time window.

Parameters

FieldTypeDescription
service_id (path) requiredstring (uuid)ID of the service.
start (query) requiredstring (date-time)Start of the window (ISO 8601)
end (query) requiredstring (date-time)End of the window (ISO 8601)

Request example Try it in the Dashboard

cURL
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/usage?start=2026-11-06T12:00:00Z&end=2026-11-06T12:00:00Z" \
  -H "Authorization: Bearer $PAPAPROXY_API_KEY"
Python
import os

import requests

resp = requests.get(
    "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/usage?start=2026-11-06T12:00:00Z&end=2026-11-06T12:00:00Z",
    headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js
const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/usage?start=2026-11-06T12:00:00Z&end=2026-11-06T12:00:00Z", {
  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
$ch = curl_init('https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/usage?start=2026-11-06T12:00:00Z&end=2026-11-06T12:00:00Z');
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
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/usage?start=2026-11-06T12:00:00Z&end=2026-11-06T12:00:00Z", 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 Usage stats for a proxy service. · 5 fields
    Example response · JSON
    {
      "connections": 0,
      "bytes_used": 0,
      "window": {
        "start": "2026-11-01T00:00:00Z",
        "end": "2026-11-07T23:59:59Z"
      }
    }
    FieldTypeDescription
    connectionsintegerDefault: 0
    bytes_usedintegerDefault: 0
    window requiredobjectTime window for usage stats.
    window.start requiredstring (date-time)
    window.end requiredstring (date-time)
  • 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 usage:read.
    Example · JSON
    {
      "detail": "API key is missing required scope: usage: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"
    }

Last updated: November 9, 2026. Generated from the OpenAPI 3.1 specification (API version 0.1.0). Markdown version for AI agents.