Services
6 endpoints · base URL https://papaproxy.net/account_new · authentication
List your services
/api/v1/customer/servicesservices:readList your services (paginated).
Parameters
| Field | Type | Description |
|---|---|---|
offset (query) | integer | Number of items to skip.Minimum: 0Default: 0 |
limit (query) | integer | Page size.Minimum: 1Maximum: 100Default: 50 |
Request example Try it in the Dashboard
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services" \ -H "Authorization: Bearer $PAPAPROXY_API_KEY"
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())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
$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));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
200Paginated service list. · 33 fieldsExample 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 }Field Type Description servicesrequiredarray of object services[].idrequiredstring (uuid) Unique ID. services[].owner_typerequiredstring Owner type ( customer).services[].owner_idrequiredstring (uuid) ID of your account. services[].product_idrequiredstring (uuid) ID of the catalog product. services[].product_namestring Catalog product name.Default: ""services[].product_kindstring Product type: proxy_datacenter,proxy_isp, orproxy_rotating. Dedicated proxies report the underlying type and haveparams.dedicated = true.Default:""services[].product_display_namestring Product name shown in the Dashboard.Default: ""services[].display_namestring, nullable Name shown in the Dashboard. services[].owner_emailstring, nullable Email of the owner, if set. services[].statusrequiredstring Service status, for example active,pending(awaiting payment), orsuspended.services[].paramsrequiredobject, nullable Service configuration: countries and IP counts for proxy packages; dedicated: truefor dedicated proxies.services[].started_atrequiredstring (date-time), nullable When the service started (ISO 8601, UTC). services[].expires_atrequiredstring (date-time), nullable When the current term ends (ISO 8601, UTC). services[].grace_untilstring (date-time), nullable End of the grace period after expiration, if any. services[].cancelled_atrequiredstring (date-time), nullable When the service was canceled, if it was. services[].usage_requests_currequiredinteger, nullable Requests used in the current period (rotating proxies). services[].usage_bytes_currequiredinteger, nullable Bandwidth used in the current period, in bytes. services[].is_trialboolean Whether this is a trial service.Default: falseservices[].is_auto_renewrequiredboolean Whether the service renews automatically. services[].customer_notestring, nullable Your note on the service, if any. services[].created_atrequiredstring (date-time) When it was created (ISO 8601, UTC). services[].price_centsinteger, nullable Price in cents. services[].price_unitstring, nullable Billing unit of price_cents.services[].active_addon_typesarray of string Types of the add-ons that are active on this service. services[].renewal_price_centsinteger, nullable Forecast 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_coveragestring Whether the next renewal is covered: covered_by_balance,covered_by_card(an automatic top-up will charge the saved card),not_covered, ornot_applicable.Default:"not_applicable"services[].suspend_reasonstring, nullable Why the service is suspended: quota_exhausted,expired, orother. Null when it isn't suspended.services[].next_quota_grant_atstring (date-time), nullable When the next monthly request allowance is added (rotating services), if it falls within the paid term. services[].renew_allowedboolean, nullable Whether the service can be renewed right now. totalrequiredinteger Total number of items across all pages. offsetinteger Number of items skipped.Default: 0limitinteger Page size.Default: 50401The API key is missing, malformed, revoked, or expired, or the account is inactive.Example · JSON{ "detail": "Invalid or revoked API key." }403The API key lacks scopeservices:read.Example · JSON{ "detail": "API key is missing required scope: services:read" }422Validation error: a field is missing or has the wrong type or value.Example · JSON{ "detail": "Validation error" }429Too 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
/api/v1/customer/servicesservices:writeBuy 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
| Field | Type | Description |
|---|---|---|
product_id required | string (uuid) | ID of the catalog product. |
params | object, nullable | |
auto_renew | boolean | Default: true |
expected_price_cents | integer, nullable | The 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 -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}'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())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
$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));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
201Result of service creation. · 31 fieldsExample 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 }Field Type Description servicerequiredobject A purchased service / subscription. service.idrequiredstring (uuid) Unique ID. service.owner_typerequiredstring Owner type ( customer).service.owner_idrequiredstring (uuid) ID of your account. service.product_idrequiredstring (uuid) ID of the catalog product. service.product_namestring Catalog product name.Default: ""service.product_kindstring Product type: proxy_datacenter,proxy_isp, orproxy_rotating. Dedicated proxies report the underlying type and haveparams.dedicated = true.Default:""service.product_display_namestring Product name shown in the Dashboard.Default: ""service.display_namestring, nullable Name shown in the Dashboard. service.owner_emailstring, nullable Email of the owner, if set. service.statusrequiredstring Service status, for example active,pending(awaiting payment), orsuspended.service.paramsrequiredobject, nullable Service configuration: countries and IP counts for proxy packages; dedicated: truefor dedicated proxies.service.started_atrequiredstring (date-time), nullable When the service started (ISO 8601, UTC). service.expires_atrequiredstring (date-time), nullable When the current term ends (ISO 8601, UTC). service.grace_untilstring (date-time), nullable End of the grace period after expiration, if any. service.cancelled_atrequiredstring (date-time), nullable When the service was canceled, if it was. service.usage_requests_currequiredinteger, nullable Requests used in the current period (rotating proxies). service.usage_bytes_currequiredinteger, nullable Bandwidth used in the current period, in bytes. service.is_trialboolean Whether this is a trial service.Default: falseservice.is_auto_renewrequiredboolean Whether the service renews automatically. service.customer_notestring, nullable Your note on the service, if any. service.created_atrequiredstring (date-time) When it was created (ISO 8601, UTC). service.price_centsinteger, nullable Price in cents. service.price_unitstring, nullable Billing unit of price_cents.service.active_addon_typesarray of string Types of the add-ons that are active on this service. service.renewal_price_centsinteger, nullable Forecast 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_coveragestring Whether the next renewal is covered: covered_by_balance,covered_by_card(an automatic top-up will charge the saved card),not_covered, ornot_applicable.Default:"not_applicable"service.suspend_reasonstring, nullable Why the service is suspended: quota_exhausted,expired, orother. Null when it isn't suspended.service.next_quota_grant_atstring (date-time), nullable When the next monthly request allowance is added (rotating services), if it falls within the paid term. service.renew_allowedboolean, nullable Whether the service can be renewed right now. invoice_urlstring, nullable Link to the invoice, if one was issued. 401The API key is missing, malformed, revoked, or expired, or the account is inactive.Example · JSON{ "detail": "Invalid or revoked API key." }403The API key lacks scopeservices:write.Example · JSON{ "detail": "API key is missing required scope: services:write" }422Validation error: a field is missing or has the wrong type or value.Example · JSON{ "detail": "Validation error" }429Too 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
/api/v1/customer/services/{service_id}services:readGet details of one of your services.
Parameters
| Field | Type | Description |
|---|---|---|
service_id (path) required | string (uuid) | ID of the service. |
Request example Try it in the Dashboard
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6" \ -H "Authorization: Bearer $PAPAPROXY_API_KEY"
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())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
$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));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
200A purchased service / subscription. · 29 fieldsExample 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 }Field Type Description idrequiredstring (uuid) Unique ID. owner_typerequiredstring Owner type ( customer).owner_idrequiredstring (uuid) ID of your account. product_idrequiredstring (uuid) ID of the catalog product. product_namestring Catalog product name.Default: ""product_kindstring Product type: proxy_datacenter,proxy_isp, orproxy_rotating. Dedicated proxies report the underlying type and haveparams.dedicated = true.Default:""product_display_namestring Product name shown in the Dashboard.Default: ""display_namestring, nullable Name shown in the Dashboard. owner_emailstring, nullable Email of the owner, if set. statusrequiredstring Service status, for example active,pending(awaiting payment), orsuspended.paramsrequiredobject, nullable Service configuration: countries and IP counts for proxy packages; dedicated: truefor dedicated proxies.started_atrequiredstring (date-time), nullable When the service started (ISO 8601, UTC). expires_atrequiredstring (date-time), nullable When the current term ends (ISO 8601, UTC). grace_untilstring (date-time), nullable End of the grace period after expiration, if any. cancelled_atrequiredstring (date-time), nullable When the service was canceled, if it was. usage_requests_currequiredinteger, nullable Requests used in the current period (rotating proxies). usage_bytes_currequiredinteger, nullable Bandwidth used in the current period, in bytes. is_trialboolean Whether this is a trial service.Default: falseis_auto_renewrequiredboolean Whether the service renews automatically. customer_notestring, nullable Your note on the service, if any. created_atrequiredstring (date-time) When it was created (ISO 8601, UTC). price_centsinteger, nullable Price in cents. price_unitstring, nullable Billing unit of price_cents.active_addon_typesarray of string Types of the add-ons that are active on this service. renewal_price_centsinteger, nullable Forecast 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_coveragestring Whether the next renewal is covered: covered_by_balance,covered_by_card(an automatic top-up will charge the saved card),not_covered, ornot_applicable.Default:"not_applicable"suspend_reasonstring, nullable Why the service is suspended: quota_exhausted,expired, orother. Null when it isn't suspended.next_quota_grant_atstring (date-time), nullable When the next monthly request allowance is added (rotating services), if it falls within the paid term. renew_allowedboolean, nullable Whether the service can be renewed right now. 401The API key is missing, malformed, revoked, or expired, or the account is inactive.Example · JSON{ "detail": "Invalid or revoked API key." }403The API key lacks scopeservices:read.Example · JSON{ "detail": "API key is missing required scope: services:read" }404Service not found, or it doesn't belong to your account.Example · JSON{ "detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found." }422Validation error: a field is missing or has the wrong type or value.Example · JSON{ "detail": "Validation error" }429Too 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
/api/v1/customer/services/{service_id}/renewservices:writeRenew 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
| Field | Type | Description |
|---|---|---|
service_id (path) required | string (uuid) | ID of the service. |
Request body
| Field | Type | Description |
|---|---|---|
period_count | integer | Minimum: 1Maximum: 12Default: 1 |
period_months | integer, nullable | Renewal term in months (1, 3, 6, or 12). Overrides period_count and applies the term discount. |
idempotency_key | string, nullable | Idempotency 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 -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"}'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())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
$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));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
200Simple status update response. · 8 fieldsExample 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 }Field Type Description service_idrequiredstring (uuid) ID of the service. statusrequiredstring messagerequiredstring refund_centsinteger, nullable new_expires_atstring (date-time), nullable charged_centsinteger, nullable Amount charged to your wallet, in cents. funding_sourcestring, nullable refund_base_centsinteger, nullable 400Insufficient wallet balance. Nothing is charged.Example · JSON{ "detail": "Insufficient funds: need 9500 cents" }401The API key is missing, malformed, revoked, or expired, or the account is inactive.Example · JSON{ "detail": "Invalid or revoked API key." }403The API key lacks scopeservices:write.Example · JSON{ "detail": "API key is missing required scope: services:write" }404Service not found, or it doesn't belong to your account.Example · JSON{ "detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found." }422Validation error: a field is missing or has the wrong type or value.Example · JSON{ "detail": "Validation error" }429Too 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
/api/v1/customer/services/{service_id}/cancelservices:writeCancel (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
| Field | Type | Description |
|---|---|---|
service_id (path) required | string (uuid) | ID of the service. |
Request example Try it in the Dashboard
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/services/3fa85f64-5717-4562-b3fc-2c963f66afa6/cancel" \ -H "Authorization: Bearer $PAPAPROXY_API_KEY"
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())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
$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));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
200Simple status update response. · 8 fieldsField Type Description service_idrequiredstring (uuid) ID of the service. statusrequiredstring messagerequiredstring refund_centsinteger, nullable new_expires_atstring (date-time), nullable charged_centsinteger, nullable Amount charged to your wallet, in cents. funding_sourcestring, nullable refund_base_centsinteger, nullable 401The API key is missing, malformed, revoked, or expired, or the account is inactive.Example · JSON{ "detail": "Invalid or revoked API key." }403The API key lacks scopeservices:write.Example · JSON{ "detail": "API key is missing required scope: services:write" }404Service not found, or it doesn't belong to your account.Example · JSON{ "detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found." }409A 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 } }422Validation error: a field is missing or has the wrong type or value.Example · JSON{ "detail": "Validation error" }429Too 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
/api/v1/customer/services/{service_id}/usageusage:readRequest and connection statistics for a service over a time window.
Parameters
| Field | Type | Description |
|---|---|---|
service_id (path) required | string (uuid) | ID of the service. |
start (query) required | string (date-time) | Start of the window (ISO 8601) |
end (query) required | string (date-time) | End of the window (ISO 8601) |
Request example Try it in the Dashboard
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"
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())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
$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));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
200Usage stats for a proxy service. · 5 fieldsExample response · JSON{ "connections": 0, "bytes_used": 0, "window": { "start": "2026-11-01T00:00:00Z", "end": "2026-11-07T23:59:59Z" } }Field Type Description connectionsinteger Default: 0bytes_usedinteger Default: 0windowrequiredobject Time window for usage stats. window.startrequiredstring (date-time) window.endrequiredstring (date-time) 401The API key is missing, malformed, revoked, or expired, or the account is inactive.Example · JSON{ "detail": "Invalid or revoked API key." }403The API key lacks scopeusage:read.Example · JSON{ "detail": "API key is missing required scope: usage:read" }404Service not found, or it doesn't belong to your account.Example · JSON{ "detail": "Service 3fa85f64-5717-4562-b3fc-2c963f66afa6 not found." }422Validation error: a field is missing or has the wrong type or value.Example · JSON{ "detail": "Validation error" }429Too 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.