Wallet
4 endpoints · base URL https://papaproxy.net/account_new · authentication
Get wallet balance
/api/v1/customer/wallet/balancewallet:readYour prepaid wallet balance, calculated from the transaction ledger. Accounts that have never topped up report balance_cents=0.
Request example Try it in the Dashboard
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/wallet/balance" \ -H "Authorization: Bearer $PAPAPROXY_API_KEY"
import os
import requests
resp = requests.get(
"https://papaproxy.net/account_new/api/v1/customer/wallet/balance",
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/wallet/balance", {
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/wallet/balance');
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/wallet/balance", 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
200Current wallet balance. · 6 fieldsExample response · JSON{ "wallet_id": "d7fa9fe6-fd70-582d-aa84-e52c5068ca35", "owner_type": "customer", "owner_id": "8218fbc6-d67b-52fd-a639-cca399215d31", "balance_cents": 1997, "currency": "USD", "has_wallet": true }Field Type Description wallet_idstring (uuid), nullable ID of your wallet. owner_typerequiredstring owner_idrequiredstring (uuid) balance_centsrequiredinteger Available balance in integer cents currencystring Currency code ( USD).Min length: 3Max length: 3Default:"USD"has_walletboolean False if the account has never topped up; balance_centsis 0 in that case.Default:true401The 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 scopewallet:read.Example · JSON{ "detail": "API key is missing required scope: wallet:read" }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" }
List wallet transactions
/api/v1/customer/wallet/ledgerwallet:readList wallet transactions (paginated, newest first).
Entries linked to a specific service carry its service_id.
Parameters
| Field | Type | Description |
|---|---|---|
offset (query) | integer | Number of items to skip.Minimum: 0Default: 0 |
limit (query) | integer | Page size.Minimum: 1Maximum: 200Default: 50 |
Request example Try it in the Dashboard
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/wallet/ledger" \ -H "Authorization: Bearer $PAPAPROXY_API_KEY"
import os
import requests
resp = requests.get(
"https://papaproxy.net/account_new/api/v1/customer/wallet/ledger",
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/wallet/ledger", {
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/wallet/ledger');
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/wallet/ledger", 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 list of ledger entries. · 18 fieldsExample response · JSON{ "entries": [ { "id": "d4ac48f1-e447-50a4-9b61-a95ea7505be0", "wallet_id": "d7fa9fe6-fd70-582d-aa84-e52c5068ca35", "idempotency_key": "addon_refund:fc9f2062-7726-5122-ab7f-d6a7814ed548#s1", "provider": null, "provider_tx_id": null, "amount_cents": 3, "balance_after_cents": 1997, "entry_type": "refund", "status": "completed", "description": "Addon refund: Extra connections (30 unused days) for Datacenter Proxy US 500 IPs", "service_id": "cb532178-5b03-506a-84ea-0230ff28576b", "usage_requests": null, "usage_bytes": null, "created_at": "2026-11-07T14:30:45.447818Z" }, { "id": "872ef948-7db3-5d67-9755-cc0f965b2b7a", "wallet_id": "d7fa9fe6-fd70-582d-aa84-e52c5068ca35", "idempotency_key": "addon_purchase:capture-d576b57ad59e", "provider": null, "provider_tx_id": null, "amount_cents": -3, "balance_after_cents": 1994, "entry_type": "debit", "status": "completed", "description": "Addon purchase: Extra connections for Datacenter Proxy US 500 IPs", "service_id": "cb532178-5b03-506a-84ea-0230ff28576b", "usage_requests": null, "usage_bytes": null, "created_at": "2026-11-07T14:30:43.459177Z" } ], "total": 26, "offset": 0, "limit": 3 }Field Type Description entriesrequiredarray of object entries[].idrequiredstring (uuid) Unique ID. entries[].wallet_idrequiredstring (uuid) ID of your wallet. entries[].idempotency_keyrequiredstring entries[].providerrequiredstring, nullable Payment processor or source of the transaction. entries[].provider_tx_idrequiredstring, nullable Transaction ID at the payment processor. entries[].amount_centsrequiredinteger Amount in integer cents entries[].balance_after_centsrequiredinteger Running balance after this entry entries[].entry_typerequiredstring entries[].statusrequiredstring entries[].descriptionrequiredstring, nullable entries[].service_idrequiredstring (uuid), nullable ID of the service. entries[].usage_requestsrequiredinteger, nullable entries[].usage_bytesrequiredinteger, nullable entries[].created_atrequiredstring (date-time) When it was created (ISO 8601, UTC). 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 scopewallet:read.Example · JSON{ "detail": "API key is missing required scope: wallet: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" }
Top up your wallet
/api/v1/customer/wallet/deposit/initwallet:depositStart a wallet top-up and get a checkout URL. The wallet is credited after the payment processor confirms the payment — check the transaction list to see the credit. Pass idempotency_key to make retries safe.
If the selected payment method requires identity verification that hasn't been completed, the response is HTTP 403 with detail.error = "kyc_required".
Request body
| Field | Type | Description |
|---|---|---|
gateway required | string | Payment gateway: stripe | heleket | freekassa | onepaymentMin length: 1Max length: 64 |
amount_cents required | integer | Amount in integer cents |
idempotency_key | string, nullable | Optional client-supplied idempotency keyMax length: 255 |
currency | string | Currency code (USD).Min length: 3Max length: 3Default: "USD" |
order_metadata | object, nullable | Optional order details to attach to the payment. |
return_url | string, nullable | Relative path to return to after a canceled or failed payment (for example /wallet). Must start with /.Max length: 2048 |
success_url | string, nullable | Relative path to return to after a successful payment. Must start with /.Max length: 2048 |
save_card | boolean | Save the card for automatic top-ups (card payments via Stripe only).Default: false |
Request example Try it in the Dashboard
curl -X POST "https://papaproxy.net/account_new/api/v1/customer/wallet/deposit/init" \
-H "Authorization: Bearer $PAPAPROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount_cents": 5000, "gateway": "heleket", "idempotency_key": "deposit-2026-001"}'import os
import requests
resp = requests.post(
"https://papaproxy.net/account_new/api/v1/customer/wallet/deposit/init",
headers={"Authorization": f"Bearer {os.environ['PAPAPROXY_API_KEY']}"},
json={
"amount_cents": 5000,
"gateway": "heleket",
"idempotency_key": "deposit-2026-001"
},
timeout=30,
)
resp.raise_for_status()
print(resp.json())const resp = await fetch("https://papaproxy.net/account_new/api/v1/customer/wallet/deposit/init", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAPAPROXY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"amount_cents": 5000,
"gateway": "heleket",
"idempotency_key": "deposit-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/wallet/deposit/init');
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([
'amount_cents' => 5000,
'gateway' => 'heleket',
'idempotency_key' => 'deposit-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/wallet/deposit/init", strings.NewReader(`{"amount_cents": 5000, "gateway": "heleket", "idempotency_key": "deposit-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
200Top-up checkout details. · 8 fieldsExample response · JSON{ "payment_url": "https://pay.example.com/invoice/675388be-0c31-539b-8e81-0272df8d2f24", "our_order_id": "HLK-8F2A61C04D9E7B35", "amount_cents": 5000, "currency": "USD", "provider_tx_id": null, "checkout_kind": "redirect", "allowed_payment_methods": null, "paypal_remaining_cents": null }Field Type Description payment_urlrequiredstring our_order_idrequiredstring amount_centsrequiredinteger currencystring Currency code ( USD).Default:"USD"provider_tx_idstring, nullable checkout_kindstring Default: "redirect"allowed_payment_methodsarray of string, nullable Payment methods allowed for this top-up, when restricted (for example ["card"]). Null means no restriction.paypal_remaining_centsinteger, nullable Remaining PayPal limit for this account, in cents. Null when there is no limit. 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 scopewallet:deposit, or the payment method requires identity verification (detail.error = "kyc_required"). — error format422Validation 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" }
Download an invoice (PDF)
/api/v1/customer/invoices/{invoice_id}/pdfwallet:readDownload the PDF of one of your invoices.
Parameters
| Field | Type | Description |
|---|---|---|
invoice_id (path) required | string | ID of the invoice. |
Request example Try it in the Dashboard
curl -X GET "https://papaproxy.net/account_new/api/v1/customer/invoices/string/pdf" \ -H "Authorization: Bearer $PAPAPROXY_API_KEY"
import os
import requests
resp = requests.get(
"https://papaproxy.net/account_new/api/v1/customer/invoices/string/pdf",
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/invoices/string/pdf", {
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/invoices/string/pdf');
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/invoices/string/pdf", 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
200The invoice PDF.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 scopewallet:read.Example · JSON{ "detail": "API key is missing required scope: wallet:read" }404Invoice not found, or it doesn't belong to your account. — error format422Validation 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.